Symfony2 передача данных между пакетами и контроллерами - PullRequest
5 голосов
/ 03 марта 2012

это скорее вопрос «лучшей практики», чем реальной проблемы:

Я работаю над проектом в Symfony 2, и я собрал пакет для обработки всех моих веб-сервисов. По сути, один контроллер получает некоторые данные JSON, отправляет их другому контроллеру для проверки их соответствия описанному формату, затем передает их другому контроллеру для обработки вызовов базы данных и в конечном итоге возвращает первоначальному контроллеру для возврата ответа JSON.

Я отправляю данные между контроллерами, делая что-то вроде этого:

$controller = new \Acme\myBundle\Controller\DefaultController;
$response = $controller->function();

Это работает правильно, но я продолжаю сталкиваться с одной проблемой. В контроллере я передаю данные мне нужно создать экземпляр AppKernel и вызвать функцию загрузки для работы любой функции Symfony. Мне это кажется немного глупым, что наводит меня на мысль, что я все делаю неправильно.

Любые предложения или советы приветствуются!

EDIT / UPDATE Спасибо всем за комментарии. Я настроил свои контроллеры как сервисы, сервисы работают, но мне все еще нужно вручную загружать / создавать экземпляр ядра, когда я вызываю сервис изнутри сервиса.

#config.yml
# API Services
services:
service.handler:
    class: Acme\APIBundle\Controller\ServicesController
    arguments:
        container: "@service_container"

service.definitions:
    class: Acme\APIBundle\Controller\DefinitionController
    arguments:
        container: "@service_container"

Из другого контроллера пакетов я могу без проблем вызвать функцию из любой из этих служб:

 $test = $this->get("service.handler")->testFunction();
 $test2 = $this->get("service.definitions")->anotherTestFunction();

Если у меня действительно возникает проблема, то если я вызываю функцию внутри одного сервиса, а затем пытаюсь вызвать другой сервис из этого сервиса, я получаю следующую ошибку PHP

Fatal error: Call to a member function get() on a non-object in /vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 188

Я могу избежать этой ошибки, используя эту функцию и вызывая ее вместо использования $ this

    public function bootKernel(){
//boot kernel
    $controller = new \Acme\myBundle\Controller\DefaultController; 
    $kernel = new \AppKernel('dev', true);$kernel->loadClassCache(); 
    $kernel->boot(); 
    $controller->setContainer($kernel->getContainer());
    return($controller);    
}

Полагаю, мое решение "работает", но оно, безусловно, не кажется эффективным способом решения проблем.

РЕДАКТИРОВАТЬ 2: Если я добавлю это в начало класса, то изменю вызов службы, это, кажется, работает ... Все еще не уверен, что это лучший способ сделать что-то.

    protected $container;

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

Ответы [ 2 ]

10 голосов
/ 05 марта 2012

Я бы пошел по маршруту «контроллер как услуга» с вышеприведенным. Скажем, вам нужно вызвать 3 метода как часть вашей обработки. Давайте назовем их foo(), bar() и something(). Каждый из этих методов находится в отдельных контроллерах:

namespace Acme\DemoBundle\Controller;

class FooController
{
    public function __construct($container, ...)
    {
        $this->container = $container;
        // ... deal with any more arguments etc here
    }

    public function foo($params)
    {
        // ...
        return $x;
    }

    protected function get($service)
    {
        return $this->container->get($service);
    }
}

То же самое для методов bar() и something(), каждый в своем контроллере. Затем добавьте их в свое приложение в качестве службы. Например, в вашем config.yml (доступны другие методы):

services:
    my.foo.service:
        class: Acme\FooBundle\Controller\FooController
        arguments:
            container: "@service_container"

См. Документы Symfony для подробнее о том, как вы можете создать эту запись, включая внедрение любых зависимостей, таких как менеджер сущностей или аналогичный. Теперь вы можете получить экземпляр этого из контейнера:

public function yourMainAction()
{
    // ...

    $newData = $this->get("my.foo.service")->fooAction($someData);

    // ...

    return new Response(json_encode($newData), ...);
}

Аналогично для BarController и SomethingController. Теперь преимущество заключается в том, что этот сервис можно сделать доступным в любой точке вашего приложения (будь то через контейнер, как указано выше, или как внедренный сервис), между пакетами, без необходимости вручную создавать экземпляр класса и предоставлять любые зависимости.

Для получения дополнительной информации о контейнере и т. Д. В документах Symfony есть хороший раздел (см. Ссылку выше).

Редактировать : Изменен пример кода, чтобы включить детали передачи аргументов в сервис. Также добавлен удобный get() метод для извлечения услуг из контейнера.

1 голос
/ 05 марта 2012

Предлагаю использовать контроллер как сервис .

...