I'm new to Zend, so pls help me out on this one, since I have searched a lot and tried a lot, I really did.
here is the very old question:
this is my current url:
www.sample.com/blog/detail/index/id/5
wanted:
www.sample.com/url-rewrite-tips
well, I put following code in the bootstrap.php
$router = Zend_Controller_Front::getInstance()->getRouter();
$route = new Zend_Controller_Router_Route(
'url-rewrite-tips',
array(
'module' => 'blog',
'controller' => 'detail',
'action' => 'index',
'id' => '5'
)
);
$router->addRoute('url-rewrite-tips', $route);
it was working, but it also is a hardcode. i tried to get param in bootstrap.php, but failed.
Now, I have more than 100 ids. However, I tried to put it in index.pthml, in a foreach(){} , then it fails.
I have rewrite names in the DB for every article, how am I supposed to it?
better not use configs or .htaccess
Thanks In advanced.
What I always do is I add the routes.ini execution in bootstrap:
protected function _initRoutes()
{
$this->bootstrap('FrontController');
$front = $this->getResource('FrontController');
$config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/routes.ini', 'production');
$router = $front->getRouter();
$router->addConfig($config, 'routes');
}
Then in routes.ini:
[production]
routes.content.route = "/s/:permalink"
routes.content.defaults.controller = "content"
routes.content.defaults.action = "show"
routes.content.reqs.permalink = "[a-z0-9-]+"
So now when someone access http://mydomain.com/s/some-nice-permalink routing goes to ContentController ShowAction() method, which takes permalink as param and finds it in database.
Of course you'll have to also write methods for creating unique permalinks in database.
Related
I have a site in zend framework . Now I am making site in multiple language. For it I need to modify the url.
For example if sitename is www.example.com then i want to make it like
www.example.com/ch
www.example.com/fr
There can be some work around it that you can ask me to create a folder name ch and put a copy of code inside it. But for it I have to manage multiple folder when updating files on server.
What is the best or correct way to do it ?
My routs code is
public function _initRouter() {
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$routes = array(
'page' => new Zend_Controller_Router_Route('page/:slug', array('controller' => 'staticpage', 'action' => 'page', 'slug' => ''))
);
$router->addRoutes($routes);
}
Thanks
You have to add the language as parameter in your route(s). Here is an example: http://devzone.zend.com/1765/chaining-language-with-default-route/
You need a function to get a user choice of a language and a default language used if a user just starts with example.com.
You may want to get the current browser and Language Header from the users HTTP request.
Take a look at Zend_Locale and Zend_Translate.
You can use something like $locale = new Zend_Locale('browser'); to detect the users browser language.
Then look if Zend_Translate or your translation engine has the language available and set it to a cookie or session to store the date.
If the user then navigate to some language change site like example.com/?language=en you may want to set the locale based on the user choice and recheck if available in your translations.
If not, get back to original default language and present an error page or something like that.
If you want to get your Zend_Router urls to be language dependent, which might be a bad choice because of copy paste, backlinks or forum posts of your links, you need to add something before each route.
In my Applications i use something like the following in my main bootstrap.php file. I've cut some parts of to keep it simple.
protected function _initTranslate() {
$session = new Zend_Session_Namespace("globals");
// Get current registry
$registry = Zend_Registry::getInstance();
/**
* Set application wide source string language
* i.e. $this->translate('Hallo ich bin ein deutscher String!');
*/
if(!$session->current_language) {
try {
$locale = new Zend_Locale('browser'); //detect browser language
}
catch (Zend_Locale_Exception $e) {
//FIXME: get from db or application.ini
$locale = new Zend_Locale('en_GB'); //use the default language
}
}
else {
$locale = new Zend_Locale($session->current_language);
}
$translate = new Zend_Translate(
array(
'adapter' => 'array',
'content' => realpath(APPLICATION_PATH . '/../data/i18n/'),
'locale' => $locale,
'scan' => Zend_Translate::LOCALE_DIRECTORY,
'reload' => false,
'disableNotices' => true, //dont get exception if language is not available
'logUntranslated' => false //log untranslated values
)
);
if(!$translate->isAvailable($locale->getLanguage())) {
$locale = new Zend_Locale('en_GB'); //default
}
$translate->setLocale($locale);
$session->current_language = $locale->getLanguage();
//Set validation messages
Zend_Validate_Abstract::setDefaultTranslator($translate);
//Max lenght of Zend_Form Error Messages (truncated with ... ending)
Zend_Validate::setMessageLength(100);
//Zend_Form Validation messages get translated into the user language
Zend_Form::setDefaultTranslator($translate);
/**
* Both of these registry keys are magical and makes do automagical things.
*/
$registry->set('Zend_Locale', $locale);
$registry->set('Zend_Translate', $translate);
return $translate;
}
This is for the default translation setup of each visitor.
To set a user language depending on some HTTP parameters, I decided to create a Plugin, which will run on each request, see if the global language parameter is set (key=_language) and try setting the new language.
I then redirect the user to the new route, depending on his choice.
So, if the user click on the link for english language (example.com/de/test/123?_language=en) he will get redirected to example.com/en/test/123.
class Application_Plugin_Translate extends Core_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$frontController = Zend_Controller_Front::getInstance();
// Get the registry object (global vars)
$registry = Zend_Registry::getInstance();
// Get our translate object from registry (set in bootstrap)
$translate = $registry->get('Zend_Translate');
// Get our locale object from registry (set in bootstrap)
$locale = $registry->get('Zend_Locale');
// Create Session block and save the current_language
$session = new Zend_Session_Namespace('globals');
//get the current language param from request object ($_REQUEST)
$language = $request->getParam('_language',$session->current_language);
// see if a language file is available for translate (scan auto)
if($translate->isAvailable($language)) {
//update global locale
$locale = $registry->get('Zend_Locale');
$locale->setLocale($language);
$registry->set('Zend_Locale', $locale);
//update global translate
$translate = $registry->get('Zend_Translate');
$translate->setLocale($locale);
$registry->set('Zend_Translate', $translate);
//language changed
if($language!=$session->current_language) {
//update session
$session->current_language = $language;
$redirector = new Zend_Controller_Action_Helper_Redirector;
$redirector->gotoRouteAndExit(array());
}
}
else {
$request->setParam('_language', '');
unset($session->current_language);
$redirector = new Zend_Controller_Action_Helper_Redirector;
$redirector->gotoRouteAndExit(array());
}
}
}
And finally, to prepare your router with the new language routes, you need to setup a base language route and chain your other language depending routes.
public function _initRouter() {
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$languageRoute = new Zend_Controller_Router_Route(
':language',
array(
'language' => "de"
),
array('language' => '[a-z]{2}')
);
$defaultRoute = new Zend_Controller_Router_Route(
':#controller/:#action/*',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'index'
)
);
$router->addRoute(
'default',
$defaultRoute
);
$languageDefaultRoute = $languageRoute->chain($defaultRoute);
$router->addRoute(
'language',
$languageDefaultRoute
);
}
Good luck with your project, hope it will help you and others!
Hi I'm new to the php world.
I'm wondering What is the best way to handle multilingual routing ?
I'm starting to create a website with Phalcon php.
I have the following routing structure.
$router->add('/{language:[a-z]{2}}/:controller/:action/:params', array(
'controller' => 2,
'action' => 3,
'params' => 4,
));
$router->add('/{language:[a-z]{2}}/:controller/:action', array(
'controller' => 2,
'action' => 3,
));
$router->add('/{language:[a-z]{2}}/:controller', array(
'controller' => 2,
'action' => 'index',
));
$router->add('/{language:[a-z]{2}}', array(
'controller' => 'index',
'action' => 'index',
));
My problem is for instance when I go on mywebsite.com/ I want to change my url in the dispatcher like mywebsite.com/en/ or other language. Is it a good practise to handle it in the beforeDispatchLoop ? I seek the best solutions.
/**Triggered before entering in the dispatch loop.
* At this point the dispatcher don't know if the controller or the actions to be executed exist.
* The Dispatcher only knows the information passed by the Router.
* #param Event $event
* #param Dispatcher $dispatcher
*/
public function beforeDispatchLoop(Event $event, Dispatcher $dispatcher)
{
//$params = $dispatcher->getParams();
$params = array('language' => 'en');
$dispatcher->setParams($params);
return $dispatcher;
}
This code doesn't work at all, my url is not change. The url stay mywebsite.com/ and not mywebsite.com/en/
Thanks in advance.
I try one solution above.
The redirect doesn't seems to work. I even try to hard-coded it for test.
use Phalcon\Http\Response;
//Obtain the standard eventsManager from the DI
$eventsManager = $di->getShared('eventsManager');
$dispatcher = new Phalcon\Mvc\Dispatcher();
$eventsManager->attach("dispatch:beforeDispatchLoop",function($event, $dispatcher)
{
$dispatcher->getDI->get('response')->redirect('/name/en/index/index/');
}
I think you are confusing something. If I understand correctly: you want to redirect users to a valid url if they open a page without specifying a language.
If that's the case you should verify in your event handler whether the language parameter is specified and redirect user to the same url + the default language if its missing. I am also assuming that your beforeDispatchLoop is located in your controller, which is also part of the problem, because your route without a language never matches and you never get into that controller. Instead you need to use it as an event handler with the event manager as per the documentation. Here is how you do the whole thing.
$di->get('eventsManager')->attach("dispatch:beforeDispatchLoop", function(Event $event, Dispatcher $dispatcher)
{
$params = $dispatcher->getParams();
// Be careful here, if it matches a valid route without a language it may go into a massive
// recursion. Really, you probably want to use `beforeExecuteRoute` event or explicitly
// check if `$_SERVER['REQUEST_URI']` contains the language part before redirecting here.
if (!isset($params['language']) {
$dispatcher->getDI->get('response')->redirect('/en' . $_SERVER['REQUEST_URI']);
return false;
}
return $dispatcher;
});
I am trying here to create url, like:
/admin/login
/moderator/login
both the request would be served by same controller & action made for login, i.e. /account/login/<type>
Currently, all I am able to make the following URL:
/login/admin
/login/moderator
My current config file looks like the following:
resources.router.routes.login.route = "login/:type"
resources.router.routes.login.defaults.controller = "account"
resources.router.routes.login.defaults.action = "login"
I can't figure out, on how to put the type variable at the start of URL, I tried it but it gives server error.
edit
I got this done, but can't understand why this didn't work earlier:
resources.router.routes.login.route = ":type/login"
resources.router.routes.login.defaults.controller = "account"
resources.router.routes.login.defaults.action = "login"
edit
Is it possible to make this arrangement more flexible, so that:
/login => /admin/login
I am not looking for solution via .htaccess
Add the following to your Bootstrap.php
function _initRoutes() {
$front_controller = Zend_Controller_Front::getInstance();
$router = $front_controller->getRouter();
$router->addRoute('login', new Zend_Controller_Router_Route(
'/:type/login', array('controller' => 'account', 'action' => 'login')
));
}
from your loginAction()
use:
$this->getRequest()->getParam('type');
Simple?
I'm writing a Zend Framework application and its not a big deal but I can't figure out (even after googling) how to remove the /index/ from the url
So I currently have this
http://myapplication.local/index/home
When I really want
http://myapplication.local/home
I understand it may be possible to do this via the .htaccess?
The issue occurs because Zend by default uses controller/action urls (which is a default route). Because your root controller is IndexController and the action is IndexController::homeAction it is accessed via index/home.
The easiest way to do what you want is adding routes to the application.ini as follows:
resources.router.routes.home_route_or_any_name.route = "home"
resources.router.routes.home_route_or_any_name.defaults.module = "default"
resources.router.routes.home_route_or_any_name.defaults.controller = "index"
resources.router.routes.home_route_or_any_name.defaults.action = "home"
You can change home_route_or_any_name to anything you want. You can also add many routes definitions to fit your needs.
For more information refer to Zend Framework Documentation
You can try this in bootstrap.php
/**
* Setup Routig.
* Now all calls are send to indexController like
* URL/ACTION-1
* URL/ACTION-2
*
* #return void
**/
protected function _initRouters()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
$route = new Zend_Controller_Router_Route(
':action/*',
array(
'controller' => 'index',
'action' => 'index'
)
);
$router->addRoute('default', $route);
}
I will remove index from all the action generated from indexController.
OR
in application.ini
routes.index.type = "Zend_Controller_Router_Route"
routes.index.route = "/"
routes.index.defaults.module = "default"
routes.index.defaults.controller = "index"
routes.index.defaults.action = "index"
For molre detail on routing you can read here
I can't seem to figure out what's going wrong, but I'm attempting to setup module routing based on sub domain. Otherwise the routing is standard. The following works until I add more than 3 parameters in the URL:
This is within a controller plugin
...
public function routeStartup() {
$router = Zend_Controller_Front::getInstance()->getRouter();
$pathRoute = new Zend_Controller_Router_Route (
':controller/:action/*',
array(
'controller' => 'index',
'action' => 'index'
)
);
$hostRoute = new Zend_Controller_Router_Route_Hostname(':module.domain.com');
$chainedRoute = $hostRoute->chain($pathRoute);
$router->addRoute('host', $chainedRoute);
...
}
http://module.domain.com/controllerName/actionName/param1 works
http://module.domain.com/controllerName/actionName/param1/param2 does not work
Has anyone else run into this?
Looks like a bug in the framework routing code.
See http://framework.zend.com/issues/browse/ZF-6654 for a fix.