2013-02-25 11 views
13

Sto provando a creare percorsi dinamici poiché ho creato un CMS in cui ogni pagina creata può essere associata a un percorso. Sto usando l'esempio da questo link - http://php-and-symfony.matthiasnoback.nl/2012/01/symfony2-dynamically-add-routes/ e tutto funziona bene, tuttavia il routing è memorizzato nella cache, quindi un percorso funzionerà ma il prossimo non lo farà a meno che non svuoti la cache. È possibile rimuovere solo la cache di routing in questa fase o esiste un'altra alternativa? Non voglio rimuovere l'intera directory della cache su ogni caricamento della pagina poiché ciò non avrebbe senso. Ecco il codice di esempio:Routing dinamico Symfony2 - problema di caching

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

Poi ho fatto un servizio per l'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> 

L'ultima cosa di cui abbiamo bisogno, è poche righe extra in/app/config/routing. yml:

AcmeRoutingBundle: 
    resource: . 
    type: extra 
+0

1+ per la domanda interessante –

risposta

0

ho studiato e provato un po 'e ho scoperto che si può solo eliminare i seguenti file:

per dev:

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

per prod:

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

C'è un solo Minior aspetto negativo di questo. Sto usando il percorso corrente per determinare se una voce di menu è attivo o meno:

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

... 

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

In questo caso app.request.attributes.get('_route') è ancora nella cache come un percorso che potrebbe non esistere più. Non so ancora se questo riguarda solo la cache di twig o altre parti.

Inoltre, non capisco perché si debba cancellare l'intera cache su ogni pagina caricata? Devi solo svuotare la cache quando vengono aggiunti nuovi percorsi.

0

Ho risolto questo problema nel mio CMS.

All'inizio mi escludeva la base Router classe:

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

estendendolo:

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); 
     } 
    } 
} 

secondo luogo ho creato un servizio CacheService:

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

e aggiunto il seguente metodo :

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

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

Così ora posso chiamare questo metodo quando ho bisogno di svuotare la cache per l'ambiente corrente o specifico.

0

Questo è abbastanza inefficiente, perché con ogni nuovo percorso è necessario svuotare la cache, quindi sarai vincolato da hdd/ssd con cache chiara inutile. L'alternativa è creare un nuovo metodo nel controller che accetta una pagina dinamica su GET e mostrare il contenuto dinamico in twig.

È possibile creare un servizio per il rendering delle pagine dinamiche, che semplificherà le cose.

0

Avete guardato il DynamicRouter dal progetto symfony-cmf? Penso che questo si adatta alle tue esigenze ed è esattamente creato per il tuo caso d'uso.

L'attuale implementazione ha alcuni problemi che dovresti sapere. Prima di tutto, è necessario cancellare la cache di routing, per ogni percorso che si crea/modifica/cancella. Ciò porta a condizioni di gara e picchi di memoria senza motivo.

L'implementazione predefinita di symfony consiste nel gestire route statiche, non dinamiche.

Problemi correlati