我有一个当前项目,必须显示具有特定实体的已定义页面,使用Symfony2非常容易管理的内容,以及不同布局上的内容页面,我猜 - 有点不太常见。
我在尝试构建路由系统时遇到了麻烦。
例如,如果我必须显示包含某些新闻的页面, 我想用一条新路线更新我的捆绑包的路由器,如:
my_bundle_news_page:
pattern: /news
defaults:
_controller: MyBundle:NewsController:indexAction
但是如何管理一个可以在多个级别上拥有完全自定义URL的动态路由器?
让我们想象一下,我有一个“页面”实体,这是一个选择性“父子关系”的自我引用。 我不认为我可以使用任何配置YAML文件进行此特定路由?!
my_bundle_custom_page:
pattern: /{slug}
defaults:
_controller: MyBundle:PageController:showAction
这将绑定所有第一级页面:
/项目
/约
/接触
/我们的项目
如果要显示的页面怎么样?例如:
/我们的项目/健康
实际上任何网址......
/ {slug-level1} / {slug-level2} / {slug-level3}等。
因为页面应该更改并从网站管理更新。
我想最好的方法是使用路由器将{slug}与数据库字段(实体属性)进行比较
我在the Symfony-CMF doc中读到可以基于路由提供者编写服务:
namespace MyBundle\Routing;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route as SymfonyRoute;
use MyBundle\Entity\PageRepository;
class RouteProvider extends PageRepository {
public function findPageBySlug($slug)
{
// Find a page by slug property
$page = $this->findOneBySlug($slug);
if (!$page) {
// Maybe any custom Exception
throw $this->createNotFoundException('The page you are looking for does not exists.');
}
$pattern = $page->getUrl(); // e.g. "/first-level/second-level/third-level"
$collection = new RouteCollection();
// create a new Route and set our page as a default
// (so that we can retrieve it from the request)
$route = new SymfonyRoute($pattern, array(
'page' => $page,
));
// add the route to the RouteCollection using a unique ID as the key.
$collection->add('page_'.uniqid(), $route);
return $collection;
}
}
但是如何将其设置为服务?有一些要求吗? 这种事情怎么可能有效,它是否在调用请求时为RouteCollection添加路由?
我能以这种方式绑定任何路线吗?
编辑:我的捆绑的services.yml
parameters:
cmf_routing.matcher.dummy_collection.class: Symfony\Component\Routing\RouteCollection
cmf_routing.matcher.dummy_context.class: Symfony\Component\Routing\RequestContext
cmf_routing.generator.class: Symfony\Cmf\Bundle\RoutingBundle\Routing\ContentAwareGenerator
cmf_routing.nested_matcher.class: Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher
cmf_routing.url_matcher.class: Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher
fsbcms.chain_router.class: Symfony\Cmf\Component\Routing\ChainRouter
fsbcms.route_provider.class: FSB\CMSBundle\Routing\RouteProvider
fsbcms.dynamic_router.class: Symfony\Cmf\Component\Routing\DynamicRouter
fsbcms.route_entity.class: null
services:
fsbcms.router:
class: %fsbcms.chain_router.class%
arguments:
- "@logger"
calls:
- [setContext, ["router.request_context"]]
fsbcms.route_provider:
class: "%fsbcms.route_provider.class%"
arguments:
- "@doctrine"
cmf_routing.matcher.dummy_collection:
class: "%cmf_routing.matcher.dummy_collection.class%"
public: "false"
cmf_routing.matcher.dummy_context:
class: "%cmf_routing.matcher.dummy_context.class%"
public: false
cmf_routing.generator:
class: "%cmf_routing.generator.class%"
arguments:
- "@fsbcms.route_provider"
- "@logger"
calls:
- [setContainer, ["service_container"]]
- [setContentRepository, ["cmf_routing.content_repository"]]
cmf_routing.url_matcher:
class: "%cmf_routing.url_matcher.class%"
arguments: ["@cmf_routing.matcher.dummy_collection", "@cmf_routing.matcher.dummy_context"]
cmf_routing.nested_matcher:
class: "%cmf_routing.nested_matcher.class%"
arguments: ["@fsbcms.route_provider"]
calls:
- [setFinalMatcher, ["cmf_routing.url_matcher"]]
fsbcms.dynamic_router:
class: "%fsbcms.dynamic_router.class%"
arguments:
- "@router.request_context"
- "@cmf_routing.nested_matcher"
- "@cmf_routing.generator"
tags:
- { name: router, priority: 300 }
答案 0 :(得分:3)
我建议看看Symfony CMF路由组件和CmfRoutingBundle(在symfony中实现组件)。
路由组件使用链路由器,这与此问题无关,但很高兴知道。链路由器链接在路由器队列上。该组件提供了一个使用NestedMatcher的DynamicRouter。这正是你想要的。
NestedMatcher使用Route提供程序从动态源(例如数据库)获取路由。您正在问题中显示路线提供者的示例。
此外,它使用FinalMatcher来匹配路线。你可以传递一个Symfony\Cmf\Component\Routing\NestedMatcher\UrlMatcher
的实例,因为你做的事情并不太困难。
查看docs of the RoutingBundle以了解如何激活链路由器,然后创建一个路由提供程序来加载路由,提供服务:
acme_routing.route_provider:
class: Acme\RoutingBundle\Provider\DoctrineOrmProvider
arguments: ["@doctrine"]
现在,您可以创建一个NestedMatcher服务:
acme_routing.url_matcher:
class: Symfony\Cmf\Component\Routing\NestedMatcher\UrlMatcher
arguments: ["@cmf_routing.matcher.dummy_collection", "@cmf_routing.matcher.dummy_context"]
acme_routing.nested_matcher:
class: Symfony\Cmf\Component\Routing\NestedMatcher
arguments: ["@acme_routing.route_provider"]
calls:
- [setFinalMatcher, ["acme_routing.url_matcher"]]
现在,注册DynamicRouter并将其放入链中:
acme_routing.dynamic_router:
class: Symfony\Cmf\Component\Routing\DynamicRouter
arguments:
- "@router.request_context"
- "@acme_routing.nested_matcher"
- "@cmf_routing.generator"
tags:
- { name: router, priority: 300 }
现在,它应该工作,应该从数据库加载路由并根据请求匹配它们。