Symfony自动装配不会在指定路径中获取服务

时间:2017-06-28 15:13:36

标签: symfony autowired

尝试升级现有的Symfony 3.3.2项目以使用自动装配 按照此处的说明操作:https://symfony.com/doc/current/service_container/3.3-di-changes.html#content_wrapper

对我来说不起作用的是能够将目录中的所有服务设置为公共。

重要提示:我的services.yml文件位于src / SiteBundle / Resources / config中,而不是app / config。

# src/SiteBundle/Resources/config/services.yml
services:
  _defaults: 
    autowire: true
    autoconfigure: true
    public: false

  SiteBundle\Service:
    resource: '../../Service'
    public: true

  CustomerOrderMasterRepository:
    class: Doctrine\ORM\EntityRepository
    factory: ["@doctrine.orm.entity_manager", get_repository]
    arguments:
      - SiteBundle\Entity\CustomerMaster

  SiteBundle\Service\CustomersService:
    arguments:
      - '@doctrine.orm.entity_manager'
      - '@CustomerMasterRepository'

如果我然后进行控制台调试:container | grep -i服务,它只显示输出头和Symfony服务容器。没有选择src / SiteBundle / Service目录中的类。

  

Symfony Container公共服务服务ID
  班级名称service_container
  的Symfony \组件\ DependencyInjection \ ContainerInterface

如果我添加--show-private,则显示它们(以及许多其他内容)。

  

Symfony Container公共和私人服务服务ID
  班级名称
  1_bcf140bb848ef41617942628c8525b4872574e826d00fee6aaabbf2ede89fbb8
  Symfony的\分量\ DependencyInjection \服务定位
  PSR \集装箱\ ContainerInterface
  " service_container"的别名   SiteBundle \服务\ CustomerOrdersService
  SiteBundle \服务\ CustomerOrdersService
  SiteBundle \服务\ CustomersService
  SiteBundle \服务\ CustomersService
  SiteBundle \服务\ InventoryItemsService
  SiteBundle \服务\ InventoryItemsService
  SiteBundle \服务\ VendorOrdersService
  SiteBundle \服务\ VendorOrdersService
  SiteBundle \服务\ VendorsService
  SiteBundle \服务\ VendorsService
  SiteBundle \服务\ WorkOrdersService
  SiteBundle \服务\ WorkOrdersService
  Symfony的\分量\ DependencyInjection \ ContainerInterface
  " service_container"的别名argument_resolver.service
  Symfony的\分量\ HttpKernel \控制器\ ArgumentResolver \ ServiceValueResolver   routing.loader.service
  Symfony的\分量\路由\装载机\ DependencyInjection \ ServiceRouterLoader   security.authentication.rememberme.services.abstract
  security.authentication.rememberme.services.persistent
  Symfony的\分量\安全\ HTTP \与rememberMe \对PersistentTokenBasedRememberMeServices   security.authentication.rememberme.services.simplehash
  Symfony的\分量\安全\ HTTP \与rememberMe \ TokenBasedRememberMeServices   service_container
  Symfony的\分量\ DependencyInjection \ ContainerInterface
  service_locator.1712c3a50d1ec2c742b2ead0f03bb76c
  Symfony的\分量\ DependencyInjection \服务定位
  service_locator.26ac001b3ede28481ac0de703666b4d7
  Symfony的\分量\ DependencyInjection \服务定位
  service_locator.39e66930232432ca5ba91e98fdd8a17b
  Symfony的\分量\ DependencyInjection \服务定位
  service_locator.6f24348b77840ec12a20c22a3f985cf7
  Symfony的\分量\ DependencyInjection \服务定位
  service_locator.8925f20c49cbd61fcb37adf8c595459e
  Symfony的\分量\ DependencyInjection \服务定位
  service_locator.b8d2046fb854cde05549fb309e1a80d2
  别名   " 1_bcf140bb848ef41617942628c8525b4872574e826d00fee6aaabbf2ede89fbb8"
  service_locator.ceb8bbb9f48e8bfd1c8ec2d209eabdca
  的Symfony \组件\ DependencyInjection \服务定位

如果我注释掉SiteBundle \ Service \ CustomerService定义,则debug:container命令会抛出此异常:

  

PHP致命错误:未捕获   Symfony的\分量\ DependencyInjection \异常\ AutowiringFailedException:   无法自动服务" SiteBundle \ Entity \ CustomerMasterRepository":   争论" $ em"方法   "学说\ ORM \ EntityRepository :: __构建体()"必须有一个类型提示   或明确给出一个值。   坦率地说,我不能做出头脑或尾巴。

连连呢? 感谢。

2 个答案:

答案 0 :(得分:1)

这是主要问题:

  

PHP致命错误:未捕获的Symfony \ Component \ DependencyInjection \ Exception \ AutowiringFailedException:无法自动装配服务“SiteBundle \ Entity \ CustomerMasterRepository”:方法“Doctrine \ ORM \ EntityRepository :: __ construct()”的参数“$ em”必须具有类型提示或明确赋予值。坦率地说,我无法做出头脑或尾巴。

当您使用EntityRepository作为服务时,会发生这种情况,但是继承自Doctrine BaseRepository。这种组合永远不会发生。

存储库应该使用组合来获取Doctrine 像这样:

<?php

namespace AppBundle\EntityRepository;

use AppBundle\Entity\Channel;
use Doctrine\ORM\EntityManager;

class ChannelRepository
{
    private $repository;

    public function __construct(EntityManager $entityManager)
    {
        $this->repository = entityManager->getRepository(Channel::class);
    }

    public function getOneByName(string $name)
    {
        return $this->repository->findOneBy(['name' => $name]);
    }
}

如果您想了解更多信息,可以发布包含精彩代码示例的帖子:How to use Repository with Doctrine as Service in Symfony

答案 1 :(得分:0)

要使自定义存储库正常工作,我必须覆盖__construct方法以提供EntityManagerClassMetadata,如下所示:

应用程序/配置/ services.yml

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    app.repository.channel:
        class: \AppBundle\EntityRepository\ChannelRepository

的src /的appbundle / EntityRepository / ChannelRepository.php:

<?php

namespace AppBundle\EntityRepository;

use AppBundle\Entity\Channel;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;

class ChannelRepository extends RepositoryFactory
{
    public function __construct(EntityManager $entityManager)
    {
        parent::__construct($entityManager, new ClassMetadata(Channel::class));
    }

    public function getOneByName(string $name)
    {
        return $this->findOneBy(['name' => $name]);
    }
}

的src /的appbundle /实体/ Channel.php

<?php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="channel")
 * @ORM\Entity(repositoryClass="\AppBundle\EntityRepository\ChannelRepository")
 *
 */
class Channel
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
}