Cakephp routes for multilingual cms - cakephp

I'm trying to create a Route in Cakephp that can have anything as a prefix. But I also want the admin route to work properly.
The prefix would in this case be a language. The Route has to link to a controller named front with action: index.
A url should look like this
www.domain.com/eng/the/rest/of/the/url_12 or
www.domain.com/nl/the/rest/of/the/url_12
This is what I have, wich means that I have to create a route for each language, and thats not what I want.
Router::connect('/', array('controller' => 'front', 'action' => 'index'));
Router::connect('/admin', array('controller' => 'cms', 'action' => 'index', 'admin' => true));
Router::connect('/nl/*', array('controller' => 'front', 'action' => 'index'));

You can use this:
Router::connect('/:i10n/:controller', array('action' => 'index'), array('i10n' => '[a-z]{2}'));
Router::connect('/:i10n/:controller/:action/*', array(), array('i10n' => '[a-z]{2}'));

Related

How to use internationalization in cakephp with custom URL and extensions

I am using cakephp 2.0 for an application...
everything is fine but I am getting some problem with custom URL or SEO friendly URL.
Here are Route rules that I am using
Router::parseExtensions('html', 'rss', 'xml','json');
Router::connect('/:language/:controller/:action/*',array(),array('language' => 'eng|chi'));
Router::connect('/', array('controller' => 'homes', 'action' => 'index'),array('language' => 'eng|chi'));
Router::connect('/backend/*', array('controller' => 'users', 'action' => 'login', 'lab' => true));
Router::connect('/about-us/*', array('controller' => 'homes', 'action' => 'about_us'));
Router::connect('/contact/*', array('controller' => 'homes', 'action' => 'contact'));
Router::connect('/:slug', array('controller' => 'homes', 'action' => 'page'), array('pass' => array('slug'), 'slug'=>'[a-zA-Z0-9-]*'));
Here for "about-us", 'contact-us' and 3rd and main one is ":slug" ( dynamic )
Two problems:
When I try to change language, url is showing lang/controller/action ( abc.com/eng/homes/about_us ) instead of abc.com/eng/about-us.html or abc.com/chi/about-us.html
for other dynamic url eg. abc.com/page-1.html, abc.com/page-2.html, abc.com/page-3.html so on... how to use abc.com/lang/slug with .html ( abc.com/eng/page-1.html or abc.com/chi/page-1.html)
For this I am using the
Router::connect('/:slug', array('controller' => 'homes', 'action' => 'page'), array('pass' => array('slug'), 'slug'=>'[a-zA-Z0-9-]*'))
rule.
When i try to change language, url is showing lang/controller/action ( abc.com/eng/homes/about_us )
The route definitions in the question have this first:
Router::connect(
'/:language/:controller/:action/*',
array(),
array('language' => 'eng|chi')
);
Routes are tested in the order they are declared - this route will match any url which has the language eng or chi passed to it, as all urls have a controller and an action this route will always match.
instead of abc.com/eng/about-us.html or abc.com/chi/about-us.html
If there needs to be a route match for /:lang/:slug - then there has to be a route defined matching that pattern - currently there isn't.
for other dynamic url eg abc.com/page-1.html, abc.com/page-2.html, abc.com/page-3.html so on ... how to use abc.com/lang/slug with .html ( abc.com/eng/page-1.html or abc.com/chi/page-1.html)
I don't fully understand the question but the answer is probably to ensure that all routes exist with a prefix and are defined before the routes without a prefix. e.g.:
Router::parseExtensions('html', 'rss', 'xml','json');
// Define Chinese language routes first as they have a prefix
Router::connect('/chi/', ['controller' => 'homes', 'action' => 'index'],['language' => 'chi']);
Router::connect('/chi/backend/*', ['controller' => 'users', 'action' => 'login', 'lab' => true],['language' => 'chi']);
Router::connect('/chi/about-us/*', ['controller' => 'homes', 'action' => 'about_us'],['language' => 'chi']);
Router::connect('/chi/contact/*', ['controller' => 'homes', 'action' => 'contact'],['language' => 'chi']);
Router::connect('/chi/:slug', ['controller' => 'homes', 'action' => 'page'], ['pass' => ['slug'], 'slug'=>'[a-zA-Z0-9-]*'],['language' => 'chi']);
Router::connect('/chi/:controller/:action/*',[],['language' => 'chi']);
// Define English language routes last as they don't have a prefix
Router::connect('/', ['controller' => 'homes', 'action' => 'index'],['language' => 'eng']);
Router::connect('/backend/*', ['controller' => 'users', 'action' => 'login', 'lab' => true],['language' => 'eng']);
Router::connect('/about-us/*', ['controller' => 'homes', 'action' => 'about_us'],['language' => 'eng']);
Router::connect('/contact/*', ['controller' => 'homes', 'action' => 'contact'],['language' => 'eng']);
Router::connect('/:slug', ['controller' => 'homes', 'action' => 'page'], ['pass' => ['slug'], 'slug'=>'[a-zA-Z0-9-]*'],['language' => 'eng']);
Router::connect('/:controller/:action/*',[],['language' => 'eng']);
In this way all routes can be parsed unambiguously, and generated unambiguously too - assuming language is always passed when generating a url; the persist parameter can help with that.

