how to make nice rewrited urls from a router - php

I'm making a toolkit for php applications. I've a made a routing system based on some conventions, it works well but i would like to learn how to make mod_rewrite rules or any other stuff to finally make the url good to see and good for seo.
The route system starts from a config file that set the app and url roots.
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
The route always get start from index.php, wich makes instances of controllers#actions from GET parameters controllers=?&action=?
This is the index.php
<?php
include_once 'controller/Frontend.php';
require 'libraries/Router.php';
$params=array();
if(isset($_GET['controller'])&&isset($_GET['action'])){
$c = $_GET['controller'];
$a = $_GET['action'];
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_GET);
$queryValues = array_values($_GET);
for ($i=2;$i<count($queryParams);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
if ($_POST) {
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_POST);
$queryValues = array_values($_POST);
for ($i=0;$i<count($_POST);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
}
include_once APP_ROOT."/controller/$c.php";
$controller = new $c();
$controller->$a($params);
} else {
//attiva controller predefinito
$controller = new Frontend();
$controller->index();
}
This allow to select what controller and what action the router must call.
The router function here get the APP URL from settings.php in the root. You give im the two controllers#action params as string and it make the URL like so:
index.php?controller=X&action=Y&[params...]
<?php
require './settings.php';
function router($controller,$action,$query_data="") {
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = APP_URL."index.php?controller=$controller&action=$action&$param";
return $url;
}
function relativeRouter ($controller,$action,$query_data=""){
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = "index.php?controller=$controller&action=$action&$param";
return $url;
}
function redirectToOriginalUrl() {
$url = $_SERVER['HTTP_REQUEST_URI'];
header("location: $url");
}
function switchAction ($controller, $action) {
$r = router($controller, $action);
header("location:$r", true, 302);
}
In templates file i call router('controller,'action') to retrive url's to actions and also pass GET/POST data (collected from index.php that put's them into the method signature as array).
Don't blame me for using global POST/GET without filtering i'm still developing the thing, security things will be made after ;)
What i would like to ask if someone could share some thoughts on how to make pretty urls like site/page/action....
For example www.site.com/blog/post?id=1
(Actually the N params in the router function ($query_data) works this way, you pass array['id' => '1'] and you get ?id=1)
What are best strategies to make good urls?
Thank you so much, still learning PHP.
If there are best way to do such things just give your feedback.

I found myself an answer to the question, i post here maybe it's useful.
I've added a .htaccess file in the root:
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
This will return each request to the root/index.php file.
Index file collect routes from the HTTP request, check if the route exist in the "routes.json" file.
URL are written in this way:
site.com/controller/action. GET params are written as follows
site.com/controller/action/[params]/[value]...... This output for example site.com/blog/post/id/1
That should be also fine for REST.
Here the index.php
<?php
require 'controller/Frontend.php';
require 'Class/Router.php';
//require 'libraries/Router.php';
/*
* ** ROUTING SETTINGS **
*/
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
$basepath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1));
$uri = substr($_SERVER['REQUEST_URI'], strlen($basepath));
//echo $uri;
if ($uri == "/") {
$frontend = new Frontend();
$frontend->index();
} else {
$root = ltrim ($uri, '/');
//$paths = explode("/", $uri);
$paths = parse_url($root, PHP_URL_PATH);
$route = explode("/",$paths);
$request = new \PlayPhp\Classes\Request();
// controller
$c = $route[0];
// action
$a = $route[1];
$reverse = Router::inverseRoute($c,$a);
$rest = $_SERVER['REQUEST_METHOD'];
switch ($rest) {
case 'PUT':
//rest_put($request);
break;
case 'POST':
if (Router::checkRoutes($reverse, "POST")) {
foreach ($_POST as $name => $value) {
$request->setPost($name,$value);
}
break;
} else {
Router::notFound($reverse,"POST");
}
case 'GET':
if (Router::checkRoutes($reverse, "GET")) {
for ($i = 2; $i < count($route); $i++) {
$request->setGet($route[$i], $route[++$i]);
}
break;
} else {
Router::notFound($reverse,"GET");
}
break;
case 'HEAD':
//rest_head($request);
break;
case 'DELETE':
//rest_delete($request);
break;
case 'OPTIONS':
//rest_options($request);
break;
default:
//rest_error($request);
break;
}
include_once APP_ROOT.'controller/'.$c.'.php';
$controller = new $c();
$controller->$a($request);
}
The Router class:
<?php
include 'config/app.php';
/*
* Copyright (C) 2015 yuri.blanc
*/
require 'Class/http/Request.php';
class Router {
protected static $routes;
private function __construct() {
Router::$routes = json_decode(file_get_contents(APP_ROOT.'config/routes.json'));
}
public static function getInstance(){
if (Router::$routes==null) {
new Router();
}
return Router::$routes;
}
public static function go($action,$params=null) {
$actions = explode("#", $action);
$c = strtolower($actions[0]);
$a = strtolower($actions[1]);
// set query sting to null
$queryString = null;
if(isset($params)) {
foreach ($params as $name => $value) {
$queryString .= '/'.$name.'//'.$value;
}
return APP_URL."$c/$a$queryString";
}
return APP_URL."$c/$a";
}
public static function checkRoutes($action,$method){
foreach (Router::getInstance()->routes as $valid) {
/* echo $valid->action . ' == ' . $action . '|||';
echo $valid->method . ' == ' . $method . '|||';*/
if ($valid->method == $method && $valid->action == $action) {
return true;
}
}
}
public static function inverseRoute($controller,$action) {
return ucfirst($controller)."#".$action;
}
public static function notFound($action,$method) {
die("Route not found:: $action with method $method");
}
}
I use the json_decode function to parse the json object in stdClass().
The json file looks like this:
{"routes":[
{"action":"Frontend#index", "method":"GET"},
{"action":"Frontend#register", "method":"GET"},
{"action":"Frontend#blog", "method":"GET"}
]}
This way i can whitelist routes with their methods and return 404 errors while not found.
System is still quite basic but gives and idea and works, hope someone will find useful.

