Zend framework. how to pass options to custom front controller plugin? - zend-framework

I have custom front controller plugin that takes some options.
At this time I load it (plugin) in application.ini file like this:
resources.frontController.plugins.DynamicLayout = "My_Controller_Plugin_DynamicLayout"
At this time I just have option.ini file and then use zend_config to import it.
Is there a way to specify plugin options from ZEND's primary application.ini file?
Maybe something like this?:
resources.frontController.plugins.DynamicLayout.test = "test_value"

I use something like this to pass info to my layouts using bootstrap.
This example is for an application that runs on different domains, thus different layouts. (and has a separate version for MSIE). Each domain as a separate application.ini
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initAutoload() {
return new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH
));
}
// <snip> more _initMethods: Loggers, ACLs, ViewHelpers, etc. </snip>
/**
* Setup dynamic layout plugin
*
* #return Zend_Controller_Plugin_Broker
*/
protected function _initFrontControllerLayoutPlugin() {
// Ensure the front controller is initialized
$this->bootstrap('FrontController');
$front = $this->getResource('FrontController');
$this->bootstrap('layout');
$layout = $this->getResource('layout');
// Set our Front Controller Plugin
// !!!! right here I pass values to the layout
// !!!! example layoutName, but you could pass anything you want...
$plugin = new Plugin_DynamicLayout($layout, $this->getOption('layoutName'));
return $front->registerPlugin($plugin);
}
}
The layout Handler:
<?php
class Plugin_DynamicLayout extends Zend_Controller_Plugin_Abstract {
private $layoutName;
public function __construct(Zend_Layout $layout, $layoutName) {
$this->layout = $layout;
$this->layoutName = $layoutName;
}
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$layoutName = $this->layoutName;
if (false !== strpos($request->getHeader('User-Agent'), 'MSIE')) {
$layoutName = $layoutName . '-ie';
}
$this->layout->setLayout($layoutName);
}
}
The application.ini:
[production]
layoutName = "Some_File_Name"

Related

Zend Framework 1 add single custom rule for routing

I am having problem with adding custom routing into my application. Zend Framework 1:
I have already working application with default Zend routing. I have a lot of controllers and for some of them I want to use friendly urls, for example:
domain.com/cities/edit/id/3
to
domain.com/cities/edit/abu-dhabi
There are some controllers to switch into that url (in that format).
I tried to configure it by ini file:
resources.router.routes.slugurl.route = /:controller/:action/:slug
And also by Bootstrap method:
protected function _initSlugRouter()
{
$this->bootstrap('FrontController');
$router = $this->frontController->getRouter();
$route = new Zend_Controller_Router_Route('/:controller/:action/:slug/',
array(
'controller' => 'slug',
'action' => 'forward',
'slug' => ':slug'
)
);
$router->addRoute('slug',$route);
}
The main problem - with ini configuration - request goes directly to controller city (not slug). Second one (bootstrap) - also executes the city controller, but the default routing not working as it was, I am not able to execute:
domain.com/cities/ but domain.com/cities/index/ works. The error without action defined:
Action "forward" does not exist and was not trapped in __call()
I can monitor the "slug" in controllers/move check into some library, but I would like to do it only with routing - that way looks much better for me.. Please, how to solve that issue?
edit with summary of solution
Thank you Max P. for interesting. I solved it at last - in last 2 minutes:) I had wrong rules at application.ini with routing. Right now it is defined that:
resources.router.routes.slugurl.route = /:controller/:action/:slug
resources.router.routes.slugurl.defaults.controller = :controller
resources.router.routes.slugurl.defaults.action = :action
resources.router.routes.slugurl.defaults.slug = :slug
The controller is defined like that:
class CitiesController extends Crm_Abstract
The Crm_Abstract has code:
<?php
class Crm_Abstract extends Zend_Controller_Action {
public function __construct(\Zend_Controller_Request_Abstract $request, \Zend_Controller_Response_Abstract $response, array $invokeArgs = array()) {
$params = $request->getParams();
if (!empty($params['slug'])) {
$modelSlug = Crm_Helper_Slug::getInstance();
$parameters = $modelSlug->redirectRequest($request);
if ($parameters !== false) {
foreach ($parameters as $key => $value) {
$request->setParam($key, $value);
}
}
}
parent::__construct($request, $response, $invokeArgs);
}
public function __call($methodName, $args) {
parent::__call($methodName, $args);
}
}
The slug helper get parameters for slug at defined controller. The url to access the slug is defined/calculated in place of $this->url - to $this->slug and there rest of code is done in slug helper. I am not sure if my solution is 100% sure, because that is my first time with routing.
The major thing is that - I just needed to change Zend_Controller_Action to Crm_Abstract which extends the Zend_Controller_Action. Single line - no additional custom code in each controller.
I created two route rules:
resources.router.routes.slugurl.type = "Zend_Controller_Router_Route"
resources.router.routes.slugurl.route = /:controller/:action/:slug/
resources.router.routes.slugurl.defaults.module = "default"
resources.router.routes.slugurl.defaults.controller = :controller
resources.router.routes.slugurl.defaults.action = :action
resources.router.routes.slugurl.defaults.slug = :slug
resources.router.routes.plain1.route = "/:controller/:action/"
resources.router.routes.plain1.defaults.module = "default"
resources.router.routes.plain1.defaults.controller = "index"
resources.router.routes.plain1.defaults.action = "index"
And for now that works fine. Bad thing - I don't understand routing (htaccess rules), but the time spent on that problem and solve it is better than modify all controllers...

