2012-10-18 5 views
6

Provo a caricare un semplice file modello base.html.twig che è stato spostato dalla posizione predefinita di symfony app/Resources/views/ nella posizione personalizzata theme/.Symfony2: Twig: file di modello predefinito in posizione personalizzata

Il file modello contiene:

<!DOCTYPE html> 
    <html> 
    <head> 
    ... 
    </head> 
    <body> 
     {% block body %}{% endblock %} 
    </body> 
    </html> 

Estendere il file del modello di cui sopra dal controller Acme\Core\CoreBundle\Controller utilizzando il modello specifico controller

{% extends '::base.html.twig' %} 
    {% block body %} 
     Hello world! 
    {% endblock %} 

porta a dire un errore Unable to find template "::base.html.twig" in "AcmeCoreCoreBundle:Default:index.html.twig"..

Come è possibile dire a symfony dove trovare i file modello nello spazio globale?

Grazie in anticipo.

+0

potrebbe essere fatto con la \ Twig_Loader_Filesystem :: addpath ($ path, $ namespace = '__main __') '' (vedi [Fonte] (https : //github.com/fabpot/Twig/blob/master/lib/Twig/Loader/Filesystem.php)) ma non sono sicuro da dove lo chiamereste. Ho anche dato un'occhiata alla configurazione di TwigBundle, ma non sembra che ci sia un'opzione per questo lì. Se qualcuno su cui approfondire ulteriormente, potrebbe essere d'aiuto. –

risposta

7

Grazie al suggerimento di Adam, sono in grado di rispondere alla domanda da solo. Quindi voglio fornire la mia risposta se qualcuno è interessato a.

Il AcmeDemoBundle fornisce un'estensione di ramoscello (classe Acme\DemoBundle\Twig\Extension\DemoExtension) che è possibile utilizzare. Cambiare il costruttore in

public function __construct(FilesystemLoader $loader) 
    { 
    $this->loader = $loader; 
    $this->loader->addPath('path/to/your/directory'); 
    } 

Ora dire a symfony di registrare l'estensione di ramoscello. Modificare il file di config.yml (ad esempio app/config/config.yml) e aggiungere

services: 
    demo.twig.extension 
     class: Acme\DemoBundle\Twig\Extension\DemoExtension 
     tags: 
     - { name: twig.extension } 
     arguments: 
     - @Twig.loader 

Ultimo ma non meno importante modificare il file ramoscello estendere e rimuovere il :: dal namespace del vostro modello predefinito: {% extends 'base.html.twig' %}.

+1

Felice del mio suggerimento ti ha indirizzato nella giusta direzione, e grazie per la condivisione. Questa soluzione è più elegante di quella che inizialmente pensavo di fornire. –

1

da un'azione è possibile ottenere il 'twig.loader'-service dal (servizio) -container:

$this->get('twig.loader')->addPath('path/to/your/directory'); 

E quindi è possibile utilizzare questo percorso nel modello.

@besta l'ha fatto con un'estensione di ramoscello, iniettando il caricatore di ramoscelli nel costruttore. Ma nell'estensione di ramoscello è possibile utilizzare l'ambiente:

class YourTwigExtension extends \Twig_Extension { 
... 
    public function initRuntime(\Twig_Environment $environment) { 
     $this->environment = $environment; 
     $this->environment->getLoader()->addPath(__DIR__ . '/Resources/views'); 
    } 
... 
} 
5

Sono riuscito a trovare un'altra soluzione a questo che è molto più veloce da implementare. Ho provato prima la risposta accettata su questa domanda, ma avevo ancora problemi di percorso.

Poco prima il mio rendere chiamare il modello ho aggiunto il percorso del contenitore twig.loader in questo modo:

$this->container->get('twig.loader')->addPath('../../../../theme/', $namespace = '__main__'); 

Ora ramoscello modelli saranno resi da una directory chiamata 'tema' nella cartella principale. Ho trovato questa soluzione da Fabien Pontencier stesso (il creatore di Symfony e Twig) su una risposta a un bug di ramoscello qui: https://github.com/symfony/symfony/issues/1912

+0

cercando esattamente questo! – Subdigger

11

C'è una funzione nativa per fare esattamente quello che vuoi in un modo carino. È possibile aggiungere uno spazio dei nomi di ramoscello alla configurazione di ramoscello in app/config.yml come questo:

twig: 
    # ... 
    paths: 
     "%kernel.root_dir%/../vendor/acme/foo-bar/templates": foo_bar 

Questo crea un alias alla cartella vendor/acme/foo-bar/templates e quindi si può utilizzare per rendere i modelli sia da controllori:

return $this->render(
    '@foo_bar/template.html.twig', 
    $data 
); 

o da altri modelli ramoscello

{% include '@foo_bar/template.html.twig' %} 

Fonte: libro di cucina ufficiale http://symfony.com/doc/current/cookbook/templating/namespaced_paths.html

1

Supponendo che lo si voglia fare globalmente, questo tipo di cose deve essere fatto in un compiler pass.

Sarebbe molto più pulito ed efficiente in questo modo:

<?php 

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 
use Symfony\Component\DependencyInjection\ContainerBuilder; 

class CustomCompilerPass implements CompilerPassInterface 
{ 
    public function process(ContainerBuilder $container) 
    { 
     $loader = $container->getDefinition('twig.loader'); 
     $loader->addMethodCall('addPath', array('/path/to/views')); 
    } 
} 
+0

Questo non funziona, ritorna con ''Hai richiesto un servizio inesistente" twig.loader "'. Devi usare 'twig.loader.filesystem' – sschueller