【发布时间】:2018-02-15 09:25:24
【问题描述】:
我正在制作基于 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 并没有做太多事情。
昨天我花了一整天的时间尝试一些东西并查找文档,但没有成功。非常感谢您的帮助。
如果您需要更多代码,我很乐意提供。
再次感谢!
【问题讨论】:
-
很确定您需要在服务定义文件中设置 _defaults 才能使自动装配工作。 symfony.com/doc/current/…我自己没试过所以可能是错的。
标签: php symfony dependency-injection symfony4