如何将简单的 CMS 功能添加到现有的 Symfony 应用程序

How can I add simple CMS functionality to existing Symfony application

我有一个现有的 Web 应用程序正在访问 MySQL 数据库。我正在将此应用程序移植到 Symfony。新应用程序必须使用旧数据库,因为我们不能一次移植整个应用程序,即旧应用程序和新应用程序正在访问同一个数据库,并且应用程序同时 运行。

旧应用程序有一个简单的 CMS 功能,必须移植:

有一个table page代表一个页面树。每个页面都有一个 slug 字段。 URL 路径由代表标识页面节点的路径的 slug 组成,例如"/[parent-slug]/[child-slug]".

页面 table 还包含一个 content 字段。正如我已经提到的,CMS 功能非常简单,因此内容只是呈现为页面布局内的页面内容。页面条目还指定了页面布局/模板。

我的问题是我不知道如何设置路由。在正常的 Symfony 应用程序中,我以前知道 URL 模式,但在这种情况下它们是动态的。路由也不能被缓存,因为用户可以随时更改它们。我想知道我是否必须完全放弃 Symfony 的路由并自己实现一些东西。但是怎么办?

现在我发现了 Symfony CMF,它讲述了很多关于框架 VS CMS 路由冲突的信息。所以首先,我认为这是正确的方法。然而,这些教程旨在构建一个基于 PHPRC 的全新应用程序。我无法将教程的概念派生到我的用例中。

因为您在一个 symfony 应用程序上 运行 多个 URL 规则,您将需要使用 url 前缀。您的 cms 应该使用前缀 /cms/parent-slug/child-slug 或所有其他控制器。否则,当动态请求到达时,您无法区分哪个控制器。

您可以尝试使用 KernelControllerListener 的解决方法。他将赶上每个请求,然后检查是否请求了 cms 页面。您可以根据请求自行设置控制器和动作。概念:

只创建一个带有“/”的路由。放弃所有其他规则。然后像这样创建一个监听器:

<?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
    }
}

在services.yml中:

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

编辑:捕捉所有路线,参见https://www.jverdeyen.be/symfony2/symfony-catch-all-route/

问题是:你要不要迁移数据。对于这两个问题,CMF 都可以作为答案。如果你想要一个简单的动态路由器,你应该看看 ChainRouter 自定义路由器定义: https://symfony.com/doc/current/cmf/bundles/routing/dynamic.htmlhttps://symfony.com/doc/current/cmf/components/routing/chain.html 如果你想迁移数据,你可以使用夹具加载器,就像我们在几乎所有示例中使用的那样。