Zend-framework 1.12 module: links always lead to default module

I created ZendFramework 1.12 applications with modules.
The idea was to have versions of the API in modules, with RESTfull paths.
The default module was V1, and now when I am trying to create v1s1 module, all links still lead to V1.
Can anybody push me in the right direction how to solve this?
MORE DETAILS
This is the code I have to use modules.
application.ini
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.defaultModule = "v1"
resources.modules[] =
v1.boostrap.path = APPLICATION_PATH "/modules/v1/Bootstrap.php"
resources.frontController.plugins.putHandler = Zend_Controller_Plugin_PutHandler
routes.rest.type = Zend_Rest_Route
routes.rest.defaults.module = v1
Main Bootstrap.php:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initAppAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'V1s1',
'basePath' => APPLICATION_PATH . '/modules/v1s1',
));
$autoloader->addResourceType('model', 'models', 'Model');
return $autoloader;
}
}
V1 Bootstrap.php:
class V1_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected $_moduleName = "v1";
protected function _initAutoload()
{
// Add autoloader empty namespace
$autoLoader = Zend_Loader_Autoloader::getInstance();
$autoLoader->registerNamespace('v1_');
return $autoLoader;
}
protected function _initResourceLoader()
{
Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH . '/modules/v1/controllers/helpers');
}
public function _initRouts()
{
$front = Zend_Controller_Front::getInstance();
$restRoute = new Zend_Rest_Route($front, array(), $arrayOfControllers));
$front->getRouter()->addRoute('rest', $restRoute);
}
}
Now I need to create module v2, but when I do that, I everything crashes. Link are no longer RESTfull, and every link still leads to the V1 module. V2 module Bootstrap.php is being accessed.

how to differentiate admin module from main application in bootstrap file in zend framework

