2011-09-28 10 views
81

En la configuración de enrutamiento de un Symfony2 aplicación, que puede hacer referencia a un archivo de la siguiente manera:accede a los archivos relativa a bulto en Symfony2

somepage: 
    prefix: someprefix 
    resource: "@SomeBundle/Resources/config/config.yml" 

¿Hay alguna manera de acceder a un archivo en relación con el paquete dentro de un controlador u otro Código PHP? En particular, estoy tratando de usar un objeto Symfony \ Component \ Yaml \ Parser para analizar un archivo, y no quiero referirme a ese archivo en absoluto. En esencia, lo que quiero hacer esto:

$parser = new Parser(); 
$config = $parser->parse(file_get_contents("@SomeBundle/Resources/config/config.yml")); 

He comprobado a cabo la clase \ Buscador \ Buscador de Symfony \ Component, pero no creo que eso es lo que estoy buscando. ¿Algunas ideas? ¿O tal vez estoy pasando por alto una mejor manera de hacer esto?

Respuesta

176

Como cuestión de hecho, hay un servicio que podría utilizar para esto, el núcleo ($this->get('kernel')). Tiene un método llamado locateResource().

Por ejemplo:

$kernel = $container->getService('kernel'); 
$path = $kernel->locateResource('@AdmeDemoBundle/path/to/file/Foo.txt'); 
+5

¡Exactamente lo que estaba buscando! $ this-> get ('kernel') -> locateResource ("@ SomeBundle/Resources/config/config.yml"); // funcionó perfectamente –

+9

@ tomtheman5: asegúrese de detectar sus excepciones. Este método arroja '\ InvalidArgumentException', si el archivo no se puede encontrar o el nombre no es válido, y' \ RuntimeException', si el nombre contiene caracteres no válidos/inseguros. – gilden

+2

Me encantaría darte más que solo +1. – flu

6

Puede usar $container->getParameter('kernel.root_dir') para obtener la carpeta app de su aplicación y buscar en sus directorios el archivo que desee.

+0

El paquete puede estar en cualquier directorio. Ejemplos habituales: 'src/Acme/Bundle/MyBundle',' src/Acme/MyBundle', 'vendor/acme/my-bundle/src', etc. –

3

Si desea hacer eso en un archivo ubicado en src/.../SomeBundle/... puede usar __DIR__ para obtener la ruta completa del archivo actual. A continuación, anexe la ruta de Resources/... a que al igual que

$foo = __DIR__.'/Resources/config/config.yml'; 
+1

No debe hacer esto, https://insight.sensiolabs.com/what-we-analyse/symfony.dependency_injection.use_dir_file_constant – ruudy

+0

@ruudy "Solo los usuarios registrados con un plan pago pueden obtener acceso completo a las descripciones de las reglas. Esta página muestra una muestra de lo que puede obtener suscribiéndose ". – prehfeldt

+0

No pagué y puedo ver la descripción completa y la explicación de cómo resolverlo. Quizás solo necesites registrarte. – ruudy

78
respuesta de

Thomas Kelley es bueno (y funciona!), Pero si usted está usando la inyección de dependencia y/o no desea atar su código directamente al núcleo, que está mejor usar la clase/servicio FileLocator:

$fileLocator = $container->get('file_locator'); 
$path = $fileLocator->locate('@MyBundle/path/to/file.txt') 

$fileLocator habrá una instancia de \Symfony\Component\HttpKernel\Config\FileLocator. $path será la ruta completa y absoluta del archivo.

A pesar de que el servicio file_locator sí utiliza el núcleo, que es una dependencia mucho menor (más fácil de sustituir a su propia implementación, dobles prueba de uso, etc.)

usarlo con inyección de dependencias:

# services.yml 

services: 
    my_bundle.my_class: 
     class: MyNamespace\MyClass 
     arguments: 
      - @file_locator 

# MyClass.php 

use Symfony\Component\Config\FileLocatorInterface as FileLocator; 

class MyClass 
{ 
    private $fileLocator; 

    public function __construct(FileLocator $fileLocator) 
    { 
     $this->fileLocator = $fileLocator; 
    } 

    public function myMethod() 
    { 
     $path = $this->fileLocator->locate('@MyBundle/path/to/file.txt') 
    } 
} 
+0

Buen punto, pero FileLocator obtiene KernelInterface inyectado, así que, básicamente, no haces nada mejor si inyectas FileLocator en lugar de Kernel :) – tomazahlin

+9

Veo tu punto, y pensé en eso. Sin embargo, el problema no es "¿qué código se carga/ejecuta?", Sino "¿de qué código depende' MyClass'? ". La implementación actual de 'FileLocator' usa' KernelInterface', pero si eso cambia en el futuro 'MyClass' no necesita saber al respecto. Además, ahora está más claro qué 'MyClass' realmente necesita (y menos tentación de combinarlo con otras características del kernel). Habiendo dicho todo eso, el constructor probablemente requiera 'Symfony \ Component \ Config \ FileLocatorInterface' en lugar de' Symfony \ Component \ HttpKernel \ Config \ FileLocator'. Entonces puedes escribir el tuyo. – fazy

+0

Por supuesto, estoy de acuerdo. – tomazahlin

Cuestiones relacionadas