我正在制作一个基于FOSUserbundle的ProductBundle,但我在使用FormFactory和ProductManager类的服务参数自动装配时遇到了麻烦。
我一直收到错误:
无法自动装配服务“App \ Boa \ ProductBundle \ Form \ Factory \ FormFactory”:方法“__construct()”的参数“$ name”必须具有类型提示或明确赋予值。
FormFactory类:
namespace App\Boa\ProductBundle\Form\Factory;
use Symfony\Component\Form\FormFactoryInterface;
class FormFactory implements FactoryInterface
{
/**
* @var FormFactoryInterface
*/
private $formFactory;
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $type;
/**
* @var array
*/
private $validationGroups;
/**
* FormFactory constructor.
*
* @param FormFactoryInterface $formFactory
* @param string $name
* @param string $type
* @param array $validationGroups
*/
public function __construct(FormFactoryInterface $formFactory, $name,
$type, array $validationGroups = null)
{
$this->formFactory = $formFactory;
$this->name = $name;
$this->type = $type;
$this->validationGroups = $validationGroups;
}
/**
* {@inheritdoc}
*/
public function createForm(array $options = array())
{
$options = array_merge(array('validation_groups' => $this->validationGroups), $options);
return $this->formFactory->createNamed($this->name, $this->type, null, $options);
}
}
create.xml(位于App \ Boa \ ProductBundle \ Resources \ config)
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="boa_product.create.form.factory" class="App\Boa\ProductBundle\Form\Factory\FormFactory" public="true">
<argument type="service" id="form.factory" />
<argument key="$name">%boa_product.create.form.name%</argument>
<argument key="$type">%boa_product.create.form.type%</argument>
<argument>%boa_product.create.form.validation_groups%</argument>
</service>
<service id="boa_product.create.form.type" class="App\Boa\ProductBundle\Form\Type\CreateFormType">
<tag name="form.type" alias="boa_product_create" />
<argument key="$class">%boa_product.model.product.class%</argument>
</service>
<service id="boa_product.create.controller" class="App\Boa\ProductBundle\Controller\CreateController" public="true">
<argument type="service" id="boa_product.create.form.factory" />
<argument type="service" id="boa_product.product_manager" />
</service>
</services>
扩展名:
<?php
namespace App\Boa\ProductBundle\DependencyInjection;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class BoaProductExtension extends Extension
{
/**
* @var array
*/
private static $doctrineDrivers = array(
'orm' => array(
'registry' => 'doctrine',
'tag' => 'doctrine.event_subscriber',
)
);
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
//$Yamlloader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');
if ('custom' !== $config['db_driver']) {
if (isset(self::$doctrineDrivers[$config['db_driver']])) {
$loader->load('doctrine.xml');
$container->setAlias('boa_product.doctrine_registry', new Alias(self::$doctrineDrivers[$config['db_driver']]['registry'], false));
} else {
$loader->load(sprintf('%s.xml', $config['db_driver']));
}
$container->setParameter($this->getAlias().'.backend_type_'.$config['db_driver'], true);
}
if (isset(self::$doctrineDrivers[$config['db_driver']])) {
$definition = $container->getDefinition('boa_product.object_manager');
$definition->setFactory(array(new Reference('boa_product.doctrine_registry'), 'getManager'));
}
$container->setAlias('boa_product.product_manager', new Alias($config['service']['product_manager'], true));
$container->setAlias('App\Boa\ProductBundle\Model\ProductManagerInterface', new Alias('boa_product.product_manager', true));
$this->remapParametersNamespaces($config, $container, array(
'' => array(
'db_driver' => 'boa_product.storage',
'model_manager_name' => 'boa_product.model_manager_name',
'product_class' => 'boa_product.model.product.class',
),
));
$this->loadCreate($config['create'], $container, $loader);
}
/**
* @param array $config
* @param ContainerBuilder $container
* @param array $namespaces
*/
protected function remapParametersNamespaces(array $config, ContainerBuilder $container, array $namespaces)
{
foreach ($namespaces as $ns => $map) {
if ($ns) {
if (!array_key_exists($ns, $config)) {
continue;
}
$namespaceConfig = $config[$ns];
} else {
$namespaceConfig = $config;
}
if (is_array($map)) {
$this->remapParameters($namespaceConfig, $container, $map);
} else {
foreach ($namespaceConfig as $name => $value) {
$container->setParameter(sprintf($map, $name), $value);
}
}
}
}
/*
* @param array $config
* @param ContainerBuilder $container
* @param array $map
*/
protected function remapParameters(array $config, ContainerBuilder $container, array $map)
{
foreach ($map as $name => $paramName) {
if (array_key_exists($name, $config)) {
$container->setParameter($paramName, $config[$name]);
}
}
}
/**
* @param array $config
* @param ContainerBuilder $container
* @param XmlFileLoader $loader
*/
private function loadCreate(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
$loader->load('create.xml');
$this->remapParametersNamespaces($config, $container, array(
'form' => 'boa_product.create.form.%s',
));
}
}
因此,在阅读symfony的文档时,由于标量类型无法自动装配,因此获得此异常消息是正常的,但是当我拥有(我认为是)正确的xml文件并且手动连接服务时,我仍然会收到消息它们。
当我更改create.xml文件中的一个键时,例如将键“$ name”更改为“$ example”我收到以下消息:
无效服务“boa_product.create.form.factory”:方法“App \ Boa \ ProductBundle \ Form \ Factory \ FormFactory :: __ construct()”没有名为“$ example”的参数。检查您的服务定义。
所以我猜他们必须连接?然后,使用所有参数删除整个服务只会给我相同的旧异常
无法自动装配服务“App \ Boa \ ProductBundle \ Form \ Factory \ FormFactory”:方法“__construct()”的参数“$ name”必须具有类型提示或明确赋予值。
所以看起来我的xml根本没有做太多。
我昨天花了整整一天时间尝试一些东西并查找文档,但没有成功。非常感谢您的帮助。
如果您需要更多代码,我很乐意提供代码。
再次感谢!
答案 0 :(得分:0)
您是否尝试过执行错误消息所说的内容?
参数&#34; $ name&#34;方法&#34; __ construct()&#34;必须有一个类型提示或 明确给出一个值
$name
和$type
都没有方法签名中的类型提示。尝试将方法签名更改为:
public function __construct(FormFactoryInterface $formFactory, string $name, string $type, array $validationGroups = null)
修改强>:
另一种可能性是在定义此参数之前,您尝试在服务定义中使用%boa_product.create.form.name%
param。
答案 1 :(得分:0)
答案 2 :(得分:0)
在 boa_product.create.controller 作为服务的定义中,您缺少参数的键属性。尝试:
<service id="boa_product.create.controller" class="App\Boa\ProductBundle\Controller\CreateController" public="true">
<argument key="$formFactory" type="service" id="boa_product.create.form.factory" />
<argument key="$productManager" type="service" id="boa_product.product_manager" />
</service>
$ formFactory 和 $ productManager 是 CreateController 构造函数中的参数。
在您的扩展程序中,为 App \ Boa \ ProductBundle \ Model \ ProductManagerInterface 定义别名:
$container->setAlias('App\Boa\ProductBundle\Model\ProductManagerInterface', new Alias('boa_product.product_manager', true));
所以我想,你可以删除:
<argument key="$productManager" type="service" id="boa_product.product_manager" />
因为这将是自动装配的。
或者,您可以自动装配,a.k.a。也为 boa_product.create.form.factory 定义 App \ Boa \ ProductBundle \ Form \ Factory \ FactoryInterface 的别名。 how to aurowire services
添加:
<service id="App\Boa\ProductBundle\Form\Factory\FormFactory" alias="boa_product.create.form.factory" />
答案 3 :(得分:0)
我的问题最终得到了解决。我认为这是由于我试验了服务文件,但在测试结果之前没有清除缓存。因此我认为我的服务没有加载(因为结果显然没有改变)。
我最终把我的Bundle放在一个单独的存储库中,并通过composer将它包含在项目中。我还用YAML而不是XML重写了配置文件,因为我觉得它更容易阅读。
这样我就可以更好地控制它的调试,最终我摆脱了错误。
使用服务时最重要的是每次进行更改时都要运行php bin/console cache:clear
。
感谢您的帮助