Please give me proper solution for my query. I have tried to solve it but not getting any proper solution. Please give me proper solution.
If I remove following line from application.ini file then it is working well for front end application
resources.modules[] =
After remove it, I am unable to get my created module(Admin) in modules folder with proper layout. I have only one module. In module bootstrap file I have defined following functions (project/application/modules/admin/Bootstrap.php)
<?php
class Admin_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initAppAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'admin',
'basePath' => APPLICATION_PATH . '/modules/admin/'
));
return $autoloader;
}
protected function _initPlugins()
{
$bootstrap = $this->getApplication();
if ($bootstrap instanceof Zend_Application) {
$bootstrap = $this;
}
$bootstrap->bootstrap('FrontController');
$front = $bootstrap->getResource('FrontController');
$plugin = new Admin_Plugin_Layout();
// $plugin->setBootstrap($this);
$front->registerPlugin($plugin);
}
protected function _initAuthPlugin()
{
$checkAuth = Zend_Controller_Front::getInstance();
$checkAuth->registerPlugin(new Admin_Plugin_CheckAuth(Zend_Auth::getInstance()));
}
protected function _initDoctype()
{
global $adminModuleCssPath;
global $adminModuleJsPath;
$this->bootstrap( 'view' );
$view = $this->getResource( 'view' );
$view->headTitle('Jyotish - Ek Gyan');
$view->headScript()->appendFile($adminModuleJsPath.'jquery-1.7.2.js');
$view->headScript()->appendFile($adminModuleJsPath.'jquery-ui.js');
$view->headScript()->appendFile($adminModuleJsPath.'tinybox.js');
$view->headScript()->appendFile($adminModuleJsPath.'common.js');
$view->headLink()->appendStylesheet($adminModuleCssPath.'jquery-ui.css');
$view->headLink()->appendStylesheet($adminModuleCssPath.'style.css');
$view->headLink()->appendStylesheet($adminModuleCssPath.'theme.css');
$view->headLink()->appendStylesheet($adminModuleCssPath.'tinybox.css');
$view->doctype( 'XHTML1_STRICT' );
//$view->navigation = $this->buildMenu();
}
protected function _initLayoutPlugin()
{
$layout = Zend_Controller_Front::getInstance();
$layout->registerPlugin(new Admin_Plugin_AdminLayout());
}
protected function _initRouter()
{
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$route = new Zend_Controller_Router_Route(
':module/:controller/:action/*',
array('module' => 'admin')
);
$router->addRoute('default', $route);
$usersRoute = new Zend_Controller_Router_Route_Regex(
':module/:controller/:action/(?:/page/(\d+)/?)?',
array(
'module' => 'admin',
'controller' => 'users',
'action' => 'index',
'page' => 1,
),
array(
'page' => 1,
)
);
$router->addRoute('users-index', $usersRoute);
}
protected function _initActionHelpers()
{
Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH . "/modules/admin/views/helpers");
Zend_Controller_Action_HelperBroker::addPrefix('Admin_View_Helper');
}
}
In modules folder I have created following plugin Layout
class Admin_Plugin_Layout extends Zend_Controller_Plugin_Abstract
{
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
if ('admin' != $request->getModuleName()) {
// If not in this module, return early
return;
}
// Change layout
Zend_Layout::getMvcInstance()->setLayout('admin');
}
}
In frontend bootstrap file I have defined following functions(project/application/Bootstrap.php)
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initAppAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'default',
'basePath' => dirname(__FILE__),
));
return $autoloader;
}
protected function _initLayoutHelper()
{
$this->bootstrap('frontController');
$layout = Zend_Controller_Action_HelperBroker::addHelper(
new Application_View_Helper_LayoutLoader());
}
}
I have created following helper file in (project/application/view/helper/LayoutLoader.php)
<?php
class Application_View_Helper_LayoutLoader extends Zend_Controller_Action_Helper_Abstract
{
public function preDispatch()
{
$bootstrap = $this->getActionController()
->getInvokeArg('bootstrap');
$config = $bootstrap->getOptions();
$module = $this->getRequest()->getModuleName();
if (isset($config[$module]['resources']['layout']['layout'])) {
$layoutScript =
$config[$module]['resources']['layout']['layout'];
$this->getActionController()
->getHelper('layout')
->setLayout($layoutScript);
}
}
}
From last two days I am trying to create separate layout for both but I am unable to getting proper solution. When I run admin module in browser, it is working well but when I run frontend application folder it show exception error with layout of admin.
Please provide me proper solution....
Thanks
The standard way to do a layout switching is with a front-controller plugin. You don't need the LayoutLoader helper with preDispatch hook.
A simple layout-switcher plugin can be implemented as follows.
Place your various layout files in application/layouts/scripts/, named the same as your module: default.phtml, admin.phtml, etc.
In the file application/plugins/Layout.php:
class Application_Plugin_Layout extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
Zend_Layout::getMvcInstance()->setLayout($request->getModuleName());
}
}
Enable the plugin application/configs/application.ini using:
resources.frontController.plugins.layout = "Application_Plugin_Layout"
or by manually registering the plugin in Bootstrap.
Also, make sure your application.ini enables modules and identifies your layout location:
resources.modules[]=
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
You seem to be way over thinking this. I'm going to simplify this down to the basic and you can add back as you see fit.
The bootstrap system in ZF1 is a bad joke. Anything that is present in one of the bootstrap files will available to all modules at run and will be run with every request. So keep it simple and keep it light. I normally put all of the _init methods in the main bootstrap and leave the module bootstraps empty.
//simplify your bootstrap to minimum
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
//your app autoloader is the standard autoloader so is not needed here, it better just work.
/**
* initialize the session
*/
protected function _initsession()
{
Zend_Session::start();
}
/**
* initialize the registry and assign application.ini to config namespace
*/
protected function _initRegistry()
{
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
}
protected function _initView()
{
//Initialize view
$view = new Zend_View();
//add custom view helper path
$view->addHelperPath('/../library/My/View/Helper');
//set doctype for default layout
$view->doctype(Zend_Registry::get('config')->resources->view->doctype);
//set default title
$view->headTitle('Jyotish - Ek Gyan');
//set css includes
$view->headlink()->setStylesheet('/bootstrap/css/bootstrap.min.css');
//add javascript files
$view->headScript()->setFile('/bootstrap/js/jquery.min.js');
$view->headScript()->appendFile('/bootstrap/js/bootstrap.min.js');
//add it to the view renderer
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer');
$viewRenderer->setView($view);
//Return it, so that it can be stored by the bootstrap
return $view;
}
/**
* Not sure if this is really required as it seems as though your routes are pretty standard.
*/
protected function _initRouter()
{
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$route = new Zend_Controller_Router_Route(
':module/:controller/:action/*',
array('module' => 'admin')
);
$router->addRoute('default', $route);
$usersRoute = new Zend_Controller_Router_Route_Regex(
':module/:controller/:action/(?:/page/(\d+)/?)?',
array(
'module' => 'admin',
'controller' => 'users',
'action' => 'index',
'page' => 1,
),
array(
'page' => 1,
)
);
$router->addRoute('users-index', $usersRoute);
}
protected function _initAuthPlugin()
{
$checkAuth = Zend_Controller_Front::getInstance();
$checkAuth->registerPlugin(new Admin_Plugin_CheckAuth(Zend_Auth::getInstance()));
}
}
The application.ini is a very important part of application configuration:
//truncated for example
[production]
;-------------------------------------------------------------------------------
;//PHP
;-------------------------------------------------------------------------------
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
;-------------------------------------------------------------------------------
;//Paths and Namespaces, paths for application resources and library
;-------------------------------------------------------------------------------
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
autoloaderNamespaces[] = "My_"
;-------------------------------------------------------------------------------
;//Front Controller, default settings for controllers and modules
;-------------------------------------------------------------------------------
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
resources.frontController.moduleControllerDirectoryName = "controllers"
resources.frontController.params.prefixDefaultModule = ""
resources.modules = ""
resources.frontController.baseurl = http://example.com
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
;-------------------------------------------------------------------------------
;//plugins, default paths for resource plugins and action helpers, can also be
; //accomplished in the bootstrap
;-------------------------------------------------------------------------------
pluginPaths.My_Application_Resource = APPLICATION_PATH "/../library/My/Resource"
resources.frontController.actionhelperpaths.My_Controller_Action_Helper = APPLICATION_PATH "/../library/My/Controller/Action/Helper"
;-------------------------------------------------------------------------------
;//View Settings, view settings to be shared with the view object in the bootstrap
;// allows for easier editing.
;-------------------------------------------------------------------------------
resources.view[]=
resources.view.charset = "UTF-8"
resources.view.encoding = "UTF-8"
resources.view.doctype = "HTML5"
resources.view.language = "en"
resources.view.contentType = "text/html; charset=UTF-8"
;-------------------------------------------------------------------------------
;//Database Settings, default database adapter settings
;-------------------------------------------------------------------------------
resources.db.adapter = "pdo_Mysql"
resources.db.params.username = "user"
resources.db.params.password = "xxxx"
resources.db.params.dbname = "dbname"
resources.db.params.charset = "utf8"
resources.db.isDefaultTableAdapter = true
resources.db.params.profiler = true
;-------------------------------------------------------------------------------
;//Layouts, default path to layout files and default layout name
;-------------------------------------------------------------------------------
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.layout.layout = layout
Now the simplest way to accomplish layout switching is to switch the layout on a per controller basis, use the default layout except where you explicitly change it:
//some controller that needs the admin layout
//note: preDispatch() and routeShutdown() are essentially the same point in the loop
public function preDispatch() {
//switch to new layout
$this->_helper->layout->setLayout('admin');
//you can also manipulate the css and js similarly to the bootstrap
$this->view->headScript()->appendFile(
'/javascript/mediaelement/build/mediaelement-and-player.min.js');
$this->view->inlineScript()->setScript(
"$('audio').mediaelementplayer();");
}
I find that if I just need one or two different layouts this works nicely and is simple. Not really a DRY solution but can really help develop the parameters for a plugin if a DRY solution is desired.
I hope this provides some help, the big thing to remember is that the module bootstraps are basically just extentions of the main bootstrap and provide no seperation of functionality.
P.S. I would have provided a plugin demo but I really suck at plugins, Sorry.

