2016-07-10 21 views
1

Ich gehe zu diesem Forum, weil ich keine gültige Lösung für mein Problem finden kann.Symfony2: dynamischer Routing-Parameter

Ich habe die Verwaltung einer Symfony2-Anwendung übernommen, die Aufträge, Rechnungen ... innerhalb eines Unternehmens verarbeitet und das Problem ist, dass es keine Archivierungsfunktionen darauf gibt. Also bat mich der Manager, der Anwendung die Funktionalität "Jahr für Jahr" hinzuzufügen (einfach die Daten je nach gewähltem Jahr anzuzeigen).

Also habe ich beschlossen, alle Anwendungsrouten um/{Jahr} /, Präfix, der das Jahr, den der Manager sehen will, und alle Dokumente sind datiert, ich muss nur Doctrine Anfragen für die Auswahl diese zu aktualisieren die dem gewählten Jahr entsprechen. Bis jetzt keine Probleme.

routes.yml

mes_routes: 
    resource: "mes_routes.yml" 
    prefix: /{year} 
    defaults: {'year': %current_year%} 

Damit habe ich eine Symfony-Erweiterung erstellt, die die 'CURRENT_YEAR' var standardmäßig in meiner Route Definition füllt, mit dem aktuellen Jahr, wenn kein Jahr vorgesehen ist.

MyAppExtension.php

class MyAppExtension extends Extension 
{ 
    public function load(array $configs, ContainerBuilder $container) 
    { 
     $configuration = new Configuration(); 
     $config = $this->processConfiguration($configuration, $configs); 

     $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 
     $loader->load('services.yml'); 

     // Fill parameter with the current year 
     $container->setParameter('current_year', date("Y")); 
    } 
} 

Als nächstes habe ich eine RouteListener geschaffen, die eine vorherige Route und seine Parameter in einer Sitzung var speichert, wenn ein Benutzer zeigt eine neue Seite (um eine gleiche anzuzeigen Seite aber mit einem anderen Jahr next)

LastRouteListener.php

class LastRouteListener 
{ 
    public function onKernelRequest(GetResponseEvent $event) 
    { 
     // Don't store subrequests 
     if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) { 
      return; 
     } 

     $request = $event->getRequest(); 
     $session = $request->getSession(); 

     $routeName = $request->get('_route'); 
     $routeParams = $request->get('_route_params'); 
     if ($routeName[0] == "_") { 
      return; 
     } 
     $routeData = ['name' => $routeName, 'params' => $routeParams]; 

     // Don't store the same route twice 
     $thisRoute = $session->get('this_route', []); 
     if ($thisRoute == $routeData) { 
      return; 
     } 
     $session->set('last_route', $thisRoute); 
     $session->set('this_route', $routeData); 
    } 
} 

services.yml

myapp.last_route_event_listener: 
    class: MyApp\EventListener\LastRouteListener 
    tags: 
     - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 30 } 

Und schließlich habe ich einen neuen Controller, die über ein Dropdown-Menü der Anwendung navbar, der der Benutzer gerade, aber mit einem anderen Jahr die aktuelle Seite zeigt hinzugefügt

ArchiveController.php

class ArchiveController extends Controller 
{ 
    public function switchYearAction(Request $request, $year) 
    { 
     $session = $request->getSession(); 
     $lastRoute = $session->get('last_route'); 
     $route = $lastRoute["name"]; 
     $routeParams = $lastRoute["params"]; 

     if (array_key_exists("year", $routeParams)) { 
      $routeParams["year"] = $year; 
      $session->set("current_year", $year); 
     } 

     return $this->redirect($this->generateUrl($route, $routeParams)); 
    } 
} 

hier angekommen, alles funktioniert. Wenn ein Benutzer ein anderes Datum auswählt, zeigt die Anwendung die gleiche Seite an, jedoch mit dem neuen Datum.

Allerdings, und da ist mein Problem, wenn, aus einem früheren Jahr, der Benutzer auf einen Link auf der Seite klickt, kommen wir zurück zum tatsächlichen Jahr. Ganz normal, weil Twig-Pfade in der Anwendung den Routing-Parameter 'Jahr' nicht füllen und der Router standardmäßig das aktuelle Jahr angibt.

Also, meine Frage ist: Wie kann ich das gewählte Jahr im Speicher behalten und es als Route Parameter verwenden?

Zuerst hatte ich gedacht, über die lokale var Einstellung ‚CURRENT_YEAR‘, wenn die Anwendung die switchYearAction() verwendet, aber Symfony gibt einen Fehler (‚Gefrorene Variable‘)

Als nächstes wird ein über die Verwendung gedacht hatte, Sitzungs-Var speichert das ausgewählte Jahr, aber ich kann nicht auf die Sitzung innerhalb meiner Erweiterung MyAppExtension zugreifen.

Es könnte eine dritte Lösung sein, die in Update besteht alle Twig Pfade und Controller-Umleitung(), aber es stellt eine viel Linie zu bearbeiten ...

Oder vielleicht mit einem routeEventListener ... aber ich don‘ Ich weiß, wie es weitergeht.

