symfony - Symfony 5服务未加载
问题描述
我有一个类用于上传文件作为服务,如 symfony 文档。 https://symfony.com/doc/current/controller/upload_file.html#creating-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”是类型提示的“字符串”,您应该明确配置其值。
我不明白为什么,因为 _defaults autoconfigure 和 autowire = true
我测试缓存:清除,重新加载服务器,但没有任何效果。
任何帮助将不胜感激
编辑:我的捆绑扩展:在 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
<?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
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
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
我真的不明白这一点:
公共和可重用的捆绑包¶
公共包应该明确地配置他们的服务,而不是依赖于自动装配。自动装配取决于容器中可用的服务,并且捆绑包无法控制它们所包含的应用程序的服务容器。您可以在公司内部构建可重用捆绑包时使用自动装配,因为您可以完全控制所有代码。
我认为这没关系,因为它是我的捆绑包和我的应用程序,所以我可以完全控制代码。
所以,我测试了很多东西,但没有任何效果。
如果有人有想法谢谢
解决方案
Symfony 建议在 bundle 中使用手动服务定义,主要是为了避免每次重建缓存时不断扫描 bundle 的开销。但我认为看看使用 autowire/autoconfigure 创建一个可能可重用的捆绑包实际上需要什么可能会很有趣。尝试尽可能多地遵循捆绑包的最佳实践。
为了我自己的参考,我签入了一个完整的工作包示例。
最终,bundle 应该在它们自己的存储库中结束。但是,通过将捆绑包包含在应用程序中来开发捆绑包会更容易。这是我使用的方法。但重要的是不要尝试将您的应用程序源代码与捆绑源代码混合。这样做不仅具有挑战性,而且会使将您的捆绑包复制到它自己的存储库中变得困难。
所以我们从这样的目录结构开始:
project # Symfony application project
src: # Application source code
explorer-bundle # AD Explorer Bundle source code
ADExplorerBundle.php
正确设置命名空间也很重要。前缀确实应该是唯一的供应商标识符,以避免可能的命名冲突。在这种情况下,我们使用 AD。当然,由于 AD 可能有多个捆绑包,我们进一步细分为捆绑包特定标识符。
namespace AD\ExplorerBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class ADExplorerBundle extends Bundle
{
}
为了使自动加载工作,我们调整了 composer.json 文件。一旦包被转换成真正的作曲家包,这条线将不再需要。当然,您必须将 bundle 类添加到 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 文件的样子:
# 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']
为了简单起见,我只是将目标目录作为参数。您可能想要进行实际的捆绑配置并让应用程序能够设置它。但这超出了这个答案的范围。
为了测试,我选择创建一个命令。我发现它比尝试刷新浏览器更容易。
// 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;
}
}
就是这样。
推荐阅读
- javascript - 如何合并复选框和日期选择器的结果
- swift - 苹果电视上的 .ism/manifest 格式
- django - 不同域和平台之间的单点登录
- android - Firebase setCurrentScreen() 作为第一个事件没有记录正确的值
- yii2 - Codeception:使用夹具测试基于 Yii2 的应用程序会导致“连接过多”错误
- java - 如果我们保持空闲一段时间,则在连接到 Azure MSSQL DB 时,Spring Boot 应用程序中的数据库连接将关闭
- android - 使用 Paint.getTextBounds 时如何考虑换行
- android - Android Studio 3.1 设备上没有剩余空间
- javascript - Fabric.js:在文本提交时,为每一行创建一个对象
- node.js - Mongoose 在复杂结构中查找/项目