Related

Joomla component router

I'm trying to follow the instructions on this docs page, but I seem to be missing something:
https://docs.joomla.org/Supporting_SEF_URLs_in_your_component
The URI that needs to be corrected is: index.php?com_component&view=legal&page=customermasteragreement
It seems like the routing function should be simple, but the page is just displaying default instead of the sub-view.
Here's my current code:
function ComponentBuildRoute(&$query)
{
$segments = array();
if (isset($query['view'])) {
$segments[] = $query['view'];
unset($query['view']);
}
if (isset($query['page'])) {
$segments[] = $query['page'];
unset($query['page']);
}
return $segments;
}
function ComponentParseRoute($segments)
{
$vars = array();
switch($segments[0])
{
case 'legal':
$vars['view'] = 'legal';
break;
case 'customermasteragreement':
$vars['page'] = 'customermasteragreement';
break;
}
return $vars;
}
Update
This code works to display the subpage, but it gives me a URI like: legal-agreements/legal?page=customermasteragreement
class ComponentRouter extends JComponentRouterBase {
public function build(&$query) {
$segments = array();
$view = null;
if (isset($query['view'])) {
$segments[] = $query['view'];
$view = $query['view'];
unset($query['view']);
}
if (isset($query['id'])) {
if ($view !== null) {
$segments[] = $query['id'];
} else {
$segments[] = $query['id'];
}
unset($query['id']);
}
return $segments;
}
public function parse(&$segments) {
$vars = array();
// View is always the first element of the array
$vars['view'] = array_shift($segments);
return $vars;
}
}
EDIT 2
If it helps, here's my model and views
models/legal.php
// import Joomla modelitem library
jimport('joomla.application.component.modelitem');
class ComponentModelLegal extends JModelItem {
public function __construct($config = array())
{
JLoader::register('ComponentHelper', JPATH_COMPONENT_ADMINISTRATOR . '/helpers/component.php');
parent::__construct($config);
}
/**
*
* #return string
*/
public function getLegal() {
$app = JFactory::getApplication();
$page = $app->input->get('page', '', 'STRING');
if ($page) {
ComponentHelper::add('type', $page); //This is an API request to an external service, returning JSON formatted data
$legal = ComponentHelper::getData('commons/legal-agreements.json', TRUE);
if (isset($legal[0]['status'])) {
JError::raiseError(400, $legal[0]['ERROR']);
return false;
} else {
if (!isset($this->legal)) {
$this->legal = $legal;
}
return $this->legal;
}
}
}
}
views/legal/view.html.php
class ComponentViewLegal extends JViewLegacy {
function display($tpl = null) {
// Assign data to the view
$this->legal = $this->get('legal');
// Check for errors.
if (count($errors = $this->get('Errors'))) {
JLog::add(implode('<br />', $errors), JLog::WARNING, 'jerror');
return false;
}
// Display the view
parent::display($tpl);
}
}
views/legal/tmpl/default.php
$page = JRequest::getVar('page');
$pages = array(
'resellermasteragreement',
'customermasteragreement',
'resellerdomainagreement',
'customerdomainagreement',
'resellerwebserviceagreement',
'customerwebserviceagreement',
'resellerdigicertagreement',
'customerdigicertagreement',
'registraragreement',
'customerhostingproductagreement',
'resellerhostingproductagreement'
);
?>
<div class="col-lg-12">
<?php
echo in_array($page, $pages) ? $this->loadTemplate('legal') : $this->loadTemplate('home');
?>
</div>
views/legal/tmpl/default_legal.php
$page = JRequest::getVar('page');
echo nl2br(htmlspecialchars($this->legal[$page]['defaultagreement'], ENT_NOQUOTES, "UTF-8"));
?>
<a type="button" class="btn btn-primary" href="<?php echo JROUTE::_("index.php?option=com_component&view=legal"); ?>">Back</a>
EDIT 3
This works because I wasn't navigating directly to the page from a menu item. There's a top level menu, then a page a links to the agreements. I have a hidden menu to each item, but that wasn't the link I followed.
$app = JFactory::getApplication()->getMenu();
$customermaster = $app->getItems( 'link', 'index.php?option=com_component&view=legal&page=customermasteragreement', true );
JRoute::_('index.php?Itemid='.$customermaster->id);
You have one view but you're not actually set the page argument correctly when you catch a view argument, but you treat page as some king of another view. Can you please try this and check if it works:
function [componentname]ParseRoute($segments)
{
$vars = array();
switch($segments[0])
{
case 'legal':
$vars['view'] = 'legal';
$vars['page'] = $segments[1];
break;
}
return $vars;
}
Also the functions ComponentBuildRoute, ComponentParseRoute must have your components name instead of Component at the beginning.
EDIT
[componentname]BuildRoute and [componentname]ParseRoute are deprecated, you should stick the the class that extends JComponentRouterBase as you have it in your updated second example. Try this one here and see if it works:
class ComponentRouter extends JComponentRouterBase {
public function build(&$query) {
$segments = array();
$view = null;
if (isset($query['view'])) {
$segments[] = $query['view'];
$view = $query['view'];
unset($query['view']);
}
if (isset($query['page'])) {
$segments[] = $query['page'];
unset($query['page']);
}
return $segments;
}
public function parse(&$segments) {
$vars = array();
// View is always the first element of the array
$vars['view'] = array_shift($segments);
if(count($segments) > 0)
$vars['page'] = array_shift($segments);
return $vars;
}
}
EDIT 2
I have a test Joomla 3 site with a simple component named Ola.
Non SEO component URL: http://j3.dev.lytrax.net/index.php?option=com_ola&page=test_page&view=ola
URL generated by JRoute before Router class added to router.php: http://j3.dev.lytrax.net/index.php/component/ola/?page=test_page&view=ola
SEO URL returned by JRoute::_('index.php?option=com_ola&page=test_page&view=ola'); after creating router.php and used the Router class above: http://j3.dev.lytrax.net/index.php/component/ola/ola/test_page
If you visit the links, you'll see that all are working and you can even see the page, view and JRoute results of the calling component Ola.
Unless I've completely misunderstood Joomla (I've been developing with it for four five years now), there is no "sub-view" concept implemented. Trying to use the idea is what's getting you into trouble I think.
I'm astounded that the idea of using a visual debugger is so unpopular.
Get yourself something like Netbeans (there are others too), set up a local web and database server, and watch the code run. Very (well, relatively very) quickly you'll start to understand how the structure hangs together.
You may put code in your view that picks up the extra params you've set and displays or hides things accordingly, but there is no "sub-view".

