I'm creating a simple CMS with Symfony 4. Where it it's possible to create pages. When creating a page a Doctrine EvenSubscriber is being called. This subscriber creates an PageRoute.
<?php
#src/Doctrine/EvenListener
/**
* PageRouteSubscriber
*/
namespace App\Doctrine\EventListener;
use App\Controller\PageController;
use App\Entity\Page;
use App\Entity\Route;
use Doctrine\Common\EventSubscriber;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
/**
* Class PageRouteSubscriber
* @package App\Doctrine\EventListener
*/
class PageRouteSubscriber implements EventSubscriber {
/**
* Returns an array of events this subscriber wants to listen to.
* @return array
*/
public function getSubscribedEvents() {
return [
'postPersist',
'postUpdate',
];
}
public function postPersist(LifecycleEventArgs $args){
$this->index($args);
}
public function postUpdate(LifecycleEventArgs $args){
$this->index($args);
}
public function index(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if($entity instanceof Page){
$route = new Route();
$route->setController(PageController::class);
$route->setRouteContentId(get_class($entity) . '#' . $entity->getId());
$route->setLocale($entity->getLocale());
$route->setSlug($entity->getSlug());
$entityManager = $args->getObjectManager();
$entityManager->persist($route);
$entityManager->flush();
}
}
}
So when the page is created there also is an route created. See images for database page and route examples.
I don't know this is the best way to store routes and pages in DB. Because they have both the same slug. I was thinking, only set slugs in route table. And per entity checking the unique slug based on all slugs in the route table (if this is possible?).
For routing: I don't now how to grep the routes and use them with Symfony Route Collection. Also is it possible to cache te routes just like Symfony does and created on big file called: srcDevDebugProjectContainerUrlGenerator
When i've got routes working i could create the frontend menu. Where a page menu item is coupled to an page. That page has an route. With this route the menu url could be created (is the the right way of thinking?).
Was solving something similiar in past in reality you need to take few steps. My need was to have routes without prefix (so no
/article/{slug}
, but just{slug}
and I have quite large number of them so DB looks more appropriate.route_id
as one of its properties. This will as well solve generating of routes, because you will fetch them from database via association/*
, I hooked to the kernel events and if this route was matched AND I found mu current request in my database - I have modified request to point to my database record controllerThis can be easily extended for example to track history of changes (Let's say you have Article First Article (slug:
/first-article
), then you rename it to Second Article (slug changed:/second-article
) here you can easily track this change and make proper redirect.I think you should avoid storing class names in your database. If you change your namespace then they worn't work anymore. And I don't see why you need a route table?
You can just do it similar to how most CMSs are doing it: just use
slug
from your page entity, and let symfony param converter handle the rest, or load it manually.You can get locale trough urls like this.
for your menu, you can just create a "menu" entity and add a relation to your page entity or hardcore a slug/url field in it.
You don't need to store routes in database, have a look at CMF router components, you can use the dynamic router to route any cms pages based on the slug (https://symfony.com/doc/master/cmf/bundles/routing/dynamic.html), then use chain router (https://symfony.com/doc/master/cmf/components/routing/chain.html) to use it in conjunction with the standard SF router.