0
votes

I have an existing web application accessing a MySQL database. I'm porting this application to Symfony. The new application has to use the old database, as we cannot port the whole application at once, i.e. the old and the new application are accessing the same database and the applications are running simultaneously.

The old application had a simple CMS functionality which has to be ported:

There is a table pagewhich represents a page tree. Every page has a slug field. The URL path consists of those slugs representing the path identifying the page node, e.g. "/[parent-slug]/[child-slug]".

The page table also contains a content field. As I already mentioned, the CMS functionality is very simple, so the content is just rendered as page content inside a page layout. The page entry also specifies the page layout / template.

My problem is that I don't know how to set up the routing. In a normal Symfony application I'd know the URL patterns before, but in this case they are dynamic. Also routes cannot be cached, because they could be changed any time by the user. I wonder if I have to drop Symfony's routing completely and implement something on my own. But how?

Now I found Symfony CMF which tells a lot about the framework VS CMS routing conflict. So first, I thought this would be the right way. However the tutorials aim at building an entirely new application based on PHPRC. I wasn't able to derive the tutorial's concepts to my use case.

2
I edited and clarified the question. Hope that either the downvote will be removed or the down voter explains, what's the problem herefishbone

2 Answers

1
votes

since you run several URL rules on one symfony application, you will need to work with url prefixes. Either your cms should work with a prefix /cms/parent-slug/child-slug or all other controllers. Otherwise you are not able to differ which controller is meant when a dynamic request arrives.

You can try a workaround with a KernelControllerListener. He will catch up every request and then check if a cms page is requested. On the basis of the request you can set controller and action by yourself. Concept:

Create only one route with "/". Abandon oll other rules. Then create a Listener like this:

<?php

namespace AppBundle\Listener;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

/**
 * Class KernelControllerListener
 * @package ApiBundle\Listener
 */
class KernelControllerListener
{
    /**
     * @var CmsRepository
     */
    private $requestParser;

    /**
     * KernelControllerListener constructor.
     * @param CmsRepository $CmsRepository
     */
    public function __construct(CmsRepository $CmsRepository)
    {
        $this->CmsRepository = $CmsRepository;
    }

    /**
     * @param FilterControllerEvent $event
     */
    public function onKernelController(FilterControllerEvent $event){
        $request = $event->getRequest();
        //should be /parent-slug/children/slug or any other path
        $path = $request->getPathInfo();

        if($this->CmsRepository->getCmsControllerIfMatch($path)){
            //cms repository search in db for page with this path, otherwise return false
            $event->setController([AppBundle\CmsController::class, 'cmsAction']);
            return;
        }

        //repeat if clause for any other application part
    }
}

in services.yml:

app.controller_listener:
  class: AppBundle\Listener\KernelControllerListener
  arguments:
    - "@app.cms_repository"
  tags:
    - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Edit: catch all routes, see https://www.jverdeyen.be/symfony2/symfony-catch-all-route/

0
votes

The question is: Do you whant to migrate the data or not. For both question, the CMF can be an answer. If you wanna a simple dynamic router, you should have a look into the ChainRouter with an custom router definition: https://symfony.com/doc/current/cmf/bundles/routing/dynamic.html and https://symfony.com/doc/current/cmf/components/routing/chain.html If you wanna migrate the data, you can use fixture loaders, as we use in almost all of our examples.