如何将简单的 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.html
和
https://symfony.com/doc/current/cmf/components/routing/chain.html
如果你想迁移数据,你可以使用夹具加载器,就像我们在几乎所有示例中使用的那样。
我有一个现有的 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.html
和
https://symfony.com/doc/current/cmf/components/routing/chain.html
如果你想迁移数据,你可以使用夹具加载器,就像我们在几乎所有示例中使用的那样。