CakePHP 2.x Custom Route with Arguments - cakephp

In my CakePHP App I'd like to pass arguments in a custom route.
What works now
(domain/controller/action/param)
domain.com/dealers/view/1
What I'd like to do
(domain/param/controller/action/param)
domain.com/washington/dealers/view/1
This is my code in routes.php:
Router::connect('/:city/dealers/view/:id', array('controller' => 'dealers', 'action' => 'view'),
array(
'pass' => array('city', 'id')
),
array('city' => '[a-z]+')
);
This just redirects domain.com/washington/dealers/view/1 to domain.com/dealers/index for the obvious reason that I did not properly pass the parameters. Does anyone know what I am missing?

city should not be in a separate array ex:
Router::connect(
'/:city/dealers/view/:id',
array('controller' => 'dealers', 'action' => 'index'),
array(
'pass' => array('city', 'id'),
'city' => '[a-z]+'
));

Related

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: 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

In url routing named parameters are not found

I have a about us page url like below:
base_url/cmsPages/index/cmsid:1
And in routes.php i have defined
Router::connect(
'/about_us',
array('controller' => 'cmsPages', 'action' => 'index', 'cmsid' => 1),
);
But i am not getting cmsid in $this->request->params['named']['cmsid'] at index action.
Please help, how can i achieve this.
You can use following:
public function index($cmsid = null) {
// some code here...
}
// routes.php
Router::connect(
'/about_us',
array('controller' => 'cmsPages', 'action' => 'index'),
array('pass'=>array('cmsid'=>1))
);
for detailed information please visit following link :
http://book.cakephp.org/2.0/en/development/routing.html#passing-parameters-to-action
Try this code for getting named parameter
Router::connectNamed(array('id'));
Router::connect('/about-us:id', array(
'plugin' => false
'controller' => 'cmsPages',
'action' => 'index'
),array(
"pass"=>array("id")
),array(
'id' => '[0-9]+'
)
);
If you are using named parameters, you can define this route
Router::connect(
'/about_us',
array('controller' => 'cmsPages', 'action' => 'index'),
array('cmsid'=>1)
);

CakePHP 2.x Custom Route Pagination

I have a the following custom route (which works fine):
Router::connect('/:city', array('controller' => 'dealers', 'action' => 'index'), array('city' => '[a-z]+'));
With this route, I am trying to get paginated pages 2, 3, …:
Router::connect('/:city/:id', array('controller' => 'dealers', 'action' => 'index'),
array(
'pass' => array('city', 'id'),
'city' => '[a-z]+',
'id' => '[0-9]+'
)
);
The first problem now is, that if I enter domain.com/washington/2 it doesn't pass the id to Pagination and I still get page 1.
The second problem is that I do not get the Pagination Helper to write the above link. If I try this in my view:
$this->Paginator->options(array
('url'=> array(
$city[0]['City']['url'],
$this->params['id']
)
)
);
It still gives me:
http://domain.com/dealers/index/washington/page:2
I apologize in advance if this is a no brainer, but I am new to this and couldn't figure it out with the available questions/answers here, or the docs.
UPDATE 1:
I now tried the following for domain.com/washington/page/2 , but it just routes to pagination page 1:
Router::connect('/:city/:slug/:id',
array('controller' => 'dealers', 'action' => 'index'),
array(
'pass' => array('city', 'slug', 'id'),
'city' => '[a-z]+',
'slug' => '[a-z]+',
'id' => '[0-9]+'
)
);
In the action I am doing this:
public function index($slug = null, $id = null) {some code}
In the view I added:
$this->Paginator->options(array('url' => $this->passedArgs));
Still no luck, I'd be very very glad if someone could help out!
I finally got the url domain.com/washington/page/2 to work by adding this to AppController (beforeFilter):
if (isset($this->request->params['page'])) {
$this->request->params['named']['page'] = $this->request->params['page'];
}
And by adding this route:
Router::connect('/:city/page/:page',
array('controller' => 'dealers', 'action' => 'index'),
array(
'pass' => array('city', 'page'),
'city' => '[a-z]+',
'page' => '[0-9]+'
)
);
However I do not really understand what happens here, and if this is a good way of doing it. If someone could briefly explain, I'd be interested to know.
See my comment above :)
Also, you may be wanting to use this:
$this->Paginator->options(array('url' => $this->passedArgs));
This will essentially pass the arguments from the URL to the paginator helper.

Resources