2013-02-25 48 views
13

我试图创建动态路由,因为我创建了一个CMS,其中创建的每个页面都可以关联到路由。我使用这个链接中的示例 - http://php-and-symfony.matthiasnoback.nl/2012/01/symfony2-dynamically-add-routes/,并且所有工作都正常,但是路由被缓存,因此一条路由可以工作,但是除非我清除缓存,否则下一条路由将不起作用。是否有可能在此阶段删除路由缓存或者是否有其他替代方案?我不想删除每个页面加载的整个缓存目录,因为这是没有意义的。下面是示例代码:Symfony2动态路由 - 缓存问题

namespace Acme\RoutingBundle\Routing; 

use Symfony\Component\Config\Loader\LoaderInterface; 
use Symfony\Component\Config\Loader\LoaderResolver; 
use Symfony\Component\Routing\Route; 
use Symfony\Component\Routing\RouteCollection; 

class ExtraLoader implements LoaderInterface 
{ 
private $loaded = false; 

public function load($resource, $type = null) 
{ 
    if (true === $this->loaded) { 
     throw new \RuntimeException('Do not add this loader twice'); 
    } 

    $routes = new RouteCollection(); 

    $pattern = '/extra'; 
    $defaults = array(
     '_controller' => 'AcmeRoutingBundle:Demo:extraRoute', 
    ); 

    $route = new Route($pattern, $defaults); 
    $routes->add('extraRoute', $route); 

    return $routes; 
} 

public function supports($resource, $type = null) 
{ 
    return 'extra' === $type; 
} 

public function getResolver() 
{ 
} 

public function setResolver(LoaderResolver $resolver) 
{ 
    // irrelevant to us, since we don't need a resolver 
} 
} 

然后我的ExtraLoader订立业务:

<!-- in /src/Acme/RoutingBundle/Resources/config/services.xml --> 
<?xml version="1.0" ?> 
<container xmlns="http://symfony.com/schema/dic/services" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://symfony.com/schema/dic/services  http://symfony.com/schema/dic/services/services-1.0.xsd"> 

    <services> 
     <service id="acme.routing_loader" class="Acme\RoutingBundle\Routing\ExtraLoader"> 
      <tag name="routing.loader"></tag> 
     </service> 
    </services> 
</container> 

我们需要的最后一件事,是在/ app /配置/路由一些额外的线条。阳明:

AcmeRoutingBundle: 
    resource: . 
    type: extra 
+0

1+有趣的问题 – 2014-11-08 14:44:20

回答

0

我的研究和尝试了一下,我发现,你可以删除以下文件:

用于开发:

/app/cache/dev/appDevUrlGenerator.php 
/app/cache/dev/appDevUrlGenerator.php.meta 
/app/cache/dev/appDevUrlMatcher.php 
/app/cache/dev/appDevUrlMatcher.php.meta 

为PROD:

/app/cache/prod/appProdUrlGenerator.php 
/app/cache/prod/appProdUrlMatcher.php 

只有一个这样minior缺点。我使用的是当前的路由,以确定是否菜单项处于活动状态:

{% set currentPath = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %} 

... 

<li{% if currentPath == path('mybundle_default_index') %} class="active"{% endif %}> 

在这种情况下app.request.attributes.get('_route')仍缓存为可能不存在了的路线。我不知道这是否只涉及枝条缓存或其他部分。

另外我不明白为什么你将不得不删除每个页面加载整个缓存?添加新路由时只需清除缓存。

0

我在我自己的CMS中解决了这个问题。

起初我推翻基Router类:

parameters: 
    router.class: Name\Of\Your\Router 

和扩展它:

use Symfony\Bundle\FrameworkBundle\Routing\Router as BaseRouter; 

class Router extends BaseRouter 
{ 
    public function clearCache($cache_dir, $environment, $warm_up) 
    { 
     $cache_dir .= '/'. $environment; 
     $environment = ucfirst($environment); 

     @unlink($cache_dir .'/app'. $environment .'UrlMatcher.php'); 
     @unlink($cache_dir .'/app'. $environment .'UrlGenerator.php'); 

     if ($warm_up) { 
      $this->matcher = null; 
      $this->generator = null; 

      $this->warmUp($cache_dir); 
     } 
    } 
} 

其次我建立了一个服务CacheService

cache_service: 
    class: Name\Of\Your\CacheService 
    arguments: 
     - @router 
     - %kernel.environment% 
     - %kernel.root_dir%/cache 

和增加了以下方法:

public function clearCache($environment = null) 
{ 
    if (null === $environment) { 
     $environment = $this->environment; 
    } 

    $this->router->clearCache($this->cache_dir, $environment, $this->environment == $environment); 
} 

因此,现在我可以调用此方法,当我需要清除当前或特定环境的缓存。

0

这是非常低效的,因为每条新路线都必须清除缓存,所以您将被hdd/ssd绑定到无用的清除缓存。 另一种方法是在控制器中创建一个新方法,该方法接受GET上的动态页面并显示树枝中的动态内容。

您可以创建一个服务来渲染动态页面,这将简化事情。

0

您是否从symfony-cmf项目中查看了DynamicRouter?我认为这符合您的需求,并且正是为您的用例创建的。

你目前的实现有一些你应该知道的真正问题。首先,您必须清除路由缓存,为您创建/编辑/删除的每个路由。这无缘无故地导致竞赛状况和记忆高峰。

symfony的默认实现是处理静态路由,而不是动态路由。