2013-07-14 42 views
3

我有一個當前的項目,必須顯示具有特定實體的兩個定義的頁面,什麼是非常容易與Symfony2管理和內容頁面在不同的佈局,什麼是 - 我想 - 少一點共同。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 

這將約束所有的第一級頁面:

/projects

/about

/contact

/our-project

怎麼樣,將與顯示的頁面,例如,像毛坯:

/our-project/health

事實上任何URL ...

/{slug-level1}/{slug-level2}/{slug-level3} etc.

導致網頁應該更改並從網站管理系統更新。

我想最好的辦法是有一個與數據庫字段比較{塞}路由器(實體屬性)

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的路由?

我能以這種方式綁定任何路線嗎?

編輯:我捆

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 } 

回答

3

我建議採取看看Symfony的CMF路由組件和CmfRoutingBundle的services.yml(以實現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 } 

現在,它應該可以工作,並且應該從數據庫加載路由並將它們與請求進行匹配。

+0

謝謝,我能理解更多的方式去做。你推薦我實現CMF RoutingBundle還是基於這個例子編寫我自己的? 你認爲有可能通過這種功能在模板和控制器的「Page」實體中添加一些字段來編寫一些特定的功能嗎? 還是更好,如果有任何頁面有特定的需求,我自己開發它作爲經典的Symfony2路線與定義的控制器和模板? –

+1

1)本示例基於組件,組件提供基礎知識,您需要創建實現(或使用該包的PHPCR ODM實現),但您始終需要該包; 2)你創建自己的路線實體,所以是的,這是可能的。只要你的路線實體擴展了Symfony路線,它就可以工作 –

+0

好吧,很高興知道。我今晚會測試它! –