Symfony - 在接口中获取容器
Symfony - Get a container inside an Interface
我正在使用 symfony 并且需要知道如何将容器注入 EventSubscriberInterface?
我的目标是使用“mail_template_type.repository”。它在控制器中工作正常,但 EventSubscriberInterface 似乎没有容器,或者至少 dumpe($event) 没有显示它。
/**
* @var EntityRepositoryInterface $mailTypeRepository
* @var EntityRepositoryInterface $mailRepository
*/
$mailTypeRepository = getContainer()->get('mail_template_type.repository');
$mailRepository = getContainer()->get('mail_template.repository');
完整代码如下:
<?php
namespace RegistrationExtension\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Checkout\Customer\CustomerEvents;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Controller\StorefrontController;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Checkout\Customer\Event\CustomerRegisterEvent;
use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoadedEvent;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Psr\Container\ContainerInterface;
use RegisterExtension\Struct\RegisterStruct;
class RegisterExtensionSubscriber implements EventSubscriberInterface{
/**
* @param ContainerInterface|NULL $container
*/
public function setContainer(ContainerInterface $container = NULL){
$this->container = $container;
return $this;
}
/**
* @return ContainerInterface
*/
protected function getContainer(){
return $this->container;
}
public static function getSubscribedEvents(): array{
return [
AccountLoginPageLoadedEvent::class => 'onCustomRegister'
];
}
public function onCustomRegister(AccountLoginPageLoadedEvent $event){
//dump($this->getContainer('mail_template_type.repository'));
//$event->getPage()->addExtension('custom_struct', new RegisterStruct());
/**
* @var EntityRepositoryInterface $mailTypeRepository
* @var EntityRepositoryInterface $mailRepository
*/
$mailTypeRepository = getContainer()->get('mail_template_type.repository');
$mailRepository = getContainer()->get('mail_template.repository');
$mailEntity = $mailTypeRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template_type.technicalName', "customer_register")),
$event->getContext()
);
$mailTypeId = $mailEntity->getEntities()->first()->getId();
$mailEntity = $mailRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template.mailTemplateTypeId', $mailTypeId)),
$event->getContext()
);
//$mailEntity->getEntities()->setContentHtml("test");
$mail = $mailEntity->getEntities();
}
}
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="RegistrationExtension\Storefront\Controller\RegistrationExtensionController" public="true"> </service>
<service id="RegistrationExtension\Subscriber\RegisterExtensionSubscriber">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
如我的评论所述,您应该利用依赖注入来仅添加您需要的服务,而不是整个容器。
请务必在进行以下更改后清除并预热您的 Symfony 缓存。
自动装配服务
在 Symfony 3.4+ 中,您可以使用 autowire
,它会自动将已知的 FQCN 服务注入 __construct
,例如使用记录器服务。
vendor/symfony/monolog-bundle/Resources/config/monolog.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="monolog.logger" parent="monolog.logger_prototype" public="false">
<argument index="0">app</argument>
<call method="useMicrosecondTimestamps">
<argument>%monolog.use_microseconds%</argument>
</call>
</service>
<service id="logger" alias="monolog.logger" />
<service id="Psr\Log\LoggerInterface" alias="logger" public="false" />
<!-- ... -->
</service>
</services>
</container>
config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<!-- attempts to inject and tag services automatically -->
<defaults autowire="true" autoconfigure="true" public="false"/>
<service id="RegistrationExtension\Storefront\Controller\RegistrationExtensionController" public="true"> </service>
<service id="RegistrationExtension\Subscriber\RegisterExtensionSubscriber">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
src/RegistrationExtension/Subscriber/RegisterExtensionSubscriber.php
use Psr\Log\LoggerInterface;
class RegisterExtensionSubscriber implements EventSubscriberInterface
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
依赖注入
如果服务无法使用 autowire
注入,因为它使用字符串服务名称而不是 FQCN,您可以在配置中手动声明该服务。
config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="RegistrationExtension\Storefront\Controller\RegistrationExtensionController" public="true"> </service>
<service id="RegistrationExtension\Subscriber\RegisterExtensionSubscriber">
<argument type="service" id="mail_template_type.repository" />
<argument type="service" id="mail_template.repository" />
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
src/RegistrationExtension/Subscriber/RegisterExtensionSubscriber.php
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
//...
class RegisterExtensionSubscriber implements EventSubscriberInterface
{
/**
* @var EntityRepositoryInterface
*/
private $mailTypeRepository;
/**
* @var EntityRepositoryInterface
*/
private $mailRepository;
public function __construct(
EntityRepositoryInterface $mailTypeRepository,
EntityRepositoryInterface $mailRepository
) {
$this->mailTypeRepository = $mailTypeRepository;
$this->mailRepository = $mailRepository;
}
public function onCustomRegister(AccountLoginPageLoadedEvent $event)
{
$mailEntity = $this->mailTypeRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template_type.technicalName', "customer_register")),
$event->getContext()
);
if ($mailType = $mailEntity->getEntities()->first()) {
$mailEntity = $this->mailRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template.mailTemplateTypeId', $mailType->getId())),
$event->getContext()
);
$mail = $mailEntity->getEntities();
//...
}
}
}
我正在使用 symfony 并且需要知道如何将容器注入 EventSubscriberInterface?
我的目标是使用“mail_template_type.repository”。它在控制器中工作正常,但 EventSubscriberInterface 似乎没有容器,或者至少 dumpe($event) 没有显示它。
/**
* @var EntityRepositoryInterface $mailTypeRepository
* @var EntityRepositoryInterface $mailRepository
*/
$mailTypeRepository = getContainer()->get('mail_template_type.repository');
$mailRepository = getContainer()->get('mail_template.repository');
完整代码如下:
<?php
namespace RegistrationExtension\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Checkout\Customer\CustomerEvents;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Controller\StorefrontController;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Checkout\Customer\Event\CustomerRegisterEvent;
use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoadedEvent;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Psr\Container\ContainerInterface;
use RegisterExtension\Struct\RegisterStruct;
class RegisterExtensionSubscriber implements EventSubscriberInterface{
/**
* @param ContainerInterface|NULL $container
*/
public function setContainer(ContainerInterface $container = NULL){
$this->container = $container;
return $this;
}
/**
* @return ContainerInterface
*/
protected function getContainer(){
return $this->container;
}
public static function getSubscribedEvents(): array{
return [
AccountLoginPageLoadedEvent::class => 'onCustomRegister'
];
}
public function onCustomRegister(AccountLoginPageLoadedEvent $event){
//dump($this->getContainer('mail_template_type.repository'));
//$event->getPage()->addExtension('custom_struct', new RegisterStruct());
/**
* @var EntityRepositoryInterface $mailTypeRepository
* @var EntityRepositoryInterface $mailRepository
*/
$mailTypeRepository = getContainer()->get('mail_template_type.repository');
$mailRepository = getContainer()->get('mail_template.repository');
$mailEntity = $mailTypeRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template_type.technicalName', "customer_register")),
$event->getContext()
);
$mailTypeId = $mailEntity->getEntities()->first()->getId();
$mailEntity = $mailRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template.mailTemplateTypeId', $mailTypeId)),
$event->getContext()
);
//$mailEntity->getEntities()->setContentHtml("test");
$mail = $mailEntity->getEntities();
}
}
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="RegistrationExtension\Storefront\Controller\RegistrationExtensionController" public="true"> </service>
<service id="RegistrationExtension\Subscriber\RegisterExtensionSubscriber">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
如我的评论所述,您应该利用依赖注入来仅添加您需要的服务,而不是整个容器。
请务必在进行以下更改后清除并预热您的 Symfony 缓存。
自动装配服务
在 Symfony 3.4+ 中,您可以使用 autowire
,它会自动将已知的 FQCN 服务注入 __construct
,例如使用记录器服务。
vendor/symfony/monolog-bundle/Resources/config/monolog.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="monolog.logger" parent="monolog.logger_prototype" public="false">
<argument index="0">app</argument>
<call method="useMicrosecondTimestamps">
<argument>%monolog.use_microseconds%</argument>
</call>
</service>
<service id="logger" alias="monolog.logger" />
<service id="Psr\Log\LoggerInterface" alias="logger" public="false" />
<!-- ... -->
</service>
</services>
</container>
config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<!-- attempts to inject and tag services automatically -->
<defaults autowire="true" autoconfigure="true" public="false"/>
<service id="RegistrationExtension\Storefront\Controller\RegistrationExtensionController" public="true"> </service>
<service id="RegistrationExtension\Subscriber\RegisterExtensionSubscriber">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
src/RegistrationExtension/Subscriber/RegisterExtensionSubscriber.php
use Psr\Log\LoggerInterface;
class RegisterExtensionSubscriber implements EventSubscriberInterface
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
依赖注入
如果服务无法使用 autowire
注入,因为它使用字符串服务名称而不是 FQCN,您可以在配置中手动声明该服务。
config/services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="RegistrationExtension\Storefront\Controller\RegistrationExtensionController" public="true"> </service>
<service id="RegistrationExtension\Subscriber\RegisterExtensionSubscriber">
<argument type="service" id="mail_template_type.repository" />
<argument type="service" id="mail_template.repository" />
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
src/RegistrationExtension/Subscriber/RegisterExtensionSubscriber.php
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
//...
class RegisterExtensionSubscriber implements EventSubscriberInterface
{
/**
* @var EntityRepositoryInterface
*/
private $mailTypeRepository;
/**
* @var EntityRepositoryInterface
*/
private $mailRepository;
public function __construct(
EntityRepositoryInterface $mailTypeRepository,
EntityRepositoryInterface $mailRepository
) {
$this->mailTypeRepository = $mailTypeRepository;
$this->mailRepository = $mailRepository;
}
public function onCustomRegister(AccountLoginPageLoadedEvent $event)
{
$mailEntity = $this->mailTypeRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template_type.technicalName', "customer_register")),
$event->getContext()
);
if ($mailType = $mailEntity->getEntities()->first()) {
$mailEntity = $this->mailRepository->search(
(new Criteria())->addFilter(new EqualsFilter('mail_template.mailTemplateTypeId', $mailType->getId())),
$event->getContext()
);
$mail = $mailEntity->getEntities();
//...
}
}
}