Мне нужно добавить, а затем из контекста получить дополнительные параметры / конфигурацию из файла behat.yml.
Behat не позволяет мне добавлять некоторые случайные параметры в файл behat.yml, поэтому я создал новое пользовательское расширение. Это расширение позволяет мне передавать определенные значения конфигурации
extensions: App\Behat\DevToolsExtension: api_url: "https://api.example.com"
Поэтому сейчас не жалуйтесь на новую конфигурацию в файле behat.yml.
Теперь я застрял. Как получить эту конфигурацию из моего расширения во время выполнения?
Я устанавливаю существующие параметры в своем расширении в рамках публичной функции load (ContainerBuilder $ container, array $ config), например:
$container->setParameter($configKey . $key, $config[$key]);
Опять же, есть способ получить этот объект ContainerBuilder или объект DevToolsExtension в Context?
Решение заключалось в создании сервисного контейнера и вступлении к нему в ContainerBuilder следующим образом:
class AppExtension implements ExtensionInterface { // ... public function load(ContainerBuilder $container, array $config) { $configKey = $this->getConfigKey() . '.'; foreach ($this->keys as $key) { $keyValue = $configKey . $key; $container->setParameter($keyValue, $config[$key]); } $this->getServiceLocator()->setBehatContainer($container); }
И затем используйте служебный локатор для извлечения параметров конфигурации
$value = $this->getBehatContainer()->getParameter($key);
Это хороший вопрос. В базовых контекстах нет ссылок на верху, поэтому вы не можете точно узнать, какие расширения загружаются. Расширения инициализируются и подключаются во внутреннюю систему событий. Когда контексты инициализируются, они получают уведомление и могут передавать им необходимые параметры. Зная это, вы можете создать правильное расширение, которое перехватывает систему событий Behat и передает конфигурацию в ваш контекст – это будет способ сделать это.
Расширение Mink – хороший пример этого, вы, вероятно, не найдете никакой документации, но вы можете создать конструктор в одном из ваших (Mink) контекстов, добавить там точку перелома и следовать следу, чтобы узнать, как работает все это ,
Но … В большинстве случаев это было бы излишним. То же самое может быть (и должно быть) достигнуто с использованием либо внешнего файла конфигурации, который вы можете загрузить из своего контекста, либо путем передачи параметров в контекст (так же, как и теперь с расширением). Последний вариант может работать не очень хорошо, если у вас много контекстов, которые нуждаются в такой конфигурации.
У меня была эта проблема, и я решил это для проекта: CLIPBOARD
Конечно, работает над ~ v3.0 Вероятно, работает над версией v2.5.
В классе Exntesion после создания расширения вам потребуется инициализатор, который инициализирует любой контекст в системе. Для этого вам нужно создать службу в контейнере с ContextExtension :: INITIALIZER_TAG и зависит от конфигурации. у меня есть
$container->setParameter('dev_tools_extension.parameters', $config);
А потом
private function loadContextInitializer(ContainerBuilder $container) { $definition = new Definition( 'App\Behat\DevToolsExtension\Context\Initializer\DevToolsExtensionInitializer', array( '%dev_tools_extension.parameters%' ) ); $definition->addTag(ContextExtension::INITIALIZER_TAG, array('priority' => 0)); $container->setDefinition('dev_tools_extension.context_initializer', $definition); }
Инициализатор реализует Behat \ Behat \ Context \ Initializer \ ContextInitializer с вызываемым контекстом. Затем вы создаете (например, интерфейс) и вызываете функцию в контексте. У меня есть:
/** * Initializes provided context. * * @param Context $context */ public function initializeContext(Context $context) { if (!$context instanceof ClipboardContextInterface) { return; } /** @var ClipboardContextInterface $context */ $context->setClipboard($this->clipboard); }