2

I need to forward the ajax request to the other Action method of current controller. I use the Forward plugin but it doesn't work. There is an example in the manual about how to use the Forward Plugin:

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

My code:

// 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');
    }
}

The error I get in the Console is:

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

If I do not use Forward everything works fine, the request comes to the indexAction just fine. Only Forward throws an error.

From the manual, about The Forward Plugin:

For the Forward plugin to work, the controller calling it must be ServiceLocatorAware; otherwise, the plugin will be unable to retrieve a configured and injected instance of the requested controller.

From the manual, about Available Controllers:

Implementing each of the above interfaces is a lesson in redundancy; you won’t often want to do it. As such, we’ve developed two abstract, base controllers you can extend to get started.

AbstractActionController implements each of the following interfaces:

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

So my FooController extends AbstractActionController, which implements ServiceLocatorAwareInterface, so the Forward has to work, but it doesn't. What did I miss? How to make it work?

Green
  • 28,742
  • 61
  • 158
  • 247

4 Answers4

3

You should remember that the dispatch plugin gets the controller to dispatch to from the service manager by name. You should therefore use the correct name and not just the classname.

Look in your configuration for the controllers.invokables array. That should contain which name of the service maps to what FQCN.

It might be you name IS FooController, then forget what I just said

bas
  • 628
  • 9
  • 22
1

You should use fully qualified name when calling the controller, so 'FooController' should be namespaced as well. Also, you should add the controller in the list of the invokables in the module config files, for example:

return array(
    'controllers' => array(
        'invokables' => array(
             'FooController' => 'Namespace/Controller/FooController'
              ...
         ),
    )
 )
Roberto
  • 2,206
  • 4
  • 24
  • 31
1

try this:

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

here invokable is: 'Bar\Controller\Bar' => 'Bar\Controller\Bar'

webcoder
  • 1,355
  • 1
  • 15
  • 14
1

try this:

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

Your module.config.php file is like this:

'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
                    ),
                ),
            ),
        ),
    ),
Chirag Shah
  • 1,463
  • 2
  • 18
  • 40