How to pass parameter from View Helper (widget) to action?

551 Views Asked by At

I have widget which is calling an action for another controller and I need to pass a parameter to the action. I tried the following so far and I am getting the following error :

Error

Fatal error: Call to a member function getParam() on a non-object in C:\dev\projects\OnlineFieldEvaluation\vendor\zendframework\zendframework\library\Zend\Mvc\Controller\Plugin\Params.php on line 118

Widget

namespace OnlineFieldEvaluation\View\Helper;

use OnlineFieldEvaluation\Controller\TabsController;
use Zend\View\Helper\AbstractHelper;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;


class IdentityInformationWidget extends AbstractHelper implements ServiceLocatorAwareInterface
{

    protected $idinfoService = null;

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

...

    /**
     * @param $id
     */
    public function __invoke($id)
    {

        $viewModel = $this->idinfoService->editidentityinformationAction($id);

        return $this->getView()->render($viewModel);

    }

}

Controller:

   public function editidentityinformationAction()
    {
      $id = (int)$this->params()->fromRoute('id', 0);
     //$id = (int)$this->params('id', 0);

...

        $view = new ViewModel(array(
            'id' => $id,
            'form' => $form,
        ));
        $view->setTemplate('online-field-evaluation/tabs/editidentityinformation.phtml');

        return $view;
    }

Calling from view

 <?php echo $this->identityInformationWidget(3); ?>

EDIT 1: after trying : " $id = $this->getEvent()->getRouteMatch()->getParam('id', 0);"

Event:

enter image description here

and "$this->getEvent()->getRouteMatch()" returns null

I am trying to modify this example for my use case: http://www.michaelgallego.fr/blog/2012/10/06/how-to-replace-the-action-helper-in-zf-2-and-make-great-widgetized-content/

2

There are 2 best solutions below

0
On

Well there are several ways to achieve your widget :

First just calling your the desired action, as you trying to do, passing params to your action (like $id) in your case BUT this way, your action might not work as expected because you are creating a "new" entry point to your action. You can face troubles that way.

Best method I think is to use forward()->dispatch controller plugin, because ZF2 will get all the context and isolate the processing to give your a ViewModel instance your can render after. You will achieve a better isolation.

Exemple :

Beware : your route definition must be a Segment type and have :id in route pattern

Controller

public function editidentityinformationAction()
    {
      // use params form routing
      $id = (int)$this->params()->fromRoute('id', 0);

      // Some Logic using dispatch context, servicemanager, etc...
...

        $view = new ViewModel(array(
            'id' => $id,
            'form' => $form,
        ));
        $view->setTemplate('online-field-evaluation/tabs/editidentityinformation.phtml');

        return $view;
    }

View helper :

class IdentityInformationWidget extends AbstractHelper implements ServiceLocatorAwareInterface
{

    protected $serviceLocator;

    public function __construct(ServiceLocatorInterface $serviceLocator)
    {
        // $serviceLocator is an instance of ViewHelperManager
        // We get ServiceManager (its "parent" ServiceLocatorInterface) with $serviceLocator->getServiceLocator()
        // Make good use of your ServiceLocatorAwareInterface
        $this->setServiceLocator($serviceLocator->getServiceLocator());
    }

...

    /**
     * @param $id
     */
    public function __invoke($id)
    {
        // Going through ServiceManager to get ControllerPluginManager and Forward controller plugin
        $forwardPlugin = $this->getServiceLocator()
             ->get('ControllerPluginManager')->get('forward');

        // Dispatch Action with parameter (Force ZF2 MVC dispatch stack process)
        $viewModel = $this->forward()
           ->dispatch('Onlin‌​eFieldEvaluation\Controller\TabsController', array(
               'action' => 'editidentityinformation',
               'id'     => $id
           ));

        return $this->getView()->render($viewModel);

    }

}
  • Note : I did not test this code, there are certainly errors but logic is here

http://framework.zend.com/manual/2.3/en/modules/zend.mvc.plugins.html#forward-plugin for more help on forward plugin

This way you can your action either as a normal page, or as a widget with the help of your viewhelper, your action is also testable, because its logic does not change as a webpage or as a widget, you can also test your widget easily as you can mock services, etc...

1
On

Try: $this->getEvent()->getRouteMatch()->getParam('id', 0);