【问题标题】:Symfony autowiring Event ListenerSymfony 自动装配事件监听器
【发布时间】:2019-07-06 18:43:34
【问题描述】:

Symfony 4.2.2

为了在一个控制器中缓存所有响应,我使用了 kernel.controller 事件的事件侦听器。我的事件监听器需要一些服务和信息:

  • EnityManager 接口
  • 被缓存的控制器
  • 内核缓存文件夹

我是这样设置的:

namespace App\Listener;


use App\Controller\DataOutputController;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

class CachedOutput{

    protected $cacheFolder;
    protected $em;
    protected $controller;
    public function __construct($cacheFolder, EntityManagerInterface $em, DataOutputController $controller )
    {
        $this->cacheFolder = $cacheFolder;
        $this->em = $em;
        $this->controller = $controller;
    }



    public function findCachedObject(FilterControllerEvent $event, $eventName, TraceableEventDispatcher $dispatcher

    ){
        $params      = $event->getRequest()->attributes->get('_route_params');

        $fileType = $this->em->getRepository('App:FileType')->find($params->get('fileType'));
        $dataSet = $this->controller->getDataSet($params->get('dataSetSearch')?:'latest', $fileType->getType());

        $cacheFile = $this->cacheFolder.'/output/DS'.$dataSet->getId().'-FT'.$fileType->getId().'.html';

        if (file_exists($cacheFile)){
            $fh = fopen($cacheFile,'r');
            return new Response(fpassthru($fh));
        }
    }



}



services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: true       # Allows optimizing the container by removing unused services; this also means
                            # fetching services directly from the container via $container->get() won't work.
                            # The best practice is to be explicit about your dependencies anyway.
        bind:
            $projectDir: '%kernel.project_dir%'
    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

    # controllers are imported separately to make sure services can be injected
    # as action arguments even if you don't extend any base controller class
    App\Controller\:
        resource: '../src/Controller'
        tags: ['controller.service_arguments']


    controller.return_cached_output:
        class: App\Listener\CachedOutput
        arguments:
            $cacheFolder: "%kernel.cache_dir%"
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: findCachedObject }

但是,我仍然收到有关缓存文件夹的错误:

无法自动装配服务“App\Listener\CachedOutput”:方法“__construct()”的参数“$cacheFolder”没有类型提示,您应该明确配置其值。

我错过了什么?

更新:

曾尝试为这样的服务使用别名:

App\Listener\CachedOutput:
    public: false
    arguments:
        $cacheFolder: "%kernel.cache_dir%"
    tags:
        - { name: kernel.event_listener, event: kernel.controller, method: findCachedObject }

return_cached_output:
    alias: App\Listener\CachedOutput
    public: true

没有成功

【问题讨论】:

  • 你在项目中的监听器在哪里?
  • App/Listener/Cached Output.php
  • 你在哪里声明你的监听器为服务?
  • 整个 services.yaml 都在问题中
  • 题外话:把你的听众变成subscriber,你就可以摆脱标签部分了。在 _defaults 部分(如 $projectDir)绑定 $cacheFolder,您可以完全摆脱手动服务定义。

标签: symfony


【解决方案1】:

您需要在__construct(string $cacheFolder, ...) 中输入提示

【讨论】:

  • 那会做什么? autowire 如何知道要注入哪个字符串?
猜你喜欢
  • 1970-01-01
  • 2018-06-06
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
相关资源
最近更新 更多