Why Zend plugin postDispatch method is not called after indexAction - zend-framework

When i go to controllers index URL preDispatch is called before entering indexAction method of that controller but postDispatch is not called after it. Why it is not called and should i force it somehow to call postDispatch?
I have two plugin with postDispach methods whitch are not called.
If i got to URL e.g admin/listperms postDispatch is called and everything works.
AdminController.php
class AdminController extends Application_Controllers_Base {
public function indexAction() {
$this->view->headTitle = $this->alias('TITLE_ADMIN_PANEL');
}
public function listpermsAction() {
$this->view->headTitle = $this->alias('TITLE_PERMISSION_LIST');
$permService = new Application_Services_AdminPermission();
$perms = $permService->getPermissionList();
if(!$perms) {
// TODO:
} else {
$this->view->permList = $perms;
}
}
}
Base.php
class Application_Controllers_Base extends Zend_Controller_Action {
}
DbLogPlugin.php
class Application_Plugin_DbLogPlugin extends Zend_Controller_Plugin_Abstract {
public function postDispatch(Zend_Controller_Request_Abstract $request) {
$view = Zend_Controller_Front::getInstance()->getParam('bootstrap')->getResource('view');
$view->developerLog = $this->getQuerysLogs();
}
}
bootstrap.php
protected function _initAutoload(){
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Application_', //'
'basePath' => APPLICATION_PATH
));
$autoloader->addResourceType('dao', 'dao', 'Dao');
$autoloader->addResourceType('services', 'services', 'Services');
$autoloader->addResourceType('plugins', 'plugins', 'Plugins');
$autoloader->addResourceType('models', 'models', 'Models');
$autoloader->addResourceType('controllers', 'controllers', 'Controllers');
require_once('controllers/FrontController.php');
$front = Application_Controllers_FrontController::getInstance();
$front->setControllerDirectory(APPLICATION_PATH.'/controllers')
->setRouter(new Zend_Controller_Router_Rewrite())
->registerPlugin(new Application_Plugin_DbLogPlugin())
->registerPlugin(new Application_Plugin_AuthPlugin())
->registerPlugin(new Application_Plugin_ViewPlugin());
return $autoloader;
}

Related

Cant find included class in controller. Zend Framework 2

Also i begin learning zend framework 2. Install skillet application with composel. All goes fine until i didnt begin read that chapter http://framework.zend.com/manual/2.3/en/user-guide/forms-and-actions.html
in part where i try to create new class object in controller /src/Album/controller/AlbumController.php in function addAction().
There my PHP error:
http://i63.fastpic.ru/big/2014/1201/93/9684e5bcc24b52fec546f07e90abe593.png
There my IDE:
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Album\Model\Album;
use Album\Form\AlbumForm; //COLORED RED "Form"
class AlbumController extends AbstractActionController
{
protected $albumTable;
public function indexAction()
{
return new ViewModel(array(
'albums' => $this->getAlbumTable()->fetchAll(),
));
}
public function addAction()
{
$form = new AlbumForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if ($request->isPost()) {
$album = new Album(); //THE EEROR STRING THAT I GET IN PHP.
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$album->exchangeArray($form->getData());
$this->getAlbumTable()->saveAlbum($album);
// Redirect to list of albums
return $this->redirect()->toRoute('album');
}
}
return array('form' => $form);
}

ZF2 (2.1 method) Populating select/drop down element in form

I used Zend Framework 2.1(not 2.0x) method to populate a select/drop down that is described in following links:
http://zf2.readthedocs.org/en/develop/modules/zend.form.advanced-use-of-forms.html#handling-dependencies
http://www.michaelgallego.fr/blog/2012/11/09/discover-whats-coming-for-zendform-in-zf-2-1/
Though it seems I have done as they told I got a error message like:
*... ::__construct() must be an instance of Zend\Db\TableGateway\TableGateway, none given, called in ...*
which seems service locator is not used properly.
My form code that adds my FieldSet SupplierFieldset:
namespace Inventory\Form;
use Zend\Form\Form;
use Inventory\Model;
class ItemForm extends Form
{
public function init()
{
$this->add(array(
'name' => 'sup_code',
'type' => 'Inventory\Form\SupplierFieldset'
));
}
}
My 'SupplierFieldset' class:
namespace Inventory\Form;
use Inventory\Model;
use Zend\Form\Element;
use Zend\Form\Fieldset;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\InputFilter\InputFilterProviderInterface;
use Inventory\Model\SupplierTable;
use Inventory\Model\Supplier;
class SupplierFieldset extends Fieldset implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
protected $supplierTable;
public function init()
{
parent::__construct('Suppliers Code');
$this->setLabel('Supplier Code');
$this->setName('supplier_code');
$suppliers = $this->getSupplierTable()->fetchAll();
$select = new Element\Select('supplier_code');
$options = array();
foreach ($suppliers as $supplier) {
$options[$supplier->id] = $supplier->sup_code;
}
$select->setValueOptions($options);
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function getSupplierTable()
{
if (!$this->supplierTable) {
$sm = $this->getServiceLocator();
$this->supplierTable = $sm->get('Inventory\Model\SupplierTable');
}
return $this->supplierTable;
}
}
My Module.php getFormElementConfig() function:
public function getFormElementConfig()
{
return array(
'factories' => array(
'SupplierFieldset' => function($sm) {
$serviceLocator = $sm->getServiceLocator();
$supplierTable = $serviceLocator->get('Inventory\Model\SupplierTable');
$fieldset = new SupplierFieldset($supplierTable);
return $fieldset;
}
)
);
}
My SupplierTable.php model:
namespace Inventory\Model;
use Zend\Db\TableGateway\TableGateway;
class SupplierTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
}
I know SupplierTable model's constructor needs a TableGateway $tableGateway parameter. But this model is working properly when called from SupplierController.

How to pass params from controller to Zend_Form?

I know this question is already answered here. But this doesnt work for me.
The Form is generated by using the PluginLoader:
$formClass = Zend_Registry::get('formloader')->load('Payment');
$form = new $formClass(array('someval' => $my_arr));
Payment.php:
class Form_Payment extends Zend_Form
{
protected $_someval = array();
public function init()
{
$this->setAction('payment/save');
//....
$this->addElement('multiCheckbox', 'store_id', array('label' => 'Someval:', 'required' => true, 'multiOptions' => $this->getSomeval()))
}
public function setSomeval($someval) {
$this->_someval = $someval;
}
public function getSomeval() {
return $this->_someval;
}
}
As I can see the load method only returns the class name, so new $formClass(); is equal new Form_Payment() but why this isn't accept params?
Ok I found a way by myself. I was looking for a way to inject some params while my Zend_Form was initialised. It seems the only way for this is to pass the params to the constructor - which is executed before the init method.
class Form_Payment extends Zend_Form
{
private $_someval;
public function __construct(array $params = array())
{
$this->_someval = $params['someval'];
parent::__construct();
}
public function init()
{
$this->setAction('payment/save');
//....
$this->addElement('multiCheckbox', 'store_id',
array('label' => 'Someval:',
'required' => true,
'multiOptions' => $this->_someval // passed params now available
))
}
}
You can add custom function to your form class like
class Form_Payment extends Zend_Form
{
public function init()
{
$this->setAction('payment/save');
// and so on
}
public function doSome()
{
$this->setAction('other/action');
}
}
and call it after instanciating form in controller
$form = new $formClass();
$form->doSome();

Zend: ACL logic in View helpers

