Доступ к файлам относительно пакета в Symfony2

81

В конфигурации маршрутизации приложений Symfony2 я могу ссылаться на такой файл:

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

Есть ли способ получить доступ к файлу относительно пакета в контроллере или другом PHP-коде? В частности, я пытаюсь использовать объект Symfony\Component\Yaml\Parser для анализа файла, и я не хочу полностью ссылаться на этот файл. По сути, я хочу сделать это:

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

Я проверил класс Symfony\Component\Finder\Finder, но я не думаю, что то, что я ищу. Есть идеи? Или, может быть, я полностью игнорирую лучший способ сделать это?

Теги:

4 ответа

175
Лучший ответ

На самом деле, для этого есть сервис, ядро ​​($this->get('kernel')). Он имеет метод locateResource().

Например:

$kernel = $container->getService('kernel');
$path = $kernel->locateResource('@AdmeDemoBundle/path/to/file/Foo.txt');
  • 5
    Именно то, что я искал! $ This-> получить ( 'ядро') -> locateResource ( "@ SomeBundle / Ресурсы / конфигурации / config.yml"); // работал отлично
  • 9
    @ tomtheman5: Обязательно поймай его исключения. Этот метод \InvalidArgumentException , если файл не может быть найден или имя недопустимо, и \RuntimeException , если имя содержит недопустимые / небезопасные символы.
Показать ещё 4 комментария
82

Ответ Томаса Келли хорош (и работает!), но если вы используете инъекцию зависимостей и/или не хотите привязывать свой код непосредственно к ядру, вам лучше использовать класс/службу FileLocator:

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

$fileLocator будет экземпляром \Symfony\Component\HttpKernel\Config\FileLocator. $path будет полным, абсолютным путем к файлу.

Даже если сама служба file_locator использует ядро, это гораздо меньшая зависимость (проще заменить вашу собственную реализацию, использовать тестовые двойники и т.д.).

Чтобы использовать его при инъекции зависимостей:

# 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
    Замечательно, но FileLocator вводит KernelInterface, так что, по сути, вы ничего не делаете лучше, если внедрите FileLocator вместо Kernel :)
  • 9
    Я понимаю вашу точку зрения, и я подумал об этом. Однако проблема не в том, «какой код загружается / выполняется?», А в том, «от какого кода зависит MyClass ?». Текущая реализация FileLocator использует KernelInterface , но если это изменится в будущем, MyClass не должен знать об этом. Кроме того, теперь стало понятнее, что на самом деле нужно MyClass (и меньше искушений связать его с другими функциями ядра). Сказав все это, конструктор, вероятно, должен требовать Symfony\Component\Config\FileLocatorInterface а не Symfony\Component\HttpKernel\Config\FileLocator . Тогда вы можете написать свой собственный.
Показать ещё 2 комментария
6

Вы можете использовать $container->getParameter('kernel.root_dir'), чтобы получить папку app вашего приложения и просмотреть ваши каталоги в нужном файле.

  • 0
    Пакет может быть в любом каталоге. Обычные примеры: src/Acme/Bundle/MyBundle , src/Acme/MyBundle , vendor/acme/my-bundle/src и так далее.
4

Если вы хотите сделать это в файле, расположенном в src/.../SomeBundle/..., вы можете использовать __DIR__, чтобы получить полный путь к текущему файлу. Затем добавьте путь Resources/... к тому, что нравится

$foo = __DIR__.'/Resources/config/config.yml';
  • 0
    @ruudy "Только зарегистрированные пользователи с платным планом могут получить полный доступ к описаниям правил. На этой странице показан пример того, что вы можете получить, подписавшись."
  • 0
    Я не заплатил, и я могу увидеть полное описание и объяснение того, как ее решить. Может быть, вам нужно только зарегистрироваться.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню