В конфигурации маршрутизации приложений 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, но я не думаю, что то, что я ищу. Есть идеи? Или, может быть, я полностью игнорирую лучший способ сделать это?
На самом деле, для этого есть сервис, ядро ($this->get('kernel')
). Он имеет метод locateResource()
.
Например:
$kernel = $container->getService('kernel');
$path = $kernel->locateResource('@AdmeDemoBundle/path/to/file/Foo.txt');
Ответ Томаса Келли хорош (и работает!), но если вы используете инъекцию зависимостей и/или не хотите привязывать свой код непосредственно к ядру, вам лучше использовать класс/службу 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')
}
}
MyClass
?». Текущая реализация FileLocator
использует KernelInterface
, но если это изменится в будущем, MyClass
не должен знать об этом. Кроме того, теперь стало понятнее, что на самом деле нужно MyClass
(и меньше искушений связать его с другими функциями ядра). Сказав все это, конструктор, вероятно, должен требовать Symfony\Component\Config\FileLocatorInterface
а не Symfony\Component\HttpKernel\Config\FileLocator
. Тогда вы можете написать свой собственный.
Вы можете использовать $container->getParameter('kernel.root_dir')
, чтобы получить папку app
вашего приложения и просмотреть ваши каталоги в нужном файле.
src/Acme/Bundle/MyBundle
, src/Acme/MyBundle
, vendor/acme/my-bundle/src
и так далее.
Если вы хотите сделать это в файле, расположенном в src/.../SomeBundle/...
, вы можете использовать __DIR__
, чтобы получить полный путь к текущему файлу. Затем добавьте путь Resources/...
к тому, что нравится
$foo = __DIR__.'/Resources/config/config.yml';
\InvalidArgumentException
, если файл не может быть найден или имя недопустимо, и\RuntimeException
, если имя содержит недопустимые / небезопасные символы.