How to set router for earch module in zend framework - zend-framework

I have 1 zend (v1) application, and 2 module : default + admin
I want when call default module will be set router in configs/router/default.ini
and if in module admin do not any thing
I tried using plugin but it doesn't work
in my plugin
class Australian_Controller_Plugin_DefaultRouter extends Zend_Controller_Plugin_Abstract {
public function routeShutdown(Zend_Controller_Request_Abstract $request) {
$currModule = $request->getModuleName();
if ($currModule != 'default') {
return;
}
$fontController = Zend_Controller_Front::getInstance();
$router1 = new Zend_Controller_Router_Rewrite();
$fontController->getRouter()->removeDefaultRoutes();
$myRoutes = new Zend_Config_Ini(APPLICATION_PATH . '/configs/router/default.ini', 'production');
$router1->addConfig($myRoutes, 'routes');
$fontController->setRouter($router1);
}
}
and /default/Bootstrap.php
protected function _initRoutes() {
$fontController = Zend_Controller_Front::getInstance();
$fontController->registerPlugin(new Australian_Controller_Plugin_DefaultRouter());
}
thanks

Note that you are adding new router after Routing so Zend already decoded address using old routes. This way you can generate URLs using new routes, but they will not e recognized by Zend. You need to call $router->route($request); again to set module/controller/action using new set of routes.
Sadly this is not working when its called in routeShutdown and has to be added to preDispatch(). Sadly I'm quite new to Zend too and still not grasping why it is so.
Code i used:
$fontController = Zend_Controller_Front::getInstance();
$router = $fontController->getRouter();
$r = new Zend_Controller_Router_Route(
'/testnew',
array(
'module' => 'user',
'controller' => 'index',
'action' => 'myaccount',
));
$router->addRoute('testnew', $r);
$router->route($request);

Related

Zend Framework Router Hostname and Multi-Language support

Last two days I was fighting with Zend Framework Router and still didn't find solution.
Existing project has 2 different modules which work with the same domain e.g. www.domain1.com:
default - Contains public information, can be accessed via www.domain1.com
admin - Administrator interface, can be accessed via www.domain1.com/admin
Project is multi-langual and to keep language code it is transmitted as first parameter of every URL, e.g. www.domain1.com/en/ www.domain1.com/en/admin
Part of code which takes care is next plugin:
class Foo_Plugin_Language extends Zend_Controller_Plugin_Abstract
{
const LANGUAGE_KEY = 'lang';
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$languagesRegexp = implode('|', array_map('preg_quote', $this->_bootstrap->getLanguages()));
$routeLang = new Zend_Controller_Router_Route(
':' . self::LANGUAGE_KEY,
array(self::LANGUAGE_KEY => $this->_bootstrap->getLanguage()->toString()),
array(self::LANGUAGE_KEY => $languagesRegexp)
);
$router = $this->getFrontController()->getRouter();
$router->addDefaultRoutes();
$chainSeparator = '/';
foreach ($router->getRoutes() as $name => $route) {
$chain = new Zend_Controller_Router_Route_Chain();
$chain
->chain($routeLang, $chainSeparator)
->chain($route, $chainSeparator);
$new_name = $this->_formatLanguageRoute($name);
$router->addRoute($new_name, $chain);
}
protected function _formatLanguageRoute($name)
{
$suffix = '_' . self::LANGUAGE_KEY;
if (substr($name, -strlen($suffix)) == $suffix) return $name;
return $name . '_' . self::LANGUAGE_KEY;
}
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$lang = $request->getParam(self::LANGUAGE_KEY, null);
$this->_bootstrap->setLanguage($lang);
$actual_lang = $this->_bootstrap->getLanguage()->toString();
$router = $this->getFrontController()->getRouter();
$router->setGlobalParam(self::LANGUAGE_KEY, $lang);
// Do not redirect image resize requests OR get js, css files
if (preg_match('/.*\.(jpg|jpeg|gif|png|bmp|js|css)$/i', $request->getPathInfo())) {
return true;
}
// redirect to appropriate language
if ($lang != $actual_lang) {
$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
$params = array(self::LANGUAGE_KEY => $actual_lang);
$route = $this->_formatLanguageRoute($router->getCurrentRouteName());
return $redirector->gotoRouteAndExit($params, $route, false);
}
}
}
One of the first question is what do you think about such way to provide multi-lang support. What I've noticed is that all this chains dramatically decrease operation speed of the server, response time from the server is about 4 seconds...
Main question is: Currently I have to implement such feature: I have domain www.domain2.com that should work just with single module e.g. "foobar"... and it should be available via second url... or, of course, it should work like www.domain1.com/en/foobar by default...
To provide this functionality in Bootstrap class I'be implemented such part of code
// Instantiate default module route
$routeDefault = new Zend_Controller_Router_Route_Module(
array(),
$front->getDispatcher(),
$front->getRequest()
);
$foobarHostname = new Zend_Controller_Router_Route_Hostname(
'www.domain2.com',
array(
'module' => 'foobar'
)
);
$router->addRoute("foobarHostname", $foobarHostname->chain($routeDefault));
And that is not working and as I've found routeDefault always rewrite found correct model name "foobar" with value "default"
Then I've implemented default router like this:
new Zend_Controller_Router_Route(
':controller/:action/*',
array(
'controller' => 'index',
'action' => 'index'
);
);
But that still didn't work, and started work without language only when I comment "routeStartup" method in Foo_Plugin_Language BUT I need language support, I've played a lot with all possible combinations of code and in the end made this to provide language support by default:
class Project_Controller_Router_Route extends Zend_Controller_Router_Route_Module
{
/**
* #param string $path
* #param bool $partial
* #return array
*/
public function match($path, $partial = false)
{
$result = array();
$languageRegexp = '%^\/([a-z]{2})(/.*)%i';
if (preg_match($languageRegexp, $path, $matches)) {
$result['lang'] = $matches[1];
$path = $matches[2];
}
$parentMatch = parent::match($path);
if (is_array($parentMatch)) {
$result = array_merge($result, $parentMatch);
}
return $result;
}
}
So language parameter was carefully extracted from path and regular processed left part as usual...
But when I did next code I was not able to get access to the foobar module via www.domain2.com url, because of module name in request was always "default"
$front = Zend_Controller_Front::getInstance();
/** #var Zend_Controller_Router_Rewrite $router */
$router = $front->getRouter();
$dispatcher = $front->getDispatcher();
$request = $front->getRequest();
$routerDefault = new Project_Controller_Router_Route(array(), $dispatcher, $request);
$router->removeDefaultRoutes();
$router->addRoute('default', $routerDefault);
$foobarHostname = new Zend_Controller_Router_Route_Hostname(
'www.domain2.com',
array(
'module' => 'foobar'
)
);
$router->addRoute("foobar", $foobarHostname->chain($routerDefault));
Instead of summary:
Problem is that I should implement feature that will provide access for the secondary domain to the specific module of ZendFramework, and I should save multi-language support. And I cannot find a way, how to manage all of this...
Secondary question is about performance of chain router, it makes site work very-very slow...
The way I have solved problem with multilanguage page is in this thread:
Working with multilanguage routers in Zend (last post).
Ofcourse my sollution need some caching to do, but I think it will solve your problem.
Cheers.

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.

