【问题标题】:Symfony2 - Access repository from random classSymfony2 - 从随机类访问存储库
【发布时间】:2015-02-18 01:27:38
【问题描述】:

我计划在获得更多知识后采取不同的做法,但现在我正在努力让一些事情发挥作用。

我已经把所有东西都设置好了。将警报添加到数据库后,我需要对该警报执行一些操作。所以我做了一个EventListener,它基本上在我的随机类中调用了我需要的函数

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Nick\AlertBundle\Entity\AvailabilityAlert;
use Nick\AlertBundle\Service\ApiService;

class AvailabilityAlertListener
{

    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if ($entity instanceof AvailabilityAlert) {
            $api = new ApiService();
            $api->addFlightsAction($entity);
        }
    }
}

现在 ApiService 类目前并不真正适合我的设计,它现在只是一个随机类。我将 $entity 传递给它,以便我可以对其执行一些操作。

我需要执行的一项操作涉及实体自定义存储库类。所以我的类 ApiService 看起来像这样

<?php

namespace Nick\AlertBundle\Service;

class ApiService
{
    public function executeTerminalCommand($entity){

        $em = $this->getDoctrine()->getManager();
        $worldspanCommand = $em->getRepository("NickAlertBundle:AvailabilityAlert")->getSpecificAlert($entity->getId());
    }
}

所以在 EventListender 中,我调用上述函数并将实体传递给它。此函数应调用我的自定义存储库类中的函数。有了上述,我得到了错误

试图在类上调用方法 getDoctrine Nick\AlertBundle\Service\UapiService(500 内部服务器错误)

我将如何开始这项工作?

谢谢

【问题讨论】:

  • 首先:`$api->addFlightsAction($entity);`和public function executeTerminalCommand($entity){ ... }有不同的签名;-)
  • 对不起,那是我的错误,我正在削减课程,所以我没有发布所有代码。

标签: symfony


【解决方案1】:

两种解决方案

第一个解决方案(推荐)

ApiService 设为 symfony2 服务并注入 EntityManager ServiceContainer(避免ServiceCircularReferenceException)(construct injectionsetter injection),以便您可以直接使用它。为此,您还需要将此新服务注入您的事件侦听器。

您可以按如下方式执行此操作(也可以查看 Edit)

1) 将您的ApiService 类设为服务

your_bundle_name.api_service:
        class: Path\To\Your\Api\Service\Class
        arguments: [@doctrine.orm.entity_manager] #i.e.: constructor injection

2) 修改你的 ApiService

<?php

namespace Nick\AlertBundle\Service;

use Doctrine\ORM\EntityManager; //!IMPORTANT
class ApiService
{
    protected $em:

    public function __construct(EntityManager $em) 
    {
        $this->em = $em;
    }

    public function executeTerminalCommand($entity)
    {
        $worldspanCommand = $this->em->getRepository("NickAlertBundle:AvailabilityAlert")->getSpecificAlert($entity->getId());
    }
}

这可能会导致ServiceCircularReferenceException我的解决方案是更改点1)和2)如下

1) 将您的ApiService 类设为服务

your_bundle_name.api_service:
        class: Path\To\Your\Api\Service\Class
        arguments: [@service_container]

2) 修改你的ApiService

<?php

namespace Nick\AlertBundle\Service;

use Symfony\Component\DependencyInjection\ContainerInterface as Container; //!IMPORTANT
class ApiService
{
    protected $sc;

    public function __construct(Container $sc) 
    {
        $this->sc = $sc;
    }

    public function executeTerminalCommand($entity)
    { 
        $em = $this->sc->get('doctrine.orm.entity_manager');
        $worldspanCommand = $em->getRepository("NickAlertBundle:AvailabilityAlert")->getSpecificAlert($entity->getId());
    }
}

3) 修改您的事件侦听器服务以接受服务容器作为实例化的参数

your_listner_name:
    class: Path\To\Your\Listener\Class
    arguments: [@your_bundle_name.api_service]
    tags:
        - { name: doctrine.event_listener, event: postPersist }

4) 修改你的事件监听类

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Nick\AlertBundle\Entity\AvailabilityAlert;
use Nick\AlertBundle\Service\ApiService;

class AvailabilityAlertListener
{
    protected $api_service;

    public function __construct(ApiService $api_service)
    {
        $this->api_service = $api_service;
    }

    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if ($entity instanceof AvailabilityAlert) {
            $this->api_service->addFlightsAction($entity);
        }
    }
}

第二种解决方案

将服务容器直接注入您的侦听器并让您的ApiService 类接受实体管理器作为参数

你可以这样做

1) 修改您的 ApiService 类以使其接受实体管理器

<?php

namespace Nick\AlertBundle\Service;

use Doctrine\ORM\EntityManager; //!IMPORTANT
class ApiService
{
    protected $em:

    public function __construct(EntityManager $em) 
    {
        $this->em = $em;
    }

    public function executeTerminalCommand($entity)
    {
        $worldspanCommand = $this->em->getRepository("NickAlertBundle:AvailabilityAlert")->getSpecificAlert($entity->getId());
    }
}

2) 如下修改你的事件监听器类

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Nick\AlertBundle\Entity\AvailabilityAlert;
use Nick\AlertBundle\Service\ApiService;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;


class AvailabilityAlertListener
{
    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if ($entity instanceof AvailabilityAlert) {
            $entity_manager = $args->getEntityManager();
            $api = new ApiService($entity_manager);
            $api->addFlightsAction($entity);
        }
    }
}

【讨论】:

  • 感谢您的精彩解释。我正在浏览文档并且并没有真正理解服务,但是在您的代码中看到它我可以确切地看到发生了什么。我确实遇到了一个错误,但我现在正在尝试解决它;检测到服务“doctrine.dbal.default_connection”的循环引用,路径:“doctrine.dbal.default_connection”。
  • @NickPrice:你采用了什么解决方案?
  • 我关注的是第一个。这就是我打算在未来做的方式,因为我知道这应该是一项服务。
  • @NickPrice:你能粘贴完整的错误堆栈或堆栈跟踪(请粘贴)
  • @NickPrice:看看我的更新,我没有尝试过,但如果我理解正确,这应该可以工作
猜你喜欢
  • 1970-01-01
  • 2014-12-14
  • 2015-04-11
  • 2020-05-09
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 2020-12-21
  • 2015-01-18
相关资源
最近更新 更多