Background information:
I'm in my admin module, and I created a view helper in modules/admin/views/helpers/AdminPanel.php. I have a layout plugin that forces my view to use the layout in admin/views/layouts/default.phtml.
I'm trying to access my ACL object to determine whether or not the user has resources in the context of a view helper, and then determine whether to return the admin panel html by parsing a configs/admin-nav.xml or not return anything at all.
I'm calling it in my admin layout like so:
<?php echo $this->AdminPanel(); ?>
And the class code which is blank, which I need to access the acl object in:
class My_View_Helper_AdminPanel extends Zend_View_Helper_Abstract {
public function AdminPanel() {}
}
I tried this:
$acl = Zend_Controller_Action_HelperBroker::getStaticHelper('acl');
But this probably isn't what I'm looking for as it forces the default module's views/layouts/default.phtml to load and errors occur.
Here's my global bootstrap file:
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
private $_acl = null;
private $_auth = null;
protected function _initDoctype() {
$this->bootstrap('view');
$view = $this->getResource('view');
$view->setEncoding('UTF-8');
$view->doctype('HTML4_STRICT');
}
protected function _initAutoload() {
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('KG_');
$resourceLoader = new Zend_Loader_Autoloader_Resource(
array(
'basePath' => APPLICATION_PATH,
'namespace' => '',
'resourceTypes' => array(
'form' => array(
'path' => 'forms/',
'namespace' => 'Form_'
),
'model' => array(
'path' => 'models/',
'namespace' => 'Model_'
)
)
));
return $autoloader;
}
protected function _initAclAuth() {
$this->_acl = new Model_Acl;
$this->_auth = Zend_Auth::getInstance();
}
protected function _initNav() {
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();
$config = new Zend_Config_Xml( APPLICATION_PATH . '/configs/nav.xml', 'mainNav');
$navigation = new Zend_Navigation( $config );
$fc = Zend_Controller_Front::getInstance();
$fc->registerPlugin( new KG_Controller_Plugin_Acl( $this->_acl, $this->_auth ) );
$role = $this->_auth->getStorage()->read()->role;
if ( !$role ) {
$role = 'guest';
}
$view->navigation( $navigation )->setAcl( $this->_acl)->setRole( $role );
}
protected function _initEncoding() {
$fc = Zend_Controller_Front::getInstance();
$response = new Zend_Controller_Response_Http;
$response->setHeader('Content-Type','text/html;charset=utf-8', true);
$fc->setResponse($response);
}
}
Your KG_Controller_Plugin_Acl plugin should be taking care of the access logic, not your view. If the user doesn't have access to the resource, you should error out or redirect the user to somewhere else.
The layout should be set within the controller. Preferably in the init() method with:
$this->_helper->layout->setLayout();
It looks like you followed the same or a similar tutorial as I did for Zend_Acl. I'm posting my plugin for reference, which includes the logic to handle access control from within the plugin:
class App_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{
protected $_auth = null;
protected $_acl = null;
public function __construct(Zend_Auth $auth, Zend_Acl $acl)
{
$this->_auth = $auth;
$this->_acl = $acl;
}
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
if ($this->_auth->hasIdentity()) {
$identity = $this->_auth->getIdentity();
$role = $identity->acl_role;
} else {
$role = 'guest';
}
// Mapping to determine which Resource the current
// request refers to (really simple for this example!)
$resource = $request->controller;
$privilege = $request->action;
if (!$this->_acl->has($resource)) {
$resource = null;
}
// ACL Access Check
if (!$this->_acl->isAllowed($role, $resource, $privilege)) {
if ($this->_auth->hasIdentity()) {
// authenticated, denied access, forward to /error/permissions
$request->setModuleName('default');
$request->setControllerName('error');
$request->setActionName('permissions');
} else {
// not authenticated, forward to login form
$request->setModuleName('default');
$request->setControllerName('auth');
$request->setActionName('login');
}
}
}
}

Problem With View Helpers

