Доступ до файлів щодо пакета в Symfony2


83

У конфігурації маршрутизації програми 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, але не думаю, що це те, що я шукаю. Будь-які ідеї? А може, я повністю не помічаю кращого способу цього зробити?

Відповіді:


179

По суті, для цього є послуга, яку ви можете використати, ядро ​​( $this->get('kernel')). Він має метод, який називається locateResource().

Наприклад:

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

5
Саме те, що я шукав! $ this-> get ('kernel') -> locateResource ("@ SomeBundle / Resources / config / config.yml"); // працював ідеально
Thomas Kelley

9
@ tomtheman5: Обов’язково вловлюйте його винятки. Цей метод видає \InvalidArgumentException, якщо файл не вдається знайти або \RuntimeExceptionім'я невірно , і якщо ім'я містить недійсні / небезпечні символи.
kgilden

2
Хотіли б дати вам більше, ніж просто +1.
грип

Як (якщо взагалі) ви б використовували цей метод всередині доктрини, яка (я не думаю) мала б (або повинна) мати доступ до ядра?
Майкл Ламлі,

1
@Morslamina Перевірте відповідь fazy.
Tek

78

Відповідь Томаса Келлі хороша (і працює!), Але якщо ви використовуєте ін’єкцію залежностей та / або не хочете прив’язувати свій код безпосередньо до ядра, вам краще скористатися класом / службою 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')
    }
}

Хороший момент, але FileLocator вводить KernelInterface, тому, в основному, ви не робите нічого кращого, якщо
вставляєте

10
Я бачу вашу думку, і я про це думав. Однак проблема полягає не в тому, «який код завантажується / виконується?», А в тому, «від якого коду MyClassзалежить?». Поточна FileLocatorреалізація використовує KernelInterface, але якщо це зміниться в майбутньому MyClass, не потрібно про це знати. Крім того, тепер стає зрозуміліше, що MyClassнасправді потрібно (і менше спокус поєднати це з іншими функціями ядра). Сказавши все це, конструктор, напевно, повинен вимагати, Symfony\Component\Config\FileLocatorInterfaceа не Symfony\Component\HttpKernel\Config\FileLocator. Тоді ви можете написати свій власний.
fazy

3
це краща відповідь
NDM

6

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


Комплект може бути в будь-якому каталозі. Звичайні приклади: src/Acme/Bundle/MyBundle, src/Acme/MyBundle, vendor/acme/my-bundle/srcі так далі.
Маріус Бальчитіс,

3

Якщо ви хочете зробити це у файлі, що знаходиться в, src/.../SomeBundle/...ви можете використовувати, __DIR__щоб отримати повний шлях до поточного файлу. Потім додайте свій Resources/...шлях до цього

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

@ruudy "Лише зареєстровані користувачі з платним тарифом можуть отримати повний доступ до описів правил. Ця сторінка показує зразок того, що ви можете отримати, підписавшись".
prehfeldt

я не платив, і я бачу повний опис та пояснення, як це вирішити. Можливо, вам потрібно лише зареєструватися.
грубий

Тепер, коли я зареєстрований, я бачу сторінку. Перш за все там сказано "не слід" і не "не повинно". По-друге, це важливо лише в тому випадку, якщо ви плануєте опублікувати свій код загальнодоступним або плануєте замінити шлях до ресурсу пізніше. У моїх проектах із закритим кодом цього не станеться, тому це не так важливо для мене. Якщо цей момент важливий для вас, це залежить від контексту, де ви його будете використовувати. Тим не менше дякую за підказку.
prehfeldt

Якщо ви будете слідувати рекомендаціям, ви можете знущатись над шляхом або грати з ним з метою тестування. Я не є рідною англійською мовою, краще не використовувати ці константи php як можливі, а тим більше на таких фреймворках, як Symfony2.
ruudy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.