Symfony 5 服务未加载 [英] Symfony 5 service not load

查看:23
本文介绍了Symfony 5 服务未加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类用于将文件作为服务上传,例如 symfony 文档.https://symfony.com/doc/current/控制器/upload_file.html#creating-an-uploader-service

I got a class use to upload file as service like symfony documentation. https://symfony.com/doc/current/controller/upload_file.html#creating-an-uploader-service

我使用 symfony 5.

I use symfony 5.

当我在 main config/services.yaml 中声明服务时,这个工作.

When i declare service in main config/services.yaml, this work.

但我有一个文件管理包,我想在这个包中加入服务声明:App/AD/ExplorerBundle/Resources/config/services.yaml.

But i have a bundle for file management and i want to put service declaration in this bundle : App/AD/ExplorerBundle/Resources/config/services.yaml.

当我这样做时,这不再起作用.

When i do that this doesn't work anymore.

我有错误

无法解析App\AD\ExplorerBundle\Controller\FileController::addAction()"的参数$fileUploader:无法自动装配服务App\AD\ExplorerBundle\Service\FileUploader":方法__construct"的参数$targetDirectory"()" 是类型提示的字符串",您应该明确配置其值.

Cannot resolve argument $fileUploader of "App\AD\ExplorerBundle\Controller\FileController::addAction()": Cannot autowire service "App\AD\ExplorerBundle\Service\FileUploader": argument "$targetDirectory" of method "__construct()" is type-hinted "string", you should configure its value explicitly.

我不明白为什么,因为 _defaults autoconfigure 和 autowire = true

I don't understand why, because _defaults autoconfigure and autowire = true

我测试缓存:清除,重新加载服务器,但没有任何效果.

I test cache:clear, reload server, but nothing work.

任何帮助将不胜感激

我的捆绑扩展:在 AD\ExplorerBundle\DependencyInjection

Edit : my bundle extension: in AD\ExplorerBundle\DependencyInjection

<?php

namespace App\AD\ExplorerBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

/**
 * This is the class that loads and manages your bundle configuration.
 *
 * @link http://symfony.com/doc/current/cookbook/bundles/extension.html
 */
