ZF2: Плагин Forward контроллера не работает. Как заставить это работать?

Мне нужно перенаправить запрос ajax другому методу Action текущего контроллера. Я использую плагин Forward, но он не работает. В руководстве есть пример того, как использовать плагин Forward:

$foo = $this->forward()->dispatch('foo', array('action' => 'process')); 
return array(
    'somekey' => $somevalue,
    'foo'     => $foo, 
);

Мой код:

// From Ajax on the page. I apply to the indexAction of FooController,
// I use RegEx route
xhr.open('get', '/fooindex', true);


// My Controller
namespace Foo\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

// I extend the AbstractActionController, the manual says it's important for the Forward Plugin to work
class FooController extends AbstractActionController {

    // This is the action I send my request from Ajax
    public function indexAction() {

        // if the request if Ajax request I forward the run to the nextAction method
        if ($this->getRequest()->isXmlHttpRequest()) {

            // I do as manual says
            $rs = $this->forward()->dispatch('FooController', array('action' => 'next'));
        }
    }


    public function nextAction() {

        // And I just want to stop here to see that the Forward Plugin works
        // But control doesn't reach here 
        exit('nextAction');
    }
}

Ошибка, которую я получаю в консоли:

GET http://test.localhost/fooindex 500 (Internal Server Error) 

Если я не использую Forward, все работает нормально, запрос приходит к indexAction просто хорошо. Только Форвард выбрасывает ошибку.

Из руководства о плагине Forward:

Чтобы плагин Forward работал, вызывающий его контроллер должен быть ServiceLocatorAware; в противном случае плагин не сможет получить настроенный и внедренный экземпляр запрошенного контроллера.

Из руководства о доступных контроллерах:

Реализация каждого из вышеперечисленных интерфейсов является уроком избыточности; Вы не будете часто хотеть сделать это. Таким образом, мы разработали два абстрактных базовых контроллера, которые вы можете расширить, чтобы начать работу.

AbstractActionController реализует каждый из следующих интерфейсов:

Zend \ Stdlib \ DispatchableInterface Zend \ Mvc \ InjectApplicationEventInterface Zend \ ServiceManager \ ServiceLocatorAwareInterface Zend \ EventManager \ EventManagerAwareInterface

Так что мой FooController продолжается AbstractActionController, который реализует ServiceLocatorAwareInterfaceТак что Форвард должен работать, но это не так. Что я упустил? Как заставить это работать?

4 ответа

Вы должны помнить, что диспетчерский плагин получает диспетчер для отправки от менеджера сервиса по имени. Поэтому вы должны использовать правильное имя, а не только имя класса.

Посмотрите в своей конфигурации массив controllers.invokables. В нем должно быть указано, какое имя сервиса соответствует какому FQCN.

Возможно, вас зовут IS FooController, а потом забудьте, что я только что сказал

Попробуй это:

class FooController extends AbstractActionController {
    public function indexAction() {
        return $this->forward()->dispatch('Foo',
            array(
                'action' => 'process',
                'somekey' => $somevalue,
            ));
    }
}

Ваш файл module.config.php выглядит так:

'controllers' => array(
    'invokables' => array(
        'Foo' => 'Foo\Controller\FooController',   // <----- Module Controller
    ),
),

   'router' => array(
        'routes' => array(
            'foo' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '/foo[/:action][/:id]',  // <---- url format module/action/id
                    'constraints' => array(
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                    ),
                    'defaults' => array(
                        'controller' => 'Foo',  // <--- Defined as the module controller
                        'action'     => 'index',                   // <---- Default action
                    ),
                ),
            ),
        ),
    ),

Вы должны использовать полностью определенное имя при вызове контроллера, так что 'FooController' также должен находиться в пространстве имен. Также вы должны добавить контроллер в список активируемых файлов в файлах конфигурации модуля, например:

return array(
    'controllers' => array(
        'invokables' => array(
             'FooController' => 'Namespace/Controller/FooController'
              ...
         ),
    )
 )

Попробуй это:

class FooController extends AbstractActionController {
    public function indexAction() {
        return $this->forward()->dispatch('Bar\Controller\Bar',
            array(
                'action' => 'process',
                'somekey' => $somevalue,
            ));
    }
}

здесь доступно: 'Bar\Controller\Bar' => 'Bar\Controller\Bar'