MVC - Looking for a better way to get from URL to view

The below example shows how I am currently doing things.
index.php includes index_controller.php then index_template.php.
index_controller.php
$uri = explode('/', $_SERVER['REQUEST_URI']);
$action = $uri[1];
$call = $uri[2];
$tmp = explode('?', $call);
$call = $tmp[0];
$call = preg_replace('/-/', ' ', $call);
switch ($action) {
case "about":
$page = "about.inc.php";
$title = "About Us";
$description = "Description of page";
break;
case "category":
try {
//PDO query to make sure category ($call) exists
}
catch (PDOException $e) {
logError($e->getMessage());
}
if (query->rowCount() < 1) {
$page = "404.inc.php";
$title = "404 Error";
}
else {
//Meta information for selected category pulled from DB and put into variables.
$page = "category.inc.php";
break;
default:
$page = "404.inc.php";
$title = "404 Error";
}
The above example shows 2 of around 12 different page options in the switch statement. A simple request (about) and a more complex request (category).
index_template.php has all my head, body, and footer HTML. It sets the meta data for the page, sets up the sites structure, and includes whatever file the $page variable is set to in index_controller.php
Using the above example, if someone goes to mysite.com/category/books index_controller.php will see if the books category exists and if it does category.inc.php will be included.
category.inc.php does another PDO query to get all the items and information required to display a list of items for the selected category. It also includes a template file to structure the display of the returned items.
I am trying to achieve a MVC type structure (without using a framework like Codeigniter or CakePHP), but I don't really have the model end down.
How can I get the user from the URL to the view using classes and/or functions instead of all the includes I am currently using?
If you feel I didn't do a good job explaining the other files mentioned I can provide code examples from those files as well.
Any help, input, or suggestions will be greatly appreciated.
EDIT: Clarified question as per comment below.
With a little trick and with .htaccess you can make this much easier.
I use this method in my self made MVC based application. You can copy paste the whole code or just use a part of it. The main logic is in the Bootstrap class.
.htaccess
Options -Indexes
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
RewriteRule ^$ /news [R]
index.php
require 'brInit.php';
$app = new \brInclude\brClasses\mvc\Bootstrap();
I use brInit to automatically include classes and to include my config file
Bootstrap.php
class Bootstrap {
private $url = array();
/** #var Controller $controller */
private $controller;
function __construct(){
try {
$this->_getUrl();
$this->_loginUser();
if(!$this->_setController($this->url[0]))
throw new Exception('404');
if(!$this->_executeControllersMethod())
throw new Exception('404');
} catch(Exception $e){
$this->_error($e->getMessage());
}
}
private function _error($msg){
$this->url = array('Error', 'error', $msg);
$this->_setController($this->url[0]);
$this->_loginUser();
$this->_executeControllersMethod();
}
private function _getUrl(){
if(isset($_GET['url']))
$this->url = explode('/', rtrim($_GET['url'], '/'));
else
$this->url = array('news');
unset($_GET['url']);
}
private function _setController($name){
$path = 'brInclude/brMVC/controller/';
if(!file_exists($path)) return false;
$url = ucfirst($name) . 'Controller';
$namespace = str_replace('/', '\\', $path);
$file = $path . $url . '.php';
if(!file_exists($file)) return false;
$classWithNamespace = $namespace . $url;
$this->controller = new $classWithNamespace;
$this->controller->view->name = $name;
return true;
}
private function _loginUser(){
$model = new UserModel();
$user = $model->login();
Controller::$user = $user;
}
private function _executeControllersMethod(){
if(isset($this->url[1])){
if(method_exists($this->controller, $this->url[1])){
$count = count($this->url);
if($count > 2)
call_user_func_array(
array($this->controller, $this->url[1]),
array_slice($this->url, 2)
);
else
$this->controller->{$this->url[1]}();
} else {
return false;
}
} else {
$this->controller->index();
}
return true;
}
public static function isLoginRequired(){
return self::$loginRequired;
}
}

Rest api controller

I have build a Rest webservice that has a mvc structure, but I need some suggestion on how to make it better.
What I have right know is :
all the request come to the front controller (index.php)
$request = new Request(); //parse all the elements of the request
// spl_api_autoload takes care for loading the classes
$controller_name = ucfirst($request->url_elements[1]) . 'Controller';
if (class_exists($controller_name)) {
$controller = new $controller_name();
$action_name = strtolower($request->verb) . 'Action';
$result = $controller->$action_name($request);
} // this acts like a sort of router
The url looks like this:
index.php/tree/addnode/4/testnode
tree -> Resource
addnode -> action
4 -> parent id
testnode -> node name
What I need a suggestion is in this part down here (controller) :
if(isset($request->url_elements[2])) {
switch ($request->url_elements[2]) {
case 'addroot':
if(isset($request->url_elements[3])) {
$name = $request->url_elements[3];
$nested = new NestedSetClass();
$nested->createRootNode($name);
}
return $data;
break;
case 'addnode':
if(isset($request->url_elements[3])) {
if(isset($request->url_elements[4])) {
$parent = $request->url_elements[3];
$name = $request->url_elements[4];
$nested = new NestedSetClass();
$nested->insertChildNode($name,$parent);
}
}
break;
default:
# code...
break;
}
}
I want to skip the switch cases , Is there anyway I can do this ?
Thank you very very much for your time
When doing something like this I used the html methods like so
$app = App::init();
try{
//Pass the information here so data can be handled
//This makes it easier for other people who are new to oop, but not really correct
$app->$method($target, $data)
}catch(Exception e){ //handle error }
App Class
public function get($target, $data); get resource from db
public function post($target, $data); post resource to db
etc.
Sample of post
function post($target, $data)
{
$control = new $target();
return $control->handle($data);
}

Yii and multilingual URLs

I'm trying to create multilingual application. I've implemented ability of translationable content and next step should be showing it to user. I want to have ability of changing language depending on URL. I've found a couple of components for those purposes but they all create urls which I don't like. For example, my application's default language is English and I have content which is translated into French. I have page "contacts", for instance. And URLs which will be generated by application will be: mysite.com/en/contacts, mysite.com/fr/contacts, but I want to have mysite.com/contacts for default language and mysite.com/fr/contacts for French language. It's simillar for site's root too. mysite.com/ - for default language and mysite.com/fr for French.
Is there any methods for implementing these functionality?
I'm using XUrlManager extension XUrlManager on GitHub
Yii generates URL's based on UrlManager rules. If you want URL's without /lang/ code - you need just create correct rules. For example, if you dublicate records in rules array:
'rules'=>array(
'<_c:\w+>/<_a:\w+>'=>'<_c>/<_a>',
'<language:\w{2}>/<_c:\w+>/<_a:\w+>'=>'<_c>/<_a>',
);
your URL's will be generated withou /en/ and /fr/, but URL's with code works too. By default, XUrlManager use previously selected language and store this in session or cookie.
If you want only hide /en/ and use /fr/ and others always, you can change your XUrlManager extension with:
public function createUrl($route,$params=array(),$ampersand='&')
{
if(!isset($params['language']) && Yii::app()->language!=='en')
$params['language']=Yii::app()->language;
return parent::createUrl($route,$params,$ampersand);
}
I've found very elegant method for solving my problem on http://www.elisdn.ru
Reimplement CHttpRequest
class DLanguageHttpRequest extends CHttpRequest
{
private $_requestUri;
public function getRequestUri()
{
if ($this->_requestUri === null)
$this->_requestUri = DMultilangHelper::processLangInUrl(parent::getRequestUri());
return $this->_requestUri;
}
public function getOriginalUrl()
{
return $this->getOriginalRequestUri();
}
public function getOriginalRequestUri()
{
return DMultilangHelper::addLangToUrl($this->getRequestUri());
}
}
Reimplement CUrlManager
class DLanguageUrlManager extends CUrlManager
{
public function createUrl($route, $params=array(), $ampersand='&')
{
$url = parent::createUrl($route, $params, $ampersand);
return DMultilangHelper::addLangToUrl($url);
}
}
Change config
return array(
'sourceLanguage'=>'en',
'language'=>'ru',
'components'=>array(
'request'=>array(
'class'=>'DLanguageHttpRequest',
...
),
'urlManager'=>array(
'class'=>'DLanguageUrlManager',
...
),
),
...
'params'=>array(
'translatedLanguages'=>array(
'ru'=>'Russian',
'en'=>'English',
'de'=>'Deutsch',
),
'defaultLanguage'=>'ru',
),
);
Create DMultilangHelper
class DMultilangHelper
{
public static function enabled()
{
return count(Yii::app()->params['translatedLanguages']) > 1;
}
public static function suffixList()
{
$list = array();
$enabled = self::enabled();
foreach (Yii::app()->params['translatedLanguages'] as $lang => $name)
{
if ($lang === Yii::app()->params['defaultLanguage']) {
$suffix = '';
$list[$suffix] = $enabled ? $name : '';
} else {
$suffix = '_' . $lang;
$list[$suffix] = $name;
}
}
return $list;
}
public static function processLangInUrl($url)
{
if (self::enabled())
{
$domains = explode('/', ltrim($url, '/'));
$isLangExists = in_array($domains[0], array_keys(Yii::app()->params['translatedLanguages']));
$isDefaultLang = $domains[0] == Yii::app()->params['defaultLanguage'];
if ($isLangExists && !$isDefaultLang)
{
$lang = array_shift($domains);
Yii::app()->setLanguage($lang);
}
$url = '/' . implode('/', $domains);
}
return $url;
}
public static function addLangToUrl($url)
if (self::enabled())
{
$domains = explode('/', ltrim($url, '/'));
$isHasLang = in_array($domains[0], array_keys(Yii::app()->params['translatedLanguages']));
$isDefaultLang = Yii::app()->getLanguage() == Yii::app()->params['defaultLanguage'];
if ($isHasLang && $isDefaultLang)
array_shift($domains);
if (!$isHasLang && !$isDefaultLang)
array_unshift($domains, Yii::app()->getLanguage());
$url = '/' . implode('/', $domains);
}
return $url;
}
}
After all of these steps your application will have URLs which you want
More information here

Url language prefix with zend framework

I'm lost in the url rewriting of Zend Framework !
I have a route.ini like that :
routes.page.route = :slug
and I have a call in the bootstrap like that :
protected function _initRoutes() {
$uri = explode('/', $_SERVER['REQUEST_URI']);
if (!in_array('admin', $uri)) {
//$front = Zend_Controller_Front::getInstance();
$config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/routes.ini');
$router = $front->getRouter();
$router->addConfig($config, 'routes');
$front->registerPlugin(new Rez_Controller_Plugin_Routing(), 2);
}
}
the plugin is like that:
class Rez_Controller_Plugin_Routing extends Zend_Controller_Plugin_Abstract {
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$item_db = new Application_Model_DbTable_Item();
if(NULL != $request->getParam("slug")){
if("admin" == $request->getParam("slug")){
$request->setModuleName('admin');
$request->setControllerName("index");
$request->setActionName('index');
}
$page = $item_db->getPage($request->getParam("slug"));
if(FALSE == $page){
$request->setModuleName('default');
$request->setControllerName($request->getParam("slug"));
$request->setActionName('index');
return;
}else{
if(NULL !== $request->getParam("language")){
$page["lang"] = $request->getParam("language");
}
$request->setModuleName('default');
$request->setControllerName("index");
$request->setActionName('page');
$request->setParams($page);
return;
}
}
}
the problem is that I have to prepend a language prefix in URL "htttp://mywebsite.com/en/a-simple-page" only when the language of the browser is English or when the user have clicked the English flag, otherwise, the URL have to be like "http://mywebsite.com/a-simple-page".
I tried to add this in route.ini :
routes.page.route = :language/:slug
routes.page.reqs.language = "^(en|nl)$"
routes.page.defaults.language = "nl"
but when I tried "http://mywebsite.com/a-simple-page" it doesn't work while "http://mywebsite.com/en/a-simple-page" worked and I can get the param in the plugin. How to make it accept all URL even when a language code is not in the URL?
For this to work you will need to chain 2 routes.
resources.router.routes.defaultmodule.type = Zend_Controller_Router_Route_Module
resources.router.routes.defaultmodule.abstract = On
resources.router.routes.defaultmodule.defaults.module = "default"
resources.router.routes.locale.type = Zend_Controller_Router_Route
resources.router.routes.locale.route = ":locale"
resources.router.routes.locale.reqs.locale = "^(en)$"
resources.router.routes.locale.defaults.locale = "nl"
resources.router.routes.default.type = Zend_Controller_Router_Route_Chain
resources.router.routes.default.chain = "locale,defaultmodule"
Keep in mind that having same content under 2 urls is not good due to SEO implications. A redirect would be more appropriate.

Categories