class ADExplorerExtension extends Extension
{
    /**
     * {@inheritdoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');
    }
}

我的捆绑服务:在 AD\ExplorerBundle\Service

my bundle service : in AD\ExplorerBundle\Service

<?php
namespace App\AD\ExplorerBundle\Service;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\String\Slugger\SluggerInterface;

class FileUploader
{
    private $targetDirectory;
    private $slugger;

    public function __construct(string $targetDirectory, SluggerInterface $slugger)
    {
        $this->targetDirectory = $targetDirectory;
        $this->slugger = $slugger;
    }

    public function upload(UploadedFile $file): array
    {
        $originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
        $safeFilename = $this->slugger->slug($originalFilename);
        $fileName = $safeFilename.'-'.uniqid().'.'.$file->guessExtension();

        $result = array(
            'filename' => $fileName,
            'originalName' => $originalFilename,
            'extension' => $file->guessExtension()
                );

        try {
            $file->move($this->getTargetDirectory(), $fileName);
        } catch (FileException $e) {
            // ... handle exception if something happens during file upload
        }

        return $result;
    }

    public function getTargetDirectory()
    {
        return $this->targetDirectory;
    }
}

我的配置/services.yaml

my config/services.yaml

parameters:
    locale: 'fr'
    doctrine_behaviors_translatable_fetch_mode: "LAZY"
    doctrine_behaviors_translation_fetch_mode: "LAZY"



imports:
    - { resource: '@ADCoreBundle/Resources/config/services.yml' }
    - { resource: './parameters.yaml' }

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.

    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'


    App\Controller\:
        resource: '../src/Controller'
        tags: ['controller.service_arguments']

我的捆绑服务:在 AD\ExplorerBundle\Resources\config\service.yaml

my Bundle service : in AD\ExplorerBundle\Resources\config\service.yaml

parameters:
    brochures_directory: '%kernel.project_dir%/public/uploads'

services: 
    ad_file_uploader:         
        class: App\AD\ExplorerBundle\Service\FileUploader
        arguments:
            $targetDirectory: '%brochures_directory%'

我阅读了文档:https://symfony.com/doc/current/bundles/extension.html

https://symfony.com/doc/current/service_container.html#manually-wiring-arguments

https://symfony.com/doc/current/service_container/autowiring.html

我真的不明白:

公共和可重用的捆绑包¶

Public and Reusable Bundles¶

公共包应该明确配置他们的服务而不是依赖关于自动装配.自动装配取决于可用的服务在容器和捆绑包中无法控制服务它们包含在应用程序的容器中.您可以使用自动装配在您的公司内构建可重用的包时,因为您有完整的控制所有代码.

Public bundles should explicitly configure their services and not rely on autowiring. Autowiring depends on the services that are available in the container and bundles have no control over the service container of applications they are included in. You can use autowiring when building reusable bundles within your company, as you have full control over all code.

我认为没关系,因为它是我的包和我的应用程序,所以我可以完全控制代码.

I think it's ok because it's my bundle and my application so i have full control of code.

所以,我测试了很多东西,但没有任何效果.

So, i test a lot of thing but nothing work.

如果有人有想法谢谢

推荐答案

Symfony 建议在 bundle 中使用手动服务定义,主要是为了避免每次重建缓存时不断扫描 bundle 的开销.但我认为看看创建具有自动装配/自动配置的潜在可重用包实际上需要什么可能会很有趣.尽可能地遵循捆绑最佳实践.

Symfony recommends using manual service definitions in bundles mostly to avoid the overhead of constantly scanning the bundle everytime the cache is rebuilt. But I thought it might be interesting to see what creating a potentially reusable bundle with autowire/autoconfigure actually entails. Tried to follow the bundles best practices as much as I could.

为了我自己的参考,我查看了一个完整的工作包示例.

For my own reference, I checked in a complete working bundle example.

最终捆绑包应该在它们自己的存储库中结束.但是,通过将包包含在应用程序中来开发包会更容易.这是我使用的方法.但重要的是不要尝试将您的应用程序源代码与捆绑源代码混合在一起.这样做不仅具有挑战性,而且会使您难以将您的包复制到自己的存储库中.

Ultimately bundles should end up in their own repository. However, it can be easier to develop a bundle by enclosing it inside an application. This is the approach I used. But it is important not to try and mix your app source code with the bundle source code. Doing so is not only challenging but will make it difficult to copy your bundle into it's own repository.

所以我们从这样的目录结构开始:

So we start with a directory structure like this:

project # Symfony application project
    src: # Application source code
    explorer-bundle # AD Explorer Bundle source code
        ADExplorerBundle.php

正确使用命名空间也很重要.前缀确实应该是唯一的供应商标识符,以避免可能的命名冲突.在这种情况下,我们使用 AD.当然,由于 AD 可能有多个捆绑包,我们进一步细分为捆绑包特定标识符.

Getting your namespace right is also important. The prefix really should be a unique vendor itdentifier just to avoid possible naming conflicts. In this case, we use AD. And then of course, since AD might have multiple bundles, we further sub-divide with a bundle specific identifier.

namespace AD\ExplorerBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ADExplorerBundle extends Bundle
{

}

为了让自动加载工作,我们调整了 composer.json 文件.一旦 bundle 被转换成一个真正的 composer 包,就不再需要这一行了.当然,您必须将 bundle 类添加到 project/config/bundles.php

In order for autoloading to work we tweak the composer.json file. Once the bundle is converted into a true composer package, this line will no longer be needed. And of course you have to add the bundle class to project/config/bundles.php

# composer.json
    "autoload": {
        "psr-4": {
            "App\\": "src/",
            "AD\\ExplorerBundle\\": "explorer-bundle/"
        }
    },
# run composer "dump-autoload" after making this change

所以现在我们需要一个扩展来加载包的 services.yaml.这只是一个标准负载,因此无需在此处显示代码.这是 services.yaml 文件的样子:

So now we need an extension to load the bundle's services.yaml. It's just a standard load so no need to show the code here. This is what the services.yaml file looks like:

# explorer-bundle/Resources/config/services.yaml
parameters:
    # Cheating here, this would normally be part of the bundle configuration
    ad_explorer_target_directory: 'some_directory'

services:
    _defaults:
        autowire: true
        autoconfigure: true
        bind:
            $targetDirectory: '%ad_explorer_target_directory%'

    AD\ExplorerBundle\:
        resource: '../../*'
        exclude: '../../{DependencyInjection,Entity,Migrations,Tests,ADExplorerBundle.php}'

    AD\ExplorerBundle\Controller\:
        resource: '../../Controller'
        tags: ['controller.service_arguments']

为了简单起见,我只是将目标目录作为参数.您可能希望进行实际的捆绑配置并赋予应用程序设置它的能力.但这超出了本答案的范围.

To keep things simple, I just made the target directory a parameter. You would probably want to make an actual bundle configuration and give the application the ability to set it. But that is outside the scope of this answer.

为了测试,我选择创建一个命令.我发现它比尝试刷新浏览器更容易.

For testing I chose to create a command. I find it easier than trying to refresh the browser.

// Easier to debug an injected service using a command than a controller
class ExplorerAddCommand extends Command
{
    private $fileUploader;

    protected static $defaultName = 'ad:explorer:add';

    public function __construct(FileUploader $fileUploader)
    {
        parent::__construct();
        $this->fileUploader = $fileUploader;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        echo "Explorer Add " . $this->fileUploader->targetDirectory . "\n";
        return 0;
    }
}

就是这样.

这篇关于Symfony 5 服务未加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