How to route subcategories and pages in categories? - cakephp

My subcategories and pages in categories have similar structure. For example:
site.com/cat/page
site.com/cat/subcat
How can I route them? URLs consist only of strings, no IDs and any numbers.

Pretty straightforward, your routes.php could look like:
$routes->connect(
'/cat/:page',
['controller' => 'Pages', 'action' => 'view'],
['page' => '\s+', 'pass' => ['page']]
);
$routes->connect(
'/cat/:subcat/:page',
['controller' => 'Pages', 'action' => 'subcatView'],
['subcat' => '\s+', 'page' => '\s+', 'pass' => ['subcat', 'page']]
);
Next, in your PagesController.php (actually you can use any other your controller/action, just substitute your names in routes above):
public function view($page) {
//i.e. if url is /cat/about then $page === 'about'
}
public function subcatView($subcat, $page) {
// i.e. if url is /cat/subcat/some_page then $subcat === 'subcat' & $page === 'some_page'
}
I highly recommend to refer cakephp3 documentation, routes section, it's clear enough to help you implement any magic.

Related

SEO Friendly URL in CakePHP pagination

I'm using CakePHP v2.42 & would like to have SEO friendly URL in page pagination.
My current pagination is like
http://www.website.com/ubs/page/page:2
What to do to change to
http://www.website.com/ubs/page/2
My Controller is
<?php
class UbsController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
$this->paginate = array(
'limit' => 100,
);
$ubs = $this->paginate();
$this->set('ubs', $ubs);
}}
My Router is
Router::connect('/ubs', array('controller' => 'ubs', 'action' => 'index'));
Router::connect('/ubs/page/*', array('controller' => 'ubs', 'action' => 'index'));
EDIT - ADD MORE QUESTION
Answer by #kicaj is perfectly correct for the Router & Controller. However, the navigation link only display correctly on the first page.
In the first page navigation link show like this which is correct
http://www.website.com/ubs/
http://www.website.com/ubs/page/2/
http://www.website.com/ubs/page/3/
But navigation link show like this in second/third page page
http://www.website.com/ubs/index/2/
http://www.website.com/ubs/index/2/page:3/
I guess need to edit index.ctp file but not sure what to do.
My current navigation link in index.ctp show like this
$paginator = $this->Paginator;
$paginator->prev("« Prev");
$paginator->numbers(array('modulus' => 200, 'separator' => ' '));
$paginator->next("Next »");
What to change to correct this
Try this:
Router::connect('/ubs/page/:page', array(
'controller' => 'ubs',
'action' => 'index'
), array(
'pass' => array(
'page'
),
'page' => '[\d]+'
));
and in index action in ubs controller add code bellow:
public function index($page = 1) {
// ...
$this->request->params['named']['page'] = $page;
// ...
}
In your Paginator Helper you can choose the right friendly url you want with setting some options
url The URL of the paginating action. ‘url’ has a few sub options as well:
sort The key that the records are sorted by.
direction The direction of the sorting. Defaults to ‘ASC’.
page The page number to display.
There here an example .
$this->Paginator->options(array(
'url' => array(
'sort' => 'email', 'direction' => 'desc', 'page' => 6,
'lang' => 'en'
)
));
the source : Modifying the options PaginatorHelper uses

How to maintain a variable in the url which is customized in cakephp?

What im trying to do here is maintain the variable 42 all throughout all pagination urls. I want my url to change from this
/exams/take/42/page:2
to this
/exams/take/42/items/2
Again,the number 42 is the variable..and the number 2 is the page number..Thanks.
UPDATE :
routes.php
Router::connect('/examinations/take/:id/page/:page',
array('controller' => 'examinations', 'action' => 'take'),
array(
'pass' => array('id', 'page'),
'id' => '[0-9]+',
'page' => '[0-9]+'
)
);
in the view/take
$this->Paginator->options(array('url' => $this->passedArgs));
AppController.php
public function beforeFilter(){
if (isset($this->request->params['page'])) {
$this->request->params['named']['page'] = $this->request->params['page'];
}
}
ive tried this ..but the generated url is the same,/examinations/take/42/page:2 ,when i click the next and prev links..
You've to define custom routes:
http://book.cakephp.org/2.0/en/development/routing.html
Example as below:
Router::connect(
'/exams/take/:id/items/:number',
array('controller' => 'exams', 'action' => 'take'),
array('pass' => array('id', 'number'))
);
Also you can get more information from below url try this:
http://www.sakic.net/blog/changing-cakephp-pagination-urls
yes you can do it with the use of custom routing. for more undrestanding you can see cakephp manual to manage custom routing in pagination
http://book.cakephp.org/2.0/en/development/routing.html
below will be your
e.g.
And by adding this route:
Router::connect('/:id/page/:page',
array('controller' => 'examinations', 'action' => 'take'),
array(
'pass' => array('id', 'page'),
'id' => '[0-9]+',
'page' => '[0-9]+'
)
);
and i does not work you can refer link

Retaining parent slugs in CakePHP

