Hy.
I have 2 controllers, the first one application/classes/controller/welcome.php and the second one application/classes/controller/admin/welcome.php.
And I have the following routings, set in bootstrap.php
Route::set('admin', '(<directory>(/<controller>(/<action>(/<id>))))', array('directory' => '(admin)'))
->defaults(array(
'directory' => 'admin',
'controller' => 'welcome',
'action' => 'index',
));
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
If I access example.com/welcome it calls index action from the application/classes/controller/welcome.php controller (this is good),
if I access example.com/admin/welcome it calls index action from application/classes/controller/admin/welcome.php controller (this is good),
but if I access simply example.com, it calls the admin's welcome and not the other one, and I can't understand why.
I want this: if I access example.com, then call index action from application/classes/controller/admin/welcome.php controller.
How can I solve this?
It looks like you've set the directory tag in the first route to be optional, and so it's matching when no directory is specified. Try:
Route::set('admin', '<directory>(/<controller>(/<action>(/<id>)))', array('directory' => '(admin)'))
->defaults(array(
'directory' => 'admin',
'controller' => 'welcome',
'action' => 'index',
));
This should make the tag mandatory, and so it won't match on /.
The routes you specify are matched from top to bottom: the first one that matches will be used. So, swap your routes and it should work (make the 'admin' route the last one).
Related
I've looked at so many Stackoverflow questions regarding this and none of them seem to solve my problem. I just want to have a admin folder and controllers within those. Here is what my route looks so far
/*
* Set the routes. Each route must have a minimum of a name, a URI and a set of
* defaults for the URI.
*/
Route::set( 'default', '(<controller>(/<action>(/<id>)))' )
->defaults( array(
'controller' => 'dashboard',
'action' => 'index',
) );
Route::set('admin','admin(/<controller>(/<action>(/<id>)))')
->defaults(array(
'directory' => 'admin',
'controller' => 'dashboard',
'action' => 'index',
));
As Kingkero said in his comment, move the route above the default one and it will work. if you read the docs on routing properly (I know it takes a while and a few reads for it all to sink in if you're new to it all, I've been there myself) it should be clear that the default route is a catch-all, and that any specific routes you need should come first, and any catch-all type routes after, as they are tried in sequence and when a match is found no more routes are tried.
So I started making the admin panel of our site as a plugin. And I'm able to redirect every request like domain.com/admin or domain.com/admin/users or domain.com/admin/pages/edit/5 - to the appropriate controller and action from the admin plugin.
Like this one:
Router::connect('/admin', array('plugin' => 'admin', 'controller' => 'index', 'action' => 'index'));
Router::connect('/admin/users/list', array('plugin' => 'admin', 'controller' => 'users', 'action' => 'list'));
But this means I will have to write separate route for almost each URL ??? or actually - for each action ... So - is there a way to set it globally? ...
For example:
Router::connect('/admin/users/*', array('plugin' => 'admin', 'controller' => 'users'));
Or even better:
Router::connect('/admin/*', array('plugin' => 'admin'));
Cause the last two examples didn't work at all ...
EDIT: the CakePHP version is the latest at the moment - 2.4.1.
Normally you shouldn't have to create such routes for plugins, the basic mapping works out of the box, ie in case your plugin is named admin, then /admin/users/list will automatically map to plugin admin, controller users, action list.
An exception is your /admin route, by default this would look for index on AdminController. So for mapping to index on IndexController you'll need a custom route like the one in your question:
Router::connect('/admin', array('plugin' => 'admin', 'controller' => 'index', 'action' => 'index'));
Apart from this it should work as is in case you don't have any other preceding rules that will override the default behaviour, something like Router::connect('/*', ...) for example. In case there are such rules and you cannot change them, then this is how you could connect the basic routes of your plugin:
Router::connect('/admin/:controller/:action/*', array('plugin' => 'admin'));
Router::connect('/admin/:controller/*', array('plugin' => 'admin', 'action' => 'index'));
Router::connect('/admin/*', array('plugin' => 'admin', 'controller' => 'index', 'action' => 'index'));
Note that this needs to be placed before the other routes that override the default behaviour!
See also http://book.cakephp.org/2.0/en/development/routing.html
On a side note, list as an action name will probably not work, this should throw a parser error as list is a reserved keyword. So you in case this isn't just an example you'll need an extra route for that if you want to use /list as the action name in the URL.
I have set up two routes, one is the default and the other is one to enable the admin section which has controllers in a sub-directory of the controller directory. These are how they look like:
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'Home',
'action' => 'index',
));
// Admin routes
Route::set('admin', 'admin(/<controller>(/<action>(/<id>)))')
->defaults(array(
'directory' => 'Admin',
'controller' => 'Main',
'action' => 'index',
));
When I navigate to /admin/ or /admin/main I get a 404 error and I can't get it to work. I've also named the classes in the admin sub-directory as Controller_Admin_Main so that should work, right?
Please provide examples to how this should be done correctly. Thank you very much! :)
The problem got fixed by switching the position of the admin route to above the default route in the code. I guess kohana matched the first expression and tried to show a view according to the default route.
I tried this:
Route::set('default_controllers', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
Route::set('default', '<uri>')
->defaults(array(
'controller' => 'cms',
'directory' => 'cms',
'action' => 'render',
));
But actually I want the 'default' (with the render action) to come first than the default_controllers.
I want it to first check any controllers, and if there is nothing then it should run the second default, render. Render checks the uri in the database and returns the page if exists or else it throws a error.
If i switch on the two's route position, so the 'default' route come before 'default_controllers' then it works fine with the cms pages, but not with the controllers (since it does not look for further routes, after the render function has thrown an error that the page does not exists.)
What do i do here? How can i make them both work?
You basically have two catchall routes here. You should remove one of them, and make your routes more specific. The (<controller>(/<action>(/<id>))) route is actually very bad, and is only provided as an example.
To get this to work, you have to specifically tell the route which controllers to load.
Route::set('default_controllers', '(<controller>(/<action>(/<id>)))', array(
'controller' => 'controller|anotherController|etcController'
))
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
If you wanted to, you could write a class to go look for the controllers and cache the result as to not increase load times. You'd then pass this value into the value for the controller key in the array.
Your other route can remain how you had it:
Route::set('default', '<uri>')
->defaults(array(
'controller' => 'cms',
'directory' => 'cms',
'action' => 'render',
));
I have an application that is essentially working until I tried to implement an Auth module for logins and registrations.
My application directory structure is basically:
application
-- classes
-- controller
-- admin
(admin area)
-- block
(blocks to display within pages)
-- page
(default pages)
By default I want to have URL's such as http://www.testsite.com/test which would access the Controller_Page_Test class. Or to explicitly call admin or block pages http://www.testsite.com/admin/test which would access the Controller_Admin_Test class. To further complicate matters it also needs to handle optional actions and id's.
I said at the top that this is basically working correctly - until I've tried to add in the Auth module. The Auth module calls http://www.testsite.com/user/login but instead of accessing the module's path via the default, it looks in the page directory.
To overcome this I placed a higher level route but now this has become my default page handler. Explicit calls still get through.
My routes currently look like this:
Route::set('user', '(<controller>(/<action>(/<id>)))', array('controller' => 'user|admin_user'))
->defaults(array(
'controller' => 'user',
'action' => 'index',
'id' => NULL,
));
Route::set('with_dir', '<directory>/<controller>(/<action>(/<id>))', array('directory' => 'block|admin'))
->defaults(array(
'directory' => 'page',
'controller' => 'home',
'action' => 'index',
));
Route::set('just_id', '<controller>(/<id>)', array('id' => '\d+'))
->defaults(array(
'directory' => 'page',
'controller' => 'home',
'action' => 'index',
));
Route::set('auto_dir', '<controller>(/<action>(/<id>))', array('id' => '\d+'))
->defaults(array(
'directory' => 'page',
'controller' => 'home',
'action' => 'index',
));
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'prototype',
'action' => 'index',
));
Can this be cleaned up any better? And how do I get this module to only kick in when I need it to?
Yes, it can be cleaned better. Kohana developers encourage people using this framework to add as much routes as needed. You can even specify them for each action which will enable you to change URLs in the future (eg. instead of /user/login you may wish to have /signin), if you use proper methods to generate links etc. (eg. Route::url() helper).
Now, saying that, here is the other way to specify the user route:
Route::set('user', '<controller>(/<action>(/<id>))', array('controller' => '(user|admin_user)'))
->defaults(array(
'controller' => 'user',
'action' => 'index',
));
Which will match only the requests, where the first part of the URI is given and is equal either to user or admin_user. Previously the controller part was optional, thus was also matching calls to / URI.