首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Symfony 5服务无负载

Symfony 5服务无负载
EN

Stack Overflow用户
提问于 2020-04-12 15:08:47
回答 1查看 4.1K关注 0票数 1

我有一个类用来上传文件作为像symfony文档这样的服务。#创建-an-uploader service

我用symfony 5。

当我在main config/services.yaml中声明服务时,这项工作就完成了。

但是我有一个用于文件管理的包,我希望将服务声明放在这个包中: App/AD/ExplorerBundle/Resources/config/services.yaml.

当我这么做的时候,这已经不管用了。

我有错误

无法解析"App\AD\ExplorerBundle\Controller\FileController::addAction()":的参数$fileUploader不能自动更新服务"App\AD\ExplorerBundle\ service \FileUploader":方法"__construct()“的参数"$targetDirectory”是类型暗示的"string",您应该显式地配置它的值。

我不明白为什么,因为_defaults自动配置和自动配置= true

我测试缓存:清除,重新加载服务器,但没有工作。

任何帮助都将被接受。

编辑:我的包扩展: AD\ExplorerBundle\DependencyInjection

代码语言:javascript
复制
<?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捆绑\服务

代码语言:javascript
复制
<?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

代码语言:javascript
复制
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中

代码语言:javascript
复制
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

wiring#手动连接-配线-参数

容器/auTowiring.html

我真的不明白:

公共和可重复使用的Bundles 公共包应该明确地配置它们的服务,而不是依赖于自动装配。自动装配依赖于容器中可用的服务,而包对它们包含在其中的应用程序的服务容器没有控制权。您可以在公司内构建可重用的包时使用自动装配,因为您可以完全控制所有代码。

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

所以,我测试了很多东西,但都没有用。

如果有人有主意的话谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-14 15:42:44

Symfony建议在包中使用手动服务定义,主要是为了避免每次重建缓存时不断扫描包的开销。但是,我认为,使用自动配置/自动配置来创建一个潜在的可重用包可能会很有趣。我试着尽可能多地跟踪捆绑最佳实践

作为我自己的参考,我签了一个完全工作束示例

最终,包应该在它们自己的存储库中结束。但是,通过将包封装在应用程序中,可以更容易地开发包。这就是我使用的方法。但是,重要的是不要试图将应用程序源代码与包源代码混合。这样做不仅具有挑战性,而且很难将您的包复制到它自己的存储库中。

因此,我们从这样的目录结构开始:

代码语言:javascript
复制
project # Symfony application project
    src: # Application source code
    explorer-bundle # AD Explorer Bundle source code
        ADExplorerBundle.php

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

代码语言:javascript
复制
namespace AD\ExplorerBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ADExplorerBundle extends Bundle
{

}

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

代码语言:javascript
复制
# composer.json
    "autoload": {
        "psr-4": {
            "App\\": "src/",
            "AD\\ExplorerBundle\\": "explorer-bundle/"
        }
    },
# run composer "dump-autoload" after making this change

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

代码语言:javascript
复制
# 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']

为了保持简单,我只是让目标目录成为一个参数。您可能希望进行实际的包配置,并赋予应用程序设置它的能力。但这不属于这个答案的范围。

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

代码语言:javascript
复制
// 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;
    }
}

仅此而已。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61173574

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档