我有一个类用来上传文件作为像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
<?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捆绑\服务
<?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
我真的不明白:
公共和可重复使用的Bundles 公共包应该明确地配置它们的服务,而不是依赖于自动装配。自动装配依赖于容器中可用的服务,而包对它们包含在其中的应用程序的服务容器没有控制权。您可以在公司内构建可重用的包时使用自动装配,因为您可以完全控制所有代码。
我认为这没关系,因为这是我的包和我的应用程序,所以我可以完全控制代码。
所以,我测试了很多东西,但都没有用。
如果有人有主意的话谢谢
发布于 2020-04-14 15:42:44
Symfony建议在包中使用手动服务定义,主要是为了避免每次重建缓存时不断扫描包的开销。但是,我认为,使用自动配置/自动配置来创建一个潜在的可重用包可能会很有趣。我试着尽可能多地跟踪捆绑最佳实践。
作为我自己的参考,我签了一个完全工作束示例。
最终,包应该在它们自己的存储库中结束。但是,通过将包封装在应用程序中,可以更容易地开发包。这就是我使用的方法。但是,重要的是不要试图将应用程序源代码与包源代码混合。这样做不仅具有挑战性,而且很难将您的包复制到它自己的存储库中。
因此,我们从这样的目录结构开始:
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文件。一旦将包转换成真正的composer包,就不再需要这一行了。当然,您必须将包类添加到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;
}
}仅此而已。
https://stackoverflow.com/questions/61173574
复制相似问题