Существует довольно много способов сделать это, но я думаю, что хорошим подходом было бы добавить параметр конфигурации для класса/службы, который должен быть введен в первый аргумент конструктора.
Например, в классе Foo\MenuBundle\Menu
(при условии, что это уже определено как услуга) вы можете добавить дополнительный элемент в конфигурацию пакета для определения службы по умолчанию для $securer
, а затем, при необходимости, переопределить ее в конфигурации ,
В классе конфигурации (DependecyInjection\Configuration.php
):
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('foo_menu');
$rootNode
->children()
->arrayNode('service')
->addDefaultsIfNotSet()
->children()
->scalarNode('menu_securer')->defaultValue('foo_security.menu_securer')->end()
>end()
->end()
->end();
return $treeBuilder;
}
В классе расширения (DependecyInjection\FooMenuExtension.php
):
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
// ...
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
// This is what sets 'foo_menu.menu_securer' to the service you want
foreach ($config['service'] as $key => $service) {
$container->setAlias($this->getAlias() . '.' . $key, $service);
}
$loader->load('services.xml');
$container->getDefinition('foo_menu.menu.menu')
->replaceArgument(0, new Reference('foo_menu.menu_securer'));
}
И ваше определение услуг будет просто выглядеть примерно так ...
<service id="foo_menu.menu.menu" class="%foo_menu.menu.menu.class%">
<argument /> <!-- foo_menu.menu_securer -->
</service>
Теперь в вашем config.yml
вы c просто переключитесь из услугу, которую вы хотите использовать, определив его в под ...
foo_menu:
service:
menu_securer: 'some_other.service'
Edit: Что касается типа намекая, как уже упоминалось, Маркус, вероятно, было бы хорошей идеей, чтобы реализовать интерфейс, что $securer
должен реализовывать.
Уточнение: вопрос в основном касается оператора использования и используемого, но потенциально не объявленного интерфейса. – user2268997
Не может быть хорошего решения. Вы можете либо убедиться, что ваш пакет имеет зависимость от того, который содержит интерфейс, либо вы можете полностью разделить интерфейсы на отдельный комплект и потребовать его. Или, может быть, я неправильно понимаю реальную проблему. – ChadSikorra
@ChadSikorra: да, это действительно моя проблема. Что я сейчас делаю: создайте две отдельные службы, одну без дополнительной зависимости и одну без нее. Затем я меняю определение службы, используя пересылку компилятора в пакете Dependee Bundle. – user2268997