如何在Symfony3控制器之外调用服务?来自Repository

时间:2016-05-08 04:21:33

标签: symfony-forms symfony

我今天有两个问题。这是详细的,因为太多其他回复依赖于假设而且还不够详细。我希望这是详细的,并将能够帮助许多开发人员。

第一。下面的代码指出了我的真实问题。如何在控制器之外调用服务,因为$ this-> get()方法仅在控制器内部?这不在任何文档或KNP大学的服务教程中。

第二。根据我的阅读,根据一些,并非所有,如果你从任何地方调用存储库,它应该自动实例化实体存储库。我认为不是这样。告诉我我是对还是错。

请参阅以下内容....

我的默认控制器,它直接调用一个类,让它做一些工作。举个例子,我用服务和传统的OO方法调用它:

<?php
//  src/AppBundle/Controller/DefaultController.php
//  Here is where I am starting.  There is a service 
//  and there is a conventional OO call.
//  Both should invoke the same thing.

namespace AppBundle\Controller;

use AppBundle\Service;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {

        //  Step 1.... Do a little of this.
        //  Step 2.... Do some of that.
        //  Step 3.... Call another class to do some logic and it will
        //  eventually call a query...

        //  Invoking my service
        $obj_via_service = $this->get('app.services.process_question');
        $result1 = $obj_via_service->submitQuestion();

        //  Invoking via Namespace and Call
        $obj_via_new = new Service\ProcessQuestion();
        $result2 = $obj_via_new->submitQuestion();

        dump($result1);
        dump($result2);
        die();
    }
}

我的Service.yml文件。

#   src/app/config/services.yml
parameters:

services:
    app.services.process_question:
        class: AppBundle\Service\ProcessQuestion

    app.rep.geo_state:
        class: AppBundle\Entity\GeoStateRepository
        arguments: ['@doctrine.orm.entity_manager']

这是我的班级,正在为我工​​作。我希望能够在^^之上调用第二个服务^^,但我不能,因为我不能在控制器之外使用 $ this-&gt; get()

<?php
//  src/AppBundle/Service/ProcessQuestion.php
namespace AppBundle\Service;

class ProcessQuestion
{
    public function submitQuestion()
    {
        //  Step 1.... Do this.
        //  Step 2.... Do that.
        //  Step 3.... Query for some data...

        //  Invoke my repository class via a Service Call....
        //  but I cannot do that because 'get' is a part of the
        //  controller...
        $obj_via_service = $this->get('app.rep.geo_state');
                           **^^                         ^^**
                           **^^ This is what won't work ^^**

        $results = $obj_via_service->selectStates();

        return $results;
    }
}

我的存储库类...请记住,我还没有达到这个类,但是我把它放在这里,以便其他新的Symfony 3开发人员可以看到这个。

<?php
//  src/AppBundle/Repository/GeoState.php
//  My Repository Class where I want to do some queries...
namespace AppBundle\Repository;

use Doctrine\ORM\EntityRepository;

class GeoStateRepository extends EntityRepository
{
    /**
     * @Mapping\Column(type="string")
     */
    private $em;

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

    public function selectStates()
    {
        $sql = "SELECT * FROM geo_state";
        return $this->getEntityManager()->createQuery($sql)->getResult();
    }
}

为什么这么难找到一个例子?此外,我已经关注了一堆Symfony 2.x文档,有时候很难将细微差别移植到Symfony 3中。

我认为Fabian过多地将2.x的文档用于3.x并且在新开发者级别和硬核开发人员级别之间没有任何关于编码的好例子。如果您在Sensio并阅读此内容,请记住,我们需要覆盖中间地带,并且大部分屏幕录像都在那里,而且许多更好的文档都不是英文版。

1 个答案:

答案 0 :(得分:1)

您应该阅读有关Dependency Injection.

的更多信息

Symfony非常擅长这一点。

关于在app.rep.geo_state服务中使用app.services.process_question服务的问题。

在Symfony / DI术语中,它可以被称为将服务注入另一个服务。

documentation如何做到这一点非常好。

这是如何做到的。

services:
    app.services.process_question:
        class: AppBundle\Service\ProcessQuestion
        arguments: ['@app.rep.geo_state']

    app.rep.geo_state:
        class: AppBundle\Entity\GeoStateRepository
        arguments: ['@doctrine.orm.entity_manager']

在课堂上

<?php
//  src/AppBundle/Service/ProcessQuestion.php
namespace AppBundle\Service;
use AppBundle\Entity\GeoStateRepository;

class ProcessQuestion
{

    private $geoRepository;

    public function __construct(GeoStateRepository $geoRepository)
    {
        $this->geoRepository = $geoRepository;
    }

    public function submitQuestion()
    {
        //now you can call $this->geoRepository 
    }
}

另请注意,$this->get()只是Symfony基本Controller类提供的快捷功能,用于访问容器。

要了解有关DI的更多信息,您可以在his blog中阅读Fabian关于此的优秀文章。