I wrote few custom view helpers but I have a little trouble using them. If I add the helper path in controller action like this:
public function fooAction()
{
$this->view->addHelperPath('My/View/Helper', 'My_View_Helper');
}
Then I can use the views from that path without a problem. But when I add the path in the bootstrap file like this:
protected function _initView()
{
$this->view = new Zend_View();
$this->view->doctype('XHTML1_STRICT');
$this->view->headScript()->appendFile($this->view->baseUrl()
. '/js/jquery-ui/jquery.js');
$this->view->headMeta()->appendHttpEquiv('Content-Type',
'text/html; charset=UTF-8');
$this->view->headMeta()->appendHttpEquiv('Content-Style-Type',
'text/css');
$this->view->headMeta()->appendHttpEquiv('Content-Language', 'sk');
$this->view->headLink()->appendStylesheet($this->view->baseUrl()
. '/css/reset.css');
$this->view->addHelperPath('My/View/Helper', 'My_View_Helper');
}
Then the view helpers don't work. Why is that? It's too troublesome to add the path in every controller action. Here is an example of how my custom view helpers look:
class My_View_Helper_FooBar
{
public function fooBar() {
return 'hello world';
}
}
I use them like this in views:
<?php echo $this->fooBar(); ?>
Should I post my whole bootstrap file?
UPDATE:
Added complete bootstrap file just in case:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initFrontController()
{
$this->frontController = Zend_Controller_Front::getInstance();
$this->frontController->addModuleDirectory(APPLICATION_PATH
. '/modules');
Zend_Controller_Action_HelperBroker::addPath(
'My/Controller/Action/Helper',
'My_Controller_Action_Helper'
);
$this->frontController->registerPlugin(new My_Controller_Plugin_Auth());
$this->frontController->setBaseUrl('/');
}
protected function _initView()
{
$this->view = new Zend_View();
$this->view->doctype('XHTML1_STRICT');
$this->view->headScript()->appendFile($this->view->baseUrl()
. '/js/jquery-ui/jquery.js');
$this->view->headMeta()->appendHttpEquiv('Content-Type',
'text/html; charset=UTF-8');
$this->view->headMeta()->appendHttpEquiv('Content-Style-Type',
'text/css');
$this->view->headMeta()->appendHttpEquiv('Content-Language', 'sk');
$this->view->headLink()->appendStylesheet($this->view->baseUrl()
. '/css/reset.css');
$this->view->addHelperPath('My/View/Helper', 'My_View_Helper');
}
protected function _initDb()
{
$this->configuration = new Zend_Config_Ini(APPLICATION_PATH
. '/configs/application.ini',
APPLICATION_ENVIRONMENT);
$this->dbAdapter = Zend_Db::factory($this->configuration->database);
Zend_Db_Table_Abstract::setDefaultAdapter($this->dbAdapter);
$stmt = new Zend_Db_Statement_Pdo($this->dbAdapter,
"SET NAMES 'utf8'");
$stmt->execute();
}
protected function _initAuth()
{
$this->auth = Zend_Auth::getInstance();
}
protected function _initCache()
{
$frontend= array('lifetime' => 7200,
'automatic_serialization' => true);
$backend= array('cache_dir' => 'cache');
$this->cache = Zend_Cache::factory('core',
'File',
$frontend,
$backend);
}
public function _initTranslate()
{
$this->translate = new Zend_Translate('Array',
BASE_PATH . '/languages/Slovak.php',
'sk_SK');
$this->translate->setLocale('sk_SK');
}
protected function _initRegistry()
{
$this->registry = Zend_Registry::getInstance();
$this->registry->configuration = $this->configuration;
$this->registry->dbAdapter = $this->dbAdapter;
$this->registry->auth = $this->auth;
$this->registry->cache = $this->cache;
$this->registry->Zend_Translate = $this->translate;
}
protected function _initUnset()
{
unset($this->frontController,
$this->view,
$this->configuration,
$this->dbAdapter,
$this->auth,
$this->cache,
$this->translate,
$this->registry);
}
protected function _initGetRidOfMagicQuotes()
{
if (get_magic_quotes_gpc()) {
function stripslashes_deep($value) {
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
$_POST = array_map('stripslashes_deep', $_POST);
$_GET = array_map('stripslashes_deep', $_GET);
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
$_REQUEST = array_map('stripslashes_deep', $_REQUEST);
}
}
public function run()
{
$frontController = Zend_Controller_Front::getInstance();
$frontController->dispatch();
}
}
Solved. I just needed to add these lines at the end of _initView() method:
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$viewRenderer->setView($this->view);
I in my _initView() have something like this:
protected function _initView() {
$view = new Zend_View();
#some view initialization ...
$view->addHelperPath(APPLICATION_PATH . '/views/helpers', 'My_View_Helper');
return $view;
}
Then in a view I can execute:
<?php echo $this->fooBar(); ?>
Without APPLICATION_PATH it does not work in my case.
Just a thought: are you sure that the view that you are creating in your bootstrap ($this->view = new Zend_View();) is the same as '$this' in your view file?
I think you would need to change your initView code to the following:
protected function _initView()
{
$view = new Zend_View();
$view->doctype('XHTML1_STRICT');
$view->headScript()->appendFile($this->view->baseUrl()
. '/js/jquery-ui/jquery.js');
$view->headMeta()->appendHttpEquiv('Content-Type',
'text/html; charset=UTF-8');
$view->headMeta()->appendHttpEquiv('Content-Style-Type',
'text/css');
$view->headMeta()->appendHttpEquiv('Content-Language', 'sk');
$view->headLink()->appendStylesheet($this->view->baseUrl()
. '/css/reset.css');
$view->addHelperPath('My/View/Helper', 'My_View_Helper');
return $view;
}
If you have some View related settings in your config.ini file, you might want to change your code a little bit:
protected function _initMyView()
{
$view = $this->bootstrap('view')->getResource('view');
...
instead of:
protected function _initView()
{
$view = new Zend_View();
....
You might consider adding another init function just for your view helpers:
protected function _initViewHelpers()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath('My/View/Helper', 'My_View_Helper');
}
This way the built in view setup is not overridden.
If you add only $this->view->addHelperPath('My/View/Helper', 'My_View_Helper');
in your bootstrap use this format:
class Zend_View_Helper_FooBar extends Zend_View_Helper_Abstract {
public function fooBar() {
return 'hello world';
}
}