Have a default controller in Zend

I have a module-based arhitecture in Zend Framework 1.11 (site.com/module/controller/action).
I've setup my site to have a default module, so that if I have the site module as default, and you go to site.com/something1/something2, it will actually take you to site.com/site/something1/something2.
I want to achieve the same thing 1 level further: say if you go to site.com/something, it should take you to site.com/site/index/something. I'm not talking about a redirect, just a re-routing.
Would something like this be possible?
If I understand correctly, it is possible and here is an example you can put in your Bootstrap:
protected function _initControllerDefaults()
{
$this->bootstrap('frontcontroller');
$front = Zend_Controller_Front::getInstance();
// set default action in controllers to "something" instead of index
$front->setDefaultAction('something');
// You can also override the default controller from "index" to something else
$front->setDefaultControllerName('default');
}
If you need the default action name to be dynamic based on the URL accessed, then I think you are looking for a custom route. In that case try:
protected function _initRoutes()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
// Custom route:
// - Matches : site.com/foo or site.com/foo/
// - Routes to: site.com/site/index/foo
$route = new Zend_Controller_Router_Route_Regex(
'^(\w+)\/?$',
array(
'module' => 'site',
'controller' => 'index',
),
array(1 => 'action')
);
$router->addRoute('actions', $route);
}

Prefix Folder structure for Zend

If i have a url such as this http://example.com/controller/action every thing works find. as expected. However i need to deploy this and in deployment things change a bit to htttp://deploy.com/stuff/pile/controller/action is there any way i can control this in zend.
Thanks in advance.
Add this route to your Bootstrap:
protected function _initRoute() {
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$router->addRoute(
'prefix_route',
new Zend_Controller_Router_Route('stuff/pile/:controller/:action',
array('controller' => $front->getRequest()->getControllerName(),
'action' => $front->getRequest()->getActionName())));
);
}

Zend Framework: How and where to create custom routes in a 1.8+ application?

I've never created a custom route before, but I finally have a need for one. My question is: How can I create a custom route, and where should I create it? I'm using Zend Framework 1.9.6.
Here's how I did it. There may be a better way, but I think this is as simple as it gets:
# /application/Bootstrap.php
protected function _initSpecialRoutes()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
$router->addRoute(
'verify', new Zend_Controller_Router_Route('verify/:token', array(
'controller' => 'account',
'action' => 'verify'))
);
$router->addRoute(
'arbitrary-route-name', new Zend_Controller_Router_Route('special/route/:variablename', array(
'controller' => 'defaultcontrollername',
'action' => 'defaultactionname'))
);
}
Here's where I define my custom routes:
// in bootstrap
Zend_Controller_Front::getInstance()->registerPlugin( new Prontiso_Controller_Plugin_Routes() );
...
<?php
// Prontiso/Controller/Plugin/Routes.php
class Prontiso_Controller_Plugin_Routes extends Zend_Controller_Plugin_Abstract
{
public function routeStartup( Zend_Controller_Request_Abstract $request )
{
Prontiso_Routes::addAll();
}
}
...
<?php
// Prontiso/Routes.php
class Prontiso_Routes extends Zend_Controller_Plugin_Abstract
{
public static function addAll()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
/**
* Define routes from generic to specific.
*/
/**
* Example: Simple controller/action route, guaranteed to eliminate any extra URI parameters.
*/
$router->addRoute(
'barebones', new Zend_Controller_Router_Route(':controller/:action')
);
}
}
See the Router documentation for the how. And I would make your routes in the bootstrap. Either program the routes by hand or load a configuration file.
I know there's already an accepted answer by #Andrew but I wanted to post this method that is very similar to his but I find cleaner.
If you dig into Zend_Controller_Router_Rewrite you will find an addRoutes() method which just iterates over each key and value and calls addRoute().
So here's my solution:
# /application/Bootstrap.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initRoutes()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
$loginRoute = new Zend_Controller_Router_Route('login', array('controller' => 'auth', 'action' => 'login'));
$logoutRoute = new Zend_Controller_Router_Route('logout', array('controller' => 'auth', 'action' => 'logout'));
$routesArray = array('login' => $loginRoute, 'logout' => $logoutRoute);
$router->addRoutes($routesArray);
}
}