2012-09-10 47 views
5

Mi aplicación consiste en múltiples paquetes que se nombran como HelloWorldAdminBundle, HelloWorldUserBundle, HelloWorldDemoBundle. Esto da como resultado una raíz de configuración como hello_world_demo, hello_world_user y hello_world_demo. Quiero que las raíces de configuración de mis paquetes sean helloworld_demo, helloworld_user y helloworld_admin. En ese punto debo mencionar que esto no es realmente un problema técnico, sino más bien un problema estético.Symfony2: configuración personalizada root

he tratado de poner en práctica una extensión personalizada y registrarlo en el paquete:

public function build(ContainerBuilder $container) 
{ 
    parent::build($container); 

    $container->registerExtension(new HelloworldDemoExtension()); 
} 

La extensión:

... 
class HelloworldDemoExtension 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'); 
    } 

    public function getAlias() 
    { 
     return 'hello_world_demo'; 
    } 
} 

y finalmente la configuración:

... 
class Configuration implements ConfigurationInterface 
{ 
    public function getConfigTreeBuilder() 
    { 
     $treeBuilder = new TreeBuilder(); 
     $rootNode = $treeBuilder->root('helloworld_demo'); 
     ... 
     return $treeBuilder; 
    } 
} 

Seguí las instrucciones How to expose a Semantic Configuration for a Bundle, sin embargo cuando agrego un artículo a config.yml me sale el siguiente error:

There is no extension able to load the configuration for "helloworld_demo" 

Respuesta

3

he encontrado la solución a mi problema. Funciona exactamente como lo describí en la pregunta, sin embargo, existe una extensión predeterminada (con el nombre del paquete) .

ahora tengo un vacío, pero la extensión existente denominado HelloWorldDemoExtension (con el alias hello_world_demo y, además, he añadido DemoExtension (con el alias helloworld_demo) y funciona.

+0

¡¡Genial !! Me alegra que lo hayas encontrado –

0

Como documentation dice:

When creating an extension, follow these simple conventions:

  • The extension must be stored in the DependencyInjection sub-namespace;
  • The extension must be named after the bundle name and suffixed with Extension (AcmeHelloExtension for AcmeHelloBundle);
  • The extension should provide an XSD schema.

No estoy realmente saber si necesita definir propios build y getAlias métodos. Si lo necesita, el método getAlias debería devolver este mismo valor como define en el nodo raíz. Lo que debe ser helloworld_demo probablemente en lugar de hello_world_demo

+0

No. Por lo que he entendido la documentación, el método 'getAlias' es utilizado por Symfony para relacionar la extensión con el paquete. Como el nombre de la extensión ya no proporciona ninguna sugerencia del paquete, se utiliza el alias. ** Editar: ** Esto se explica en la parte inferior de la página de documentación de Configuración semántica: http://symfony.com/doc/2.0/cookbook/bundles/extension.html#extension-conventions –

+0

Y en cuanto a la primera parte. Soy consciente de estas convenciones y quiero romperlas por el bien de la estética. –

0

Del libro "En este caso, la clase de extensión también debe implementar un método getAlias ​​() y devolver un alias exclusivo lleva el nombre del paquete (por ejemplo acme_hello). Esto es necesario porque el nombre de clase no sigue los estándares al terminar en Extensión. Además, el método load() de su extensión solo se invocará si el usuario especifica el alias acme_hello en al menos un archivo de configuración. "

Entonces , este alias ES el nombre de la configuración raíz. Cambiar el código para

public function getAlias() 
{ 
    return 'helloworld_demo'; 
} 

y debería funcionar

+0

'[LogicException] El alias de extensión para la extensión predeterminada de un paquete debe ser la versión subrayada del nombre del paquete (" hello_world_demo "en lugar de" helloworld_demo ")' –

+0

mmm ... así que supongo que la única solución que queda es cambiar el nombre de sus paquetes a HelloworldDemoBundle, etc ... –

3

que resolvieron este reemplazando Symfony\Component\HttpKernel\Bundle\Bundle#getContainerExtension().

Este método crea y devuelve automáticamente una instancia de ExtensionInterface, y también comprueba si el alias de la extensión (que puede especificar implementando getAlias en su clase de extensión, según la respuesta Carlos Granados') cumple con la convención de nomenclatura.

Así que anulando el método getContainerExtension() en su clase de paquete, y simplemente devuelve una instancia de su clase de extensión, puede omitir el cheque y el LogicException.

Esto es lo que su clase de paquete se vería así:

<?php 

namespace HelloWorld\Bundle\UserBundle; 

use HelloWorld\Bundle\UserBundle\DependencyInjection\HelloWorldUserExtension; 
use Symfony\Component\HttpKernel\Bundle\Bundle; 

class HelloWorldUserBundle extends Bundle 
{ 
    public function getContainerExtension() 
    { 
     if (null === $this->extension) { 
      $this->extension = new HelloWorldUserExtension(); 
     } 

     return $this->extension; 
    } 
} 

Y, por supuesto, no se olvide de añadir esto a su clase de extensión:

/** 
* The extension alias 
* 
* @return string 
*/ 
public function getAlias() 
{ 
    return 'helloworld_user'; 
} 

Advertencia: I No estoy seguro de por qué esta verificación se agregó al método getContainerExtension(). Puede haber un motivo muy válido y es posible que encuentre problemas al seguir los pasos anteriores. Sin embargo, no he tenido ningún problema hasta ahora.

Editar: Ver también: Symfony2: Some things I don't like about Bundles. Este artículo de blog viene con la misma solución que mi respuesta. También, vea this pull request para la documentación de Symfony, que también describe el mismo método. Esto me hace creer que es seguro hacerlo sin tener que esperar efectos secundarios.

+0

Esto es feo, pero supongo que si realmente quieres romper las convenciones de Symfony, ese es el camino a seguir. La manera más limpia debe ser nombrar su paquete correctamente de todos modos :-). –

+1

@AlainTiemblo no siempre es posible nombrar el paquete correctamente: 'CMSIP2LocationBundle'. – tftd

Cuestiones relacionadas