Zend Framework loads mappers from Application/Model/ instead of application/models

My zend app is created, everything seems to be in order but every time I try to do something like:
$accProducts = new Application_Models_AccProductsMapper();
Only get:
Warning: include_once(Application/Models/AccProductsMapper.php): failed to open stream: No such file or directory in /home/blah/blah/blah/Loader.php on line 148
however, the AccProductsMapper.php file do exist in such directory, directories within the zend app are all lowercase tough.
I've spend a lot of time looking for something to solve this issue with no good results at all.
Bootstrap.php
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initDoctype()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->doctype('XHTML1_STRICT');
}
protected function _initAutoload()
{
$moduleLoader = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH));
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace(array('App','My_'));
return $moduleLoader;
}
}
The standard Zend_Loader_Autoloader_Resource class added to each module looks for models with the class prefix <ModuleNamespace>_Model_ in <module-directory>/models.
For the default module, the namespace is defined in your config's appnamespace property (defaults to Application). The directory is typically application.
To summarize, create your default module model classes in application/models with class prefix Application_Model_, eg
<?php
// application/models/AccProductsMapper.php
class Application_Model_AccProductsMapper
{
// etc
As for your _initAutoload() method, I can't tell what you're doing with that module loader and would advise you don't need it at all. You can register PEAR style namespaces in your config file, eg
autoloadernamespaces.App = "App_"
autoloadernamespaces.My = "My_"

Zend Framework: How can i pass values to layout.phtml?

I can pass value from controller to view with this =>
$this->view->objvalue = $value;
But how can i pass value to layout.phtml ?
I want to have a link to edit table. So i have to make the link with 'id'=>$getvaluefromsomewhere->id. How can i do this in zend framework ?
Where would i put this file (My_Layout_Plugin.php) ?
class My_Layout_Plugin extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$layout = Zend_Layout::getMvcInstance();
$view = $layout->getView();
$view->whatever = 'foo';
}
}
Sending variables to the layout in Zend Framework
put it in library/My/Layout/Plugin.php and add this in application.ini
resources.frontController.plugins.layout = "My_Layout_Plugin"
See here Zend framework 1.8 recommended way to register a plugin?