【问题标题】:Symfony2 Service with an unique instance具有唯一实例的 Symfony2 服务
【发布时间】:2024-04-25 20:20:01
【问题描述】:

我需要一些帮助:

我有以下服务:

services.yml 中的服务配置

服务:

xpad.producto_repository:
     class: Xpad\ProductoBundle\Entity\ProductRepository
     factory_service: doctrine.orm.clientes_entity_manager
     factory_method: getRepository
     arguments:
         - Xpad\ProductoBundle\Entity\Product


backend_cliente.producto_filters:
     class: Xpad\BackendClienteBundle\Filters\ProductFilters
     calls:
         - [setRepository, ["@xpad.producto_repository="]]
     scope: container

并且 backend_cliente.producto_filters 的类是:

namespace Xpad\BackendClienteBundle\Filters;

use Xpad\ProductoBundle\Entity\ProductRepository;

class ProductFilters
{
    private $_queryBuilder;


    public function getQueryBuilder()
    {
        return $this->_queryBuilder;
    }

    public function setQueryBuilder($queryBuilder)
    {
        $this->_queryBuilder = $queryBuilder;
    }

    public function setRepository(ProductRepository $productRepository = null)
    {
        if($this->_queryBuilder == null)
        {
            $this->_queryBuilder = $productRepository->createQueryBuilder('p');
        }
    }
}

并且我在我的一个控制器中执行了以下操作:

class ProductController extends Controller
{ 
 ............
    public function indexAction(Request $request)
    {
      //SOME CODE

       $service_filter = $this->container->get('backend_cliente.producto_filters');
       $queryBuilder = $service_filter->getQueryBuilder();

      //SOME OTHER CODE
    }

我的问题是:每当执行 indexAction 时,我都会获得 backend_cliente.producto_filters 服务的新实例,但我不知道为什么。我需要作为单例的唯一实例,因为 A 具有 $_queryBuilder 属性,并且我需要获取它的值,只需在需要时修改它的值即可;

请帮助我不知道我做错了什么。

【问题讨论】:

  • 您是否希望您的实例能够在多个 Web 请求中存活,因为这不会发生。或者你是在向 indexAction 发出一堆子请求吗?顺便说一句,您的服务名称“@xpad.producto_repository=”中有一个 =。因此,您发布的代码将无法按预期工作。

标签: symfony service scope singleton


【解决方案1】:

您必须将类用作服务吗?

为什么不使用单例而不使用服务?像这样:

namespace Xpad\BackendClienteBundle\Filters;

use Xpad\ProductoBundle\Entity\ProductRepository;

class ProductFilters { 
    private $_queryBuilder;
    private static $reference = null;

    public function getInstance(){
        if (self::$reference === null)
            self::$reference = new ProductFilters();
        return self::$reference;
    }

    private function __construct(){}

    public function getQueryBuilder()
    {
        return $this->_queryBuilder;
    }

    public function setQueryBuilder($queryBuilder)
    {
        $this->_queryBuilder = $queryBuilder;
    }

    public function setRepository(ProductRepository $productRepository = null)
    {
        if($this->_queryBuilder == null)
        {
            $this->_queryBuilder = $productRepository->createQueryBuilder('p');
        }

    }
}

然后调用它:

...
$filter = ProductFilters::getInstance();
...

【讨论】:

  • 很抱歉投了反对票,但 Symfony 2 确实是围绕依赖注入和服务构建的。大多数服务都是单例的。确实没有理由在 Symfony 2 中明确地创建单例。此外,它确实没有回答这个问题。我很确定@gestherhf 实际上希望他的实例能够在多个 Web 请求中生存。这当然不会发生。
  • 你在哪里读到“Symfony 2 真的是围绕依赖注入和服务构建的”?框架支持该功能这一事实并不意味着它是像 Spring 这样的“基于依赖注入的框架”......我不知道你是否真的使用 PHP,但无论如何你不能这样做在多个网络请求中生存!!您只能模拟,这不是 Java 或 C#,当您调用脚本时,脚本总是有开始和结束!他只想要一个 Singleton,也许他不知道他可以在服务之外做到这一点......
  • 他要求一个单身人士,但如果你解析他的问题,那么我认为很明显他想要在请求之间存活的东西。我们都知道,这对 php 来说是一个挑战。顺便说一句,您的单例示例忽略了对存储库的需求。这是一个很好的例子,说明为什么应该使用依赖注入容器(如果可用)。
  • 我不知道怎么会有人反对 Symfony 2 框架是围绕依赖注入和服务构建的。开箱即用的基本框架定义了 350 多种服务。如果你看一下代码,几乎每个类都注入了它的依赖项。