Vielen Dank im Voraus.

Antwort

0

Dank der Antwort von @chrisguitarguy: https://stackoverflow.com/a/13495302/1031898 habe ich einen Weg gefunden, um mein Problem zu lösen.

In der Tat könnte ich meinen routeListener verwenden, um die Aufgabe zu erledigen. Ich musste nur das Router Interface implementieren.

LastRouteListener.php (aktualisiert)

class LastRouteListener 
{ 
    private $router; 

    public function __construct(RouterInterface $router) 
    { 
     $this->router = $router; 
    } 

    public function onKernelRequest(GetResponseEvent $event) 
    { 
     // Don't store subrequests 
     if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) { 
      return; 
     } 

     $request = $event->getRequest(); 
     $session = $request->getSession(); 
     $context = $this->router->getContext(); 

     // If current_year exists in session, replace route parameter with it 
     if ($session->has('current_year')) { 
      $context->setParameter('year', $session->get('current_year')); 
     } 
     // Else, we set the current year by default 
     else { 
      $context->setParameter('year', date('Y')); 
     } 

     $routeName = $request->get('_route'); 
     $routeParams = $request->get('_route_params'); 
     if ($routeName[0] == "_") { 
      return; 
     } 
     $routeData = ['name' => $routeName, 'params' => $routeParams]; 

     // On ne sauvegarde pas la même route plusieurs fois 
     $thisRoute = $session->get('this_route', []); 
     if ($thisRoute == $routeData) { 
      return; 
     } 
     $session->set('last_route', $thisRoute); 
     $session->set('this_route', $routeData); 
    } 
} 

Vergessen Sie nicht das @router Argument in services.yml

myapp.last_route_event_listener: 
    class: MyApp\EventListener\LastRouteListener 
    tags: 
     - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 30 } 
    arguments: ['@router'] 

Und dann zu injizieren, keine Notwendigkeit 'CURRENT_YEAR' zu verwenden, Standardparameter in Route Config mehr.

routes.yml

mes_routes: 
    resource: "mes_routes.yml" 
    prefix: /{year} 

MyAppExtension.php

class MyAppExtension extends Extension 
{ 
    public function load(array $configs, ContainerBuilder $container) 
    { 
     $configuration = new Configuration(); 
     $config = $this->processConfiguration($configuration, $configs); 

     $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 
     $loader->load('services.yml'); 
} 

}

0

Sie können auf die Anwendungssitzung in Twig mit {{ app.session }} zugreifen. So etwas wie dies möglich ist:

{{ url('myapp.whatever', {year: app.session.get('current_year')}) }} 

Da Sie ein wenig Logik um die laufende Jahr Sachen haben (wenn es nicht gesetzt ist in der Sitzung Rückfall auf das laufende Jahr, usw.), ein twig extension, die ein funtion bereitstellt Holen Sie sich das aktuelle Jahr vielleicht einen besseren Weg zu gehen. Schnell, ungetestetes Beispiel:

<?php 
use Symfony\Component\HttpFoundation\Session\SessionInterface; 

class CurrentYearExtension extends \Twig_Extension 
{ 
    private $session; 
    private $defaultYear; 

    public function __construct(SessionInterface $session, $defaultYear) 
    { 
     $this->session = $session; 
     $this->defaultYear = $defaultYear; 
    } 

    public function getFunctions() 
    { 
     return [ 
      new \Twig_SimpleFunction('current_year', [$this, 'currentYear']), 
     ]; 
    } 

    public function currentYear() 
    { 
     return $this->session->get('current_year') ?: $this->defaultYear; 
    } 
} 

Dann fügen Sie es zu Ihrem Behälter und mit dem twig.extension Tag markiert.

<service id="myapp.currentyear_extension" class="CurrentYearExtension" public="false"> 
    <argument type="service" id="session" /> 
    <argument>%current_year%</argument> 
    <tag name="twig.extension" /> 
</service> 

Und es in Ihrer Route Generation verwenden:

{{ url('myapp.whatever', {year: current_year()}) }} 

Wenn Sie das aktuelle Jahr an anderen Orten als Zweig benötigen, dann ein wiederverwendbares und beide verwenden Objekt aus dem Zweig Erweiterung ziehen, dass mit die Erweiterung und anderswo.

+0

Vielen Dank für Ihre Antwort. Das Problem, alle Twig-Pfade und alle Weiterleitungs-URLs bearbeiten zu müssen, bleibt jedoch bei Ihrer Lösung bestehen. Ich bin auf der Suche nach einem Routenereignis-Listener, der den Routenaufruf abfangen und automatisch die Variable current_year mit der Sitzungsvariable oder standardmäßig mit dem aktuellen Jahr füllen kann. –

+0

Siehe diese Antwort @BenjaminLemoine http://StackOverflow.com/A/13495302/1031898 sollte sein, was Sie wollen. – chrisguitarguy

+0

Super! Diese Antwort ist genau das, was ich brauche. Vielen Dank ! Ich werde meinen aktualisierten Code in diesem Thread posten. –