0
votes

I'm currently researching Symfony CMF and PHPCR for a project I recently started. What I'm currently trying to figure out is how to create a Route and save it into the database. As far as I understand, I must use Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route and persist the element into the database. This works fine, but automatically generates a route path, which is not what I want. What I need to do is generate a custom route which links to a specific controller. Here is my code:

$em = $this->get('doctrine_phpcr.odm.document_manager');
$parent = $em->find(null, '/cms/routes');

$route = new \Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route();
$route->setParentDocument($parent);
$route->setName('my_route_name');
$route->setDefault('_controller', 'AppBaseBundle:Frontend/Users:index');

$em->persist($route);
$em->flush();

If i execute this code, the generated route will be /cms/routes/my_route_name. From what I can see, you could use $route->setPath('/testing');, but that generates the following exception:

Can not determine the prefix. Either this is a new, unpersisted document or the listener that calls setPrefix is not set up correctly.

Does anybody have any ideas how to solve this?

2

2 Answers

1
votes

In PHPCR, every document has a path where it is store. If you are familiar with doctrine ORM, the path has the role of the ID. The difference with ORM is that all documents (regardless of their type) live in the same tree. This is great, because your route can reference just anything, it is not limited to specific document types. But we need to create some structure with the paths. This is why we have the prefix concept. All routes are placed under a prefix (/cms/routes by default). That part of the document path is removed for the URL path. So repository path /cms/route/testing is the url domain.com/testing.

About your sample code: Usually, you want to configure the controller either by class of the content document or by route "type" attribute to avoid storing a controller name into your database to allow for future refactoring. A lot of this is explained in the [routing chapter of the CMF documentation][1] but the prefix is only used there, not explicitly explained. We need to improve the documentation there.

[1] http://symfony.com/doc/master/cmf/book/routing.html

0
votes

I managed to find a way to overcome this issue. Because in my project I also have the RouteAutoBundle, I created a class which extends \Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route. Inside that class I added:

/**
 * @PHPCR\Document(referenceable=true)
 */
class MenuRoute extends Route
{

    protected $url;

    /**
     * Get $this->url
     *
     * @return mixed
     */
    public function getUrl() {
        return $this->url;
    }

    /**
     * Set $this->url
     *
     * @param mixed $url
     */
    public function setUrl($url) {
        $this->url = $url;
    }
}

After that I added this to cmf_routing_auto.yml:

App\MenuBundle\Document\MenuRoute:
    uri_schema: /{getUrl}
    token_providers:
        getUrl: [content_method, { method: getUrl }]

So now one would just create an instance of MenuRoute (just like when using Route) and call the method setUrl($your_url) passing the desired url.

If anybody finds a better way, I'm opened to suggestions.