I'm experimenting with SEO friendly URL's in CakePHP as efficiently as I can, I've managed to use the current format, each example uses function view($slug) except for the first example which uses function index().
/categories/
/categories/books/
/categories/books/it-and-computing/
But what if IT & Computing has a sub-category "Web Development"? I'd like the URL to become:
/categories/books/it-and-computing/web-development/
I'm not sure how to do this without creating too many routes. Here is my route code so far:
Router::connect('/categories/', array('controller' => 'categories', 'action' => 'index'));
Router::connect('/categories/:slug',
array('controller' => 'categories', 'action' => 'view'),
array('pass' => array('slug'))
);
Router::connect('/categories/:parent/:slug',
array('controller' => 'categories', 'action' => 'view'),
array('pass' => array('parent', 'slug'))
);
Any help would be greatly appreciated
Kind Regards
Stephen
// in routes.php
Router::connect('/categories/:row:lastslash',array('controller' => 'settings', 'action' => 'show',),array(
'pass'=>array('row'),
'row'=>'.*?',
'lastslash'=>'\/?'
));
//in controller
function show($row = ""){
if($row){
$categories = split('/',$row);
?><pre><? print_r($categories);?></pre><?die();
}else{
die('do something else');
}
}
/categories/books/computing/web-development/cakephp/
result:
Array
(
[0] => books
[1] => computing
[2] => web-development
[3] => cakephp
)
/categories/
result:
do something else
/categories/books
result:
Array
(
[0] => books
)

CakePHP - how to translate current URL after changing language and reloading Routing table

I'm using different routing tables for every language, and I have wrote action which change language and redirects to the same page but in target language (and target url).
The main problem is that my action is way too complicated - how can I make it simple?
It should change language and redirect to new url (in target language).
In short: We had random valid cake url in one language and we had to translate it to adequate url in another language.
My routing table:
if( 'en' == Configure::read('Config.language') ) {
Router::connect('/help', array('controller' => 'pages', 'action' => 'display', 'help') );
} else {
Router::connect('/pomoc', array('controller' => 'pages', 'action' => 'display', 'help') );
}
Action changing language:
function lang($lang) {
// getting previous url table
$url = $this->referer();
$url = Router::parse($url);
// changing language
if( in_array($lang, Configure::read('Languages.valid') ) ) {
$this->Session->write('Language', $lang);
Configure::write('Config.language', $lang);
}
// saving base params
$requestInfo = array(Router::getParams(), Router::getPaths());
// reload routing table
Router::reload();
include(CONFIGS.'routes.php');
// restore base params
Router::setRequestInfo($requestInfo);
// fix for 'pass' params
if(!empty($url['pass']) && is_array($url['pass'])) {
$url = array_merge($url, $url['pass']);
unset($url['pass']);
}
$this->redirect($url);
}
About 'pass' key in url table:
/pages/display/help
after Router::parse(), parameter is extracted:
pass => array(
0 => 'help'
)
and later return value from Router::url() look like that:
/pages/display/pass:Array
so I have to fix it by merging 'pass' value with whole array and removing key
I have my routes.php like this
Configure::write('Config.language', $_SESSION['lang']);
Router::connect(__('/help',true), array('controller' => 'pages', 'action' => 'display', 'help') );
so I use the __() to translate the url. It seaches the translation in the po files. And in your lang() function, after changing the Session to the current lang, all you need to do is:
$this->redirect(__('/help'));
Hope this helps
I know it is too late to answer that, but for those who experience the similar needs:
In routes.php p1 identifies the static page (same for all languages), could be any string that uniquely identifies the page.
Router::connect('/:language/p1/:translation', array(
'controller' => 'pages',
'action' => 'display',
'help',
'options' => array('language' => '[a-zA-Z]{2}')
) );
In your view
$this->Html->link('Click me', array(
'language' => Configure::read('Config.language'),
'controller' => 'pages',
'action' => 'display',
'help',
'translation' => __('help') // could be any string in fact
));
will generate link to /en/p1/help in English, else to /xx/p1/pomoc.
Injection of language parameter into every link could be done in AppHelper::url() instead of providing it in every link occurence.
If you want to redirect in controller:
$this->redirect(array(
'language' => Configure::read('Config.language'),
'controller' => 'pages',
'action' => 'display',
'help',
'translation' => __('help')
));

Cakephp localization routes

My localization files (.po) work if I change the default language, but I can't make the routes working, here's what I've got atm:
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/login/*', array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout/*', array('controller' => 'users', 'action' => 'logout'));
Router::connect('/register/*', array('controller' => 'users', 'action' => 'register'));
Router::connect('/:lang/:controller/:action/*', array('lang' => 'en'), array('lang' => 'en|fr'));
But when I try : domain.com/fr/login, the cake is looking for the "fr" controller.
I am using this function in the AppController beforeFilter to switch between languages:
function setLanguage() {
if(!isset($this->params['lang']))
{
$this->params['lang'] = 'en';
}
$lang = $this->params['lang'];
App::import('Core', 'i18n');
$I18n =& I18n::getInstance();
$I18n->l10n->get($lang);
foreach (Configure::read('Config.languages') as $lang => $locale)
{
if($lang == $this->params['lang'])
{
$this->params['locale'] = $locale['locale'];
}
}
}
Cheers,
Nicolas.
You do not have a login controller. So your bottom route does not match and Cake then tries the default by looking for an fr controller.
Routes don't interact as you expect them to:
/login - would match your second route
/fr/users/login - would match your last route.
/fr/login - does NOT intelligently "merge" the two routes. You need to explicitly make such a route.

Resources