CakePHP routing same action, different route for different params - cakephp

I want to connect the following routes:
register/about_you
my_profile/edit/about_you
...to the same action. But I want the second route to bring in a parameter that I can use to identify that we are on the edit page, not registration.
I currently have in my routes.php:
Router::connect('/register/:action/*',
array(
'controller' => 'registration'
)
);
Router::connect('/my_profile/edit/:action/*',
array(
'controller' => 'registration',
'edit' => 1
)
);
This works to connect the URLs above to the correct place - and I can use $this->params['edit'] in the controller. However, when I try to build a link, using
Router::url(array('controller' => 'registration', 'action' => 'about_you', 'edit' => 1, $i));
I get
/register/about_you/0/edit:1
Instead of
/my_profile/edit/about_you
What am I doing wrong?

Did you try interchanging it like this?
Router::connect('/my_profile/edit/:action/*',
array(
'controller' => 'registration',
'edit' => 1
)
);
Router::connect('/register/:action/*',
array(
'controller' => 'registration'
)
);
If it is like this, you'll get /my_profile/edit/about_you/0

Related

CakePHP: storing origin URL when redirecting to login page using Permit class

In Config/Permit.php we define rules, which actions are permitted without login. It looks like that:
Permit::access(
array(
'controller' => array('incentives'), 'action' => array('downloadvoucher')
),
array(),
array()
);
(...)
Permit::access(
array('controller' => $controllers),
array('auth' => true),
array('redirect' => array('controller' => 'users', 'action' => 'login'), 'message' => __('Your session has ended. Please log in again.'))
);
The redirect is defined at the bottom. What would be the right approach to achieve the following: if the user calls an URL (note: by default in the following format: base/controller/action/?q=1&q=2#hash or with routing) he will be redirected to the users/login page, but we would like to store somewhere from where he is coming (for example appended to the URL).
I tried this:
array('redirect' => array('controller' => 'users', 'action' => 'login', '?' => $this->here()), 'message' => __('Your session has ended. Please log in again.'))
but of course it doesn't work - the here()method is not defined in the Permit class.
Any better ideas?

CakePHP - How to make routes with custom parameters?

My Cake URL is like this:
$token = '9KJHF8k104ZX43';
$url = array(
'controller' => 'users',
'action' => 'password_reset',
'prefix' => 'admin',
'admin' => true,
$token
)
I would like this to route to a prettier URL like:
/admin/password-reset/9KJHF8k104ZX43
However, I would like the token at the end to be optional, so that in the event that someone doesn't provide a token it is still routed to:
/admin/password-reset
So that I can catch this case and redirect to another page or display a message.
I've read the book on routing a lot and I still don't feel like it explains the complex cases properly in a way that I fully understand, so I don't really know where to go with this. Something like:
Router::connect('/admin/password-reset/:token', array('controller' => 'users', 'action' => 'password_reset', 'prefix' => 'admin', 'admin' => true));
I don't really know how to optionally catch the token and pass it to the URL.
You'll want to use named parameters. For an example from one of my projects
Router::connect('/:type/:slug',
array('controller' => 'catalogs', 'action' => 'view'),
array(
'type' => '(type|compare)', // regex to match correct tokens
'slug' => '[a-z0-9-]+', // regex again to ensure a valid slug or 404
'pass' => array(
'slug', // I just want to pass through slug to my controller
)
));
Then, in my view I can make a link which will pass the slug through.
echo $this->Html->link('My Link', array('controller' => 'catalogs', 'action' => 'view', 'type' => $catalog['CatalogType']['slug'], 'slug' => $catalog['Catalog']['slug']));
My controller action looks like this,
public function view($slug) {
// etc
}

Routing with named parameters

I have a URL that contains named parameters, which I want to map to a more user friendly URL.
Take, for example, the following URL:
/videos/index/sort:published/direction:desc
I want to map this to a more friendly URL, like:
/videos/recent
I have tried setting it up in the Router, but it doesn't work.
Code samples from the Router:
Router::connect(
'/videos/recent/*',
array('controller' => 'videos', 'action' => 'index'),
array('sort' => 'published', 'direction' => 'desc'
));
Which doesn't work. And the following also doesn't work:
Router::connect(
'/videos/recent/*',
array('controller' => 'videos', 'action' => 'index', 'sort' => 'published', 'direction' => 'desc'));
Any ideas?
Use get args
The easiest way to have routes work is to avoid named arguments all together. With pagination thats easy to achieve using appropriate config:
class FoosController extends AppController {
public $components = array(
'Paginator' => array(
'paramType' => 'querystring'
)
);
}
In this way when you load /videos/recent you should find it includes urls of the form:
/videos/recent?page=2
/videos/recent?page=3
Instead of (due to route mismatching)
/videos/index/sort:published/direction:desc/page:2
/videos/index/sort:published/direction:desc/page:3
But if you really want to use named args
You'll need to update your route definition - there's no page in the route config:
Router::connect(
'/videos/recent/*',
array(
'controller' => 'videos',
'action' => 'index',
'sort' => 'published',
'direction' => 'desc'
)
);
As such, if there is a page named parameter (which there will be for all urls generated by the paginator helper), the route won't match. You should be able to fix that by adding page to the route definition:
Router::connect(
'/videos/recent/*',
array(
'controller' => 'videos',
'action' => 'index',
'sort' => 'published',
'direction' => 'desc',
'page' => 1
)
);
Though even if it works, you may find it to be fragile.
lets see on [Router::connect documentation](Routes are a way of connecting request urls to objects in your application)
Routes are a way of connecting request urls to objects in your application
So, it's map urls to objects and not url to url.
You have 2 options:
use Router::redirect
Something like that:
Router::redirect( '/videos/recent/*', '/videos/index/sort:published/direction:desc');
but seems that's not that you want exactly
use Router::connect
use normal Router::connect which will connect url to some action which make appropriate scope. Something like that:
Router::connect(
'/videos/recent/*',
array(
'controller' => 'videos',
'action' => 'recent'
)
);
and in VideosController
public function recent() {
$this->request->named['sort'] = 'published';
$this->request->named['direction'] = 'desc';
$this->index();
}
it works and I saw such usage, but not sure, that is will satisfy you too.
as for me, I like normal named cakephp parameters. If such scope (published and desc) is your default state, just code default state in index action. For over cases i think it's normal to use ordinary named parameters.

cakephp named parameters break REST based web service

I have a json REST based in the form of:
Router::mapResources('Test');
Which is equivalent to for the index method to:
Router::connect( '/Test',
array(
'controller' => 'ChannelSources',
'action' => 'index',
'[method]' => 'GET' ),
array();
I am trying to add support for named parameters this method.
but apparently its breaks the Router method as an index action is not part of the URL
i have tried using
Router::connectNamed(array('somenameparam'));
But it failed.
I would create a specific route so that you can pass in the right parameters, then you can pass your params into the route.
Have a look at, http://book.cakephp.org/2.0/en/development/routing.html#passing-parameters-to-action
Router::connect(
'/blog/:id-:slug', // E.g. /blog/3-CakePHP_Rocks
array('controller' => 'blog', 'action' => 'view'),
array(
// order matters since this will simply map ":id" to $articleId in your action
'pass' => array('id', 'slug'),
'id' => '[0-9]+'
)
);

CakePHP: pagination and custom routes

I don't seem to be able to use a custom route with pagination. The URL of the blog should be http://www.domain.com/en/page:2. However, the links generated by the PaginateHelper (prev and next), keep adding the controller and action, so that the URL looks like http://www.domain.com/posts/index/en/page:2.
The route config is quite simple:
Router::connect(
'/:lang/*',
array(
'controller' => 'posts',
'action' => 'index'
),
array(
'lang' => '[a-z]{2}',
'pass' => array(
'lang'
)
)
);
I set this in the view:
$paginator->options(
array(
'url' => $this->passedArgs
)
);
and also to set the path manually not using an array
this happens with Cake 1.33
Any help would be greatly appreciated!
It seems prev and next method of Paginator helper doesn't use default options. That's why
$paginator->options(
array(
'url' => $this->passedArgs
)
);
doesn't work. You can set it on prev and next method directly. For example:
$paginator->prev('<< Previous', array('url' => $this->passedArgs));
Hope that help.

Resources