简体   繁体   中英

Zend Framework 2 Custom ViewHelper for specific action in a controller

is it possible to include a viewhelper on specific action inside a controller.

Here is the thing, I'm displaying a table with transaction record but before displaying it to a html table I have to have some view logic from the records return by other service. This logic is not suitable to be put in the Service side nor the view. So I think this where ViewHelper came in.

From the tutorial in the web, they put viewhelper in the module.config.php and include it on the bootstrap section in the Module.php. Now if the viewhelper is use globally in another controller or action such as "url" than it's ok to do it this way. Buy my helper is only to be use specifically for this one action inside one controller.

Here is the partial action code and how I currently integrate viewhelper inside Controller

<?php
function listAction() {
    $viewModel = new \Zend\View\Model\ViewModel();

    $service = $this->getServiceLocator();

    $transactionService = $service->get('TransactionService');
    $records = $transactionService->getTransaction();

    $helper = new \Transaction\View\Helper\TransactionViewHelper();
    $helper->setServiceLocator($service);
    $records = $helper->render($records);

    $viewModel->setVariable('records', $records);
    return $viewModel();
}
?>

It's not elegant, it works but maybe there is a better way

The structure of viewhelper is like this, I needed the servicelocator due to I don't know how to get "url" viewhelper inside my viewhelper and I need to read some config. Also the helper will never be called inside the list.phtml

<?php

 class TransactionViewHelper extends \Zend\View\Helper\AbstractHelper implements \Zend\ServiceManager\ServiceLocatorAwareInterface {
     public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

    public function __invoke()
    { 
        return $this;
    }

    public function render($records)
    {
        //Some logic here
        return $result;
    }
}
?>

Ok found better neat solution

I put it in the module.config.php as view_helpers > invokables, Then call it from ViewHelperManager. This way the servicelocator is injected automatically.

This is additional setting on module.config.php

<?php
//...
'view_helpers' => array(
    'invokables' => array(
         'transaction' => 'MyModule\View\Helper\TransactionViewHelper'
    )
)
//...
?>

This is the controller code for specific action

<?php
//...
function listAction() {
    $viewModel = new \Zend\View\Model\ViewModel();

    $service = $this->getServiceLocator();

    $transactionService = $service->get('TransactionService');
    $records = $transactionService->getTransaction();

    $helper = new \Transaction\View\Helper\TransactionViewHelper();
    $helper->setServiceLocator($service);
    $records = $helper->render($records);

    //The action it's call by ajaxAction so I use this one to return to that function
    //The ajaxAction function will format it to json 
    $viewHelperManager = $service->get('ViewHelperManager');
    $transactionRecord = $viewHelperManager->get('transaction');
    $result = $transactionRecord->render($records);
    return $result

    //If not ajax than just pass this variable to viewmodel
    //Then do echo $this->transactionRecord->render($records) in list.phtml
    $viewModel = new \Zend\View\Model\ViewModel();
    $viewModel->setVariable('records', $records);
    return $viewModel();

}
//...
?>

The viewhelper class became more simple and clean

<?php
class TransactionViewHelper extends \Zend\View\Helper\AbstractHelper {

    public function __invoke()
    { 
        return $this;
    }

    public function render($records)
    {
        //Some logic here
        return $result;
    }
}
?>

Note to access other helper plugin such as 'url' just call this inside viewhelper

<?php
$url = $this->view->plugin('url');
$url('path/to/url', array('id' => ''));
?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM