首页 文章

Symfony 4.0.0服务参数连接错误

提问于
浏览
1

我正在制作一个基于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根本没有做太多 .

昨天我花了整整一天的时间尝试一些东西并查找文档,但没有成功 . 非常感谢您的帮助 .

如果您需要更多代码,我将很乐意提供 .

再次感谢!

4 回答

  • 0

    您是否尝试过执行错误消息所说的内容?

    方法“__construct()”的参数“$ name”必须具有类型提示或显式赋予值

    $name$type 都没有方法签名中的类型提示 . 尝试将方法签名更改为:

    public function __construct(FormFactoryInterface $formFactory, string $name, string $type, array $validationGroups = null)
    

    Edit

    另一种可能是您在定义此参数之前尝试在服务定义中使用 %boa_product.create.form.name% param .

  • 0

    我的问题最终得到了解决 . 我认为这是由于我试验了服务文件,但在测试结果之前没有清除缓存 . 因此我认为我的服务没有加载(因为结果显然没有改变) .

    我最终把我的Bundle放在一个单独的存储库中,并通过composer将它包含在项目中 . 我还重写了YAML中的配置文件而不是XML,因为我觉得它更容易阅读 .

    这样我就可以更好地控制它的调试,最终我摆脱了错误 .

    使用服务时最重要的是每次进行更改时都要运行 php bin/console cache:clear .

    谢谢您的帮助

  • 0

    boa_product.create.controller 作为服务的定义中,您缺少 key attribute 作为参数 . 尝试:

    <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$productManagerCreateController 构造函数中的参数 .

    在您的扩展程序中,为 App\Boa\ProductBundle\Model\ProductManagerInterface 定义 alias

    $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" />
    
  • 0

    如果您使用接口,则需要覆盖该接口别名或添加FormFactory的显式定义 .

    查看:

    Working with Interfaces

相关问题