2
votes

Tried to find a solution, but I got always stuck a the docs or at answers include other bundles. In the documentation of the dynamic router you can find the hint:

"Of course you can also have several parameters, as with normal Symfony routes. The semantics and rules for patterns, defaults and requirements are exactly the same as in core routes."

Thats it.

...

/foo/{id}/bar

I tried (seems not) everything to get it done.

Same for all tries:

I tried it to apply a variable pattern and a child route.

use Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route as PhpcrRoute;

$dm = $this->get('cmf_routing.route_provider');

$route = new PhpcrRoute();
$route->setPosition( $dm->find( null, '/cms/routes' ), 'foo' );
$route->setVariablePattern('/{id}');
$dm->persist( $route );

$child = new PhpcrRoute();
$child->setPosition( $route, 'bar' );
$dm->persist( $child );

$dm->flush();

With or without default value and requirement only '/foo/bar' and '/foo/*' return matches, but '/foo/1/bar' prompts me with a 'No route found for "GET /foo/1/bar"'.

...

Just now I nearly got it done.

use Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route as PhpcrRoute;

$dm = $this->get('cmf_routing.route_provider');

$route = new PhpcrRoute();
$route->setPosition( $dm->find( null, '/cms/routes' ), 'example_route' );
$dm->persist( $route );

$route->setPrefix( '/cms/routes/example_route' );
$route->setPath( '/foo/{id}/bar' );

$dm->flush();

If prefix is '/cms/routes' and name is 'foo' everything works fine. But now that I got this far, assigning a speaking name would round it up.

Thanks in advice!

1
I would be thankful for and tutorial, that shows some use cases, as well. I have concerns, that route names like 'my_example_route' would ruin the advantages of the PHPCR approach. Then how would You persist a route like '/foo/{id}/bar'?Potsdamer Schnitzel

1 Answers

1
votes

You got quite close to the solution, actually!

When using PHPCR-ODM, the route document id is its path in the repository. PHPCR stores all content in a tree, so every document needs to be in a specific place in the tree. We then use the prefix to get a URL to match. If the prefix is configured as /cms/routes and the request is for /foo, the router looks in /cms/routes/foo. To allow parameters, you can use setVariablePattern as you correctly assumed. For the use case of /foo/{id}/bar, you need to do setVariablePattern('/{id}/bar'). You could also have setVariablePattern('/{context}/{id}') (this is what the doc paragraph you quoted meant - i will look into adding an example there as its indeed not helpful to say "you can do this" but not explain how to).

Calling setPath is not recommended as its just less explicit - but as you noticed, it would get the job done. See the phpdoc and implementation of Model\Route::setPattern:

/**
 * It is recommended to use setVariablePattern to just set the part after
 * the static part. If you use this method, it will ensure that the
 * static part is not changed and only change the variable part.
 *
 * When using PHPCR-ODM, make sure to persist the route before calling this
 * to have the id field initialized.
 */
public function setPath($pattern)
{
    $len = strlen($this->getStaticPrefix());

    if (strncmp($this->getStaticPrefix(), $pattern, $len)) {
        throw new \InvalidArgumentException('You can not set a pattern for the route that does not start with its current static prefix. First update the static prefix or directly use setVariablePattern.');
    }

    return $this->setVariablePattern(substr($pattern, $len));
}

About explicit names: The repository path is also the name of the route, in the example /cms/routes/foo. But it is not a good idea to use a route name of a dynamic route in your code, as those routes are supposed to be editable (and deletable) by an admin. If you have a route that exists for sure and is at a specific path, use the configured symfony routes (the routing.yml file). If its dynamic routes, have a look at the CMF Resource Bundle. It allows to define a role for a document and a way to look up documents by role. If you have a route with a specific role that you want to link to from your controller / template, this is the way to go. If you have a content document that is linked with a route document and have that content document available, your third and best option is to generate the URL from the content document. The CMF dynamic router can do that, just use the content object where you normally specify the route name.