Symfony 4从数据库路由

Symfony 4从数据库路由,symfony,doctrine-orm,routing,url-routing,symfony-cmf,Symfony,Doctrine Orm,Routing,Url Routing,Symfony Cmf,我正在用Symfony 4创建一个简单的CMS。可以创建页面的地方。创建页面时,将调用一个订阅服务器。此订阅者创建一个页面路由 <?php #src/Doctrine/EvenListener /** * PageRouteSubscriber */ namespace App\Doctrine\EventListener; use App\Controller\PageController; use App\Entity\Page; use App\Entity\Route

我正在用Symfony 4创建一个简单的CMS。可以创建页面的地方。创建页面时,将调用一个订阅服务器。此订阅者创建一个页面路由

<?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();
        }
    }
}

我认为您应该避免在数据库中存储类名。如果更改名称空间,则它们将不再工作。我不明白你为什么需要路线表

您可以像大多数CMS那样进行操作:只需从页面实体中使用
slug
,然后让symfony处理其余部分,或者手动加载

/**
 * @Route("/page/{slug}")
 * @ParamConverter("page")
 */
public function showAction(Page $page)
{
}
您可以通过URL获取区域设置


对于菜单,您只需创建一个“菜单”实体,并向页面实体添加一个关系,或在其中添加一个slug/url字段。

在解决类似问题时,实际上您需要采取一些步骤。我需要的是没有前缀的路由(所以没有
/article/{slug}
,而只是
{slug}
,我有很多这样的路由,所以DB看起来更合适

  • 存储路由-我有一个路由表,其中存储要匹配的url、目标控制器和要传递的参数(我不能在路由中包含ID)
  • 在您的案例中-文章将
    路由\u id
    作为其属性之一。这也将解决路由的生成问题,因为您将通过关联从数据库中获取它们
  • 创建新路由时,我会检查是否存在具有请求名称的路由,如果存在,我会在末尾添加递增编号
  • 然后,我在正常路由的末尾有一个常规路由来匹配所有内容
    /*
    ,我连接到内核事件,如果该路由匹配,并且我在数据库中找到了当前请求-我修改了请求以指向我的数据库记录控制器

这可以很容易地扩展,例如跟踪更改历史(假设您有第一篇文章(slug:
/First Article
),然后将其重命名为第二篇文章(slug changed:
/Second Article
)在这里,您可以轻松跟踪此更改并进行适当的重定向。

您不需要在数据库中存储路由,查看CMF路由器组件,您可以使用动态路由器根据slug()路由任何cms页面,然后使用链路由器()将其与标准SF路由器结合使用。

路由表可用于在slug更改时重写URL的功能。需要控制器将路由映射到控制器和操作。还可以阅读有关Symfony CMF路由和自定义路由加载器的内容。使用哪个更好?重新缓存路由:我假设您使用DynamicRouter该路由器的要点是路由存储在数据库中,并在运行时查询。每次编辑其中一个路由时都需要重新生成缓存文件,这将非常低效。如果您可以从内容生成路由而无需手动交互,您可以查看cmf路由包的路由提供程序-you c您可以从您的内容动态生成它们,而不需要在数据库中存储单独的路由。