我正在编写一个应用程序,它具有Symfony应用程序的结构和一些Symfony功能,但应尽可能与框架分离。所以我没有使用框架的DI,而是使用PHP-DI。
现在我需要Symfony的EventDispatcher
(对于我的框架解耦架构而言,这是一个苦果,但无论如何......)。我的问题是,我没有从services.yaml
引用到PHP-DI容器的工作 - 而且我的听众没有被EventDispatcher
连接。
如何在services.yaml
中使用PHP-DI容器的服务(特别是EventDispatcher
,如果有任何细节)?
以下是一些代码:
services.yaml
(完全)
parameters:
services:
_defaults:
autowire: true
autoconfigure: true
public: false
# events
# App\Process\SystemEventHandler: <-- No errors, but also no effect.
@system.event_handler:
tags:
- { name: system.event_handler, event: general.user_message_received, method: handle }
- { name: system.event_handler, event: xxx.foo, method: handle }
- { name: system.event_handler, event: yyy.foo, method: handle }
- { name: system.event_handler, event: zzz.foo, method: handle }
App\Kernel
(完全)
namespace App;
use DI\Bridge\Symfony\Kernel as PhpDIBridgeSymfonyKernel;
use DI\Container;
use DI\ContainerBuilder as PhpDiContainerBuilder;
use Exception;
use Psr\Container\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Exception\FileLoaderLoadException;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Routing\RouteCollectionBuilder;
class Kernel extends PhpDIBridgeSymfonyKernel
{
use MicroKernelTrait;
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
public function getCacheDir()
{
return $this->getProjectDir().'/var/cache/'.$this->environment;
}
public function getLogDir()
{
return $this->getProjectDir().'/var/log';
}
public function registerBundles()
{
$contents = require $this->getProjectDir() . '/config/bundles.php';
foreach ($contents as $class => $envs) {
if (isset($envs['all']) || isset($envs[$this->environment])) {
yield new $class();
}
}
}
/**
* @param ContainerBuilder $container
* @param LoaderInterface $loader
* @throws Exception
*/
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
// Feel free to remove the "container.autowiring.strict_mode" parameter
// if you are using symfony/dependency-injection 4.0+ as it's the default behavior
$container->setParameter('container.autowiring.strict_mode', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$confDir = $this->getProjectDir().'/config';
$loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
}
/**
* @param RouteCollectionBuilder $routes
* @throws FileLoaderLoadException
*/
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$confDir = $this->getProjectDir().'/config';
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
}
/**
* @param PhpDiContainerBuilder $builder
* @return Container|ContainerInterface
* @throws Exception
*/
protected function buildPHPDIContainer(PhpDiContainerBuilder $builder)
{
// Configure your container here
// http://php-di.org/doc/container-configuration.html
$builder->addDefinitions($this->getProjectDir() . '/config/dependencies/common.php');
return $builder->build();
}
}
/config/dependencies/common.php
(带有依赖项的文件,相关摘录)
...
return [
FooServiceInterface::class => DI\autowire(FooBService::class),
BarServiceInterface::class => DI\autowire(BarService::class),
...
EntityManagerInterface::class => function () {
...
},
'process_handler.xxx' => DI\autowire(XxxHandler::class),
'process_handler.yyy' => DI\autowire(YyyHandler::class),
'process_handler.zzz' => DI\autowire(ZzzHandler::class),
EventHandlerInterface::class => DI\factory(function(ContainerInterface $container) {
return new SystemEventHandler(
$container->get('process_handler.xxx'),
$container->get('process_handler.yyy'),
$container->get('process_handler.zzz')
);
}),
'system.event_handler' => DI\get(EventHandlerInterface::class),
EventDispatcherInterface::class => DI\get('event_dispatcher'),
];