How can I manage two different routings for a single given user in CakePHP?

For example :
Router::connect(
'/:username',
array('controller' => 'users', 'action' => 'profile'),
array('pass' => array('username'))
);
If the username parameter is prefixed by #, then it will redirect to a method. If not, it will redirect to different method.
Note : I'm using version 2.8
This should work:
Router::connect(
'/#:username',
array('controller' => 'users', 'action' => 'action1'),
array('pass' => array('username'))
);
Router::connect(
'/:username',
array('controller' => 'users', 'action' => 'action2'),
array('pass' => array('username'))
);

CakePHP routes for index with parameter

In my cake application, I have a referral program for salespersons. For each signup the user can pass a referral id. Normally, my website has a default route which does the following:
//www.mydomain.com -> www.mydomain.com/pages/home
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Now I want to route to another controller/action like this:
//www.mydomain.com/r:1234 -> www.mydomain.com/users/signup/r:1234
Router::connectNamed(array('r'));
Router::connect('/*', array('controller' => 'users', 'action' => 'signup'));
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
The routing for the signup works fine now, but the default route doesn't work anymore. I think the order is ok. Any ideas?
If i understood your issue than It should be look like this:
//www.mydomain.com/r:1234 -> www.mydomain.com/users/signup/r:1234
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/signup', array('controller' => 'users', 'action' => 'signup'));
Try this one.
Thanks

CakePHP: redirect via Router::redirect does not preserve params

I am trying to redirect /my-old-url/$slug to /news/$slug in CakePHP with the following code:
Router::redirect(
'/my-old-url/*',
array('controller' => 'news', 'action' => 'view'),
array('persist' => true)
);
Using this code throws an error (may be a bug?)
Warning (2): Invalid argument supplied for foreach() [CORE/Cake/Routing/Route/CakeRoute.php, line 381]
public function persistParams($url, $params) {
foreach ($this->options['persist'] as $persistKey) {
Even trying the following code does not work:
Router::redirect(
'/my-old-url/:slug',
array('controller' => 'news', 'action' => 'view'),
array('persist' => array('slug'))
);
This code redirects my to /news/view without any parameters.
I use the following code to connect the news URLs:
Router::connect('/news',
array('controller' => 'news', 'action' => 'index')
);
Router::connect('/news/:slug',
array('controller' => 'news', 'action' => 'view'),
array('pass' => array('slug'))
);
What to do?
Have you properly setup your routing for the new url?
Router::connect(
'/news/:slug',
array('controller' => 'news', 'action' => 'view'),
array('pass' => array('slug'), 'slug' => '[\w]')
);
Then have it do the redirect with
Router::redirect(
'/old-url/:slug',
array('controller' => 'news', 'action' => 'view'),
array('persistent' => true, 'pass' => array('slug'))
);
I don't believe you need to define slug again ([\w]) in the redirect but if it doesn't work then try it ('slug' => '[\w]' after 'pass').
Obviously you need to test if /news/test works as expected with the routing before trying the redirect.
Try following code
Router::connect('/my-old-url/*', array('controller' => 'News','action' => 'view'),array('params' => '[a-zA-Z0-9]+'));
There probably was a bug in CakePHP. Upgrading to the latest version (currently v2.3.9) did the trick. The code in my question does work.

CakePHP reverse routing: Html link not showing correct link

Firstly, I understand there have been many questions and solutions about this but none I've found fix my issue.
In summary, the Html helper is not reverse routing correctly and instead of URLs like this:
http://website.com/user_of_website/slug_name
I get URLs like this:
http://website.com/things/view/username:user_of_website/slug:a_thing
Here is my router setup:
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
/**
* ...and connect the rest of 'Pages' controller's urls.
*/
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
//User routes
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout', array('controller' => 'users', 'action' => 'logout'));
Router::connect('/register', array('controller' => 'users', 'action' => 'add'));
Router::connect('/users/:action/*', array('controller' => 'users'));
Router::connect('/things/:action/*', array('controller' => 'things'));
Router::connect(
'/:username/:slug',
array(
'controller' => 'things',
'action' => 'view'
),array(
'username' => '[a-zA-Z0-9_]+',
'slug' => '[a-zA-Z0-9_]+',
'pass'=>array(
'username',
'slug'
)
)
);
Router::connect('/:userName', array('controller' => 'things', 'action' => 'user'),array('pass'=>array('userName')));
And my Html helper:
echo $this->Html->link('View', array(
'controller' => 'things',
'action' => 'view',
'username' => 'user_of_website',
'slug' => 'a_thing'
),array(
'class' => 'text-warning'
));
I really can't see what I'm doing wrong. Any help greatly appreciated.
NB, I'm using CakePHP 2.3
Have you tried if it works if you disable the 'regular' routes for things? E.g. /things/:action/*.
My guess is that, because of the wildcard, this route will match the URL as well, and, because it is defined before your custom route, will be matched in stead.
If that resolves the problem, you may try to move that route below your 'custom' route

Resources