Kohana 3.2: Route the control to another path than default - php

I have tried the following way
Route::set('sections', '<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(admin|affiliate)'
))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
Instead of Home controller in Campaign folder I need to load Home Controller from Campaign/City folder by default. I have used the above code in bootstrap.php, but it gives 'URL not found on this server' error

The array that is passed as the third parameter to Route::set() restricts the values that can be passed to the route. In your code array('directory' => '(admin|affiliate)') restricts the directory parameter to be either 'admin' or 'affiliate' To have it go deeper you would need to modify the route.
The Kohana Routing Guide has a bunch of examples using filters to route in any way you could possibly imagine, but you could route to subdirectories without turning to filters.
For example, with the following directory structure:
classes/Controller/
Admin/
Cupertino/
Home.php (Controller_Admin_Cupertino_Home)
Home.php (Controller_Admin_Home)
Affiliate/
Cupertino/
Home.php (Controller_Affiliate_Cupertino_Home)
Home.php (Controller_Affiliate_Home)
And the following route:
Route::set('sections', '<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(admin/cupertino|admin|affiliate/cupertino|affiliate)'
))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
The URLs index.php/admin, index.php/admin/cupertino, index.php/affiliate, and index.php/affiliate/cupertino will route through their respective controllers.
Subdirectories need to be listed before their parents otherwise Kohana will always match to the parent. e.g. the following will always route to Controller_Admin_Home even for the URL index.php/admin/cupertino:
`array('directory' => 'admin|admin/cupertino')`.
Using filters might look something like the following:
Route::set('admin_subsections', 'admin/<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(cupertino|sanjose|santacruz)'
))
->filter(function($route, $params, $request)
{
// append "admin/" to the directory param
$params['directory'] = 'admin/' . $params['directory'];
return $params; // Returning an array will replace the parameters
})
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
Route::set('sections', '<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(admin)'
))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
And again, order matters.

Related

kohana 3.2.3.1 route not working when controller is in a sub folder

I've just been given a project for a CRM called Kohana, which i've never heard of until now.
Everthing works ok except for controllers that are in a sub folder and when the controller name isn't just a single word.
This controller is in system/expenses.php
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_System_Expenses extends Controller_System {
public $header = 'Expenses';
public function action_index() {
$this->template->content = view::factory('system/expenses/listings');
$this->template->content->expenses = expenses::get_all();
}
public function action_update() {
$expenses = expenses::find_by_id(form::get_value('id'));
expenses::update($expenses, form::data());
$this->redirect(request::current()->referrer());
}
}
When i try to access /system/expenses it gives a 404. If i then move the controller to the base controller folder it still doesn't work unless i rename the class to Controller_Expenses instead of Controller_System_Expenses which then works on the route /expenses
Here is the bootstrap.php file:
Route::set('automate', 'hourly')
->defaults(array('controller' => 'cron',
'action' => 'hourly'
));
Route::set('daily', 'daily')
->defaults(array('controller' => 'cron',
'action' => 'daily'
));
Route::set('auth', '<action>',
array(
'action' => '(login|logout)'
))
->defaults(array(
'controller' => 'auth',
'action' => 'login',
));
Route::set('super', 'system/(<controller>(/<action>(/<id>)))')
->defaults(array(
'directory' => 'system',
'controller' => 'settings',
'action' => 'index',
));
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'Dashboard',
'action' => 'index',
));
It doesn't matter if i add a route in here specifically for the url, if i remove the "super" route, nothing works in the sub folder, even if i rename the controller to Controller_Expenses inside the "system" controller folder the route i had working of just /expenses still doesn't work.
I'm at a loss of how this is supposed to work.
case sensitive directory/class name:
'directory' => 'System',
'controller' => 'Settings',
trailing slash:
'system(/<controller>(/<action>(/<id>)))'
defaults for optional parameters:
'id' => 0,

kohana 3.0 directory to controller

I have my website under Kohana 3.0 which works perfectly with the defaut Route
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'user',
'action' => 'index',
));
When I try to access my website at this address http://127.0.0.1/web/ It loads the url http://127.0.0.1/web/user . It is OK.
But now I want to add the admin directory under the controller. So my web tree looks like this
classes
| controller/
Admin/
dashboard
web.php
| model
I would like to allow the Admin to access the admin's page in a url like this
http://127.0.0.1/admin/dashboard. Where dashboard is the controller under the admin's directory.
I modify the bootstrap file with this
Route::set('admin', '<directory>(/<controller>(/<action>(/<id>)))',
array('directory' => '(admin)'))->defaults(array(
'controller' => 'user',
'action' => 'index',
));
I can access the admin session through http://127.0.0.1/web/admin/dashboard/
But I can't access the default controller that is http://127.0.0.1/web/ . The error Kohana_Request_Exception [ 0 ]: Unable to find a route to match the URI:
I am missing the default access for the controller.
How can I set Route it to make access to my web site either through the link:
http://127.0.0.1/web/
and
http://127.0.0.1/web/admin/dashboard/
EDIT
From the kohana documentation, it is written
In this example, we have controllers in two directories, admin and affiliate. Because this route will only match urls that begin with admin or affiliate, the default route would still work for controllers in classes/controller.
Route::set('sections', '<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(admin|affiliate)'
))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
Source : http://kohanaframework.org/3.0/guide/kohana/routing#examples
Now I modify my code to
Route::set('default', '<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(admin)'))
->defaults(array(
'controller' => 'user',
'action' => 'index',
));
but I have this error
Kohana_Request_Exception [ 0 ]: Unable to find a route to match the URI:
when I want to access the default controller like http://127.0.0.1/user/index
This route would translate to: http://127.0.0.1/admin/web, but your Admin folder would need to have user controller inside.
Route::set('default', '<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(admin)'))
->defaults(array(
'controller' => 'user',
'action' => 'index',
));
If you want the directory to be optional, you'd need to
Route::set('default', '(<directory>(/<controller>(/<action>(/<id>))))',
array(
'directory' => '(admin)'
)
)
->defaults(array(
'directory' => 'admin',
'controller' => 'dashboard',
'action' => 'index',
));
But, in your case, you need multiple routes. Above the "catch all" route, put this:
Route::set('user', 'user(/<controller>(/<action>(/<id>)))')
->defaults(array(
'directory' => 'user',
'controller' => 'user',
'action' => 'index',
));
Route::set('admin', 'admin(/<controller>(/<action>(/<id>)))')
->defaults(array(
'directory' => 'admin',
'controller' => 'dashboard',
'action' => 'index',
));
Route::set('default', '(/<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'index',
'action' => 'index',
));
Try to insert the directory inside ->defaults
Route::set('whatever', 'whatever')
->defaults(array(
'directory' => 'admin',
'controller' => 'user',
'action' => 'index',
));

CakePHP route with regex

I have a controller setup to accept two vars: /clients/view/var1/var2
And I want to show it as /var1/var2
SO i tried
Router::connect('/*', array('admin'=>false, 'controller' => 'clients', 'action' => 'view'));
But this stops all other controllers working as /* routes everything
All other pages that are on the site are within the admin prefix so basically i need a route that is ignored if the current prefix is admin! I tried this (regex is from Regular expression to match a line that doesn't contain a word?):
Router::connect('/:one', array('admin'=>false, 'controller' => 'clients', 'action' => 'view'), array(
'one' => '^((?!admin).*)$'
));
But I think the regex is incorrect because if i naviate to /test it asks for the tests controller, not clients
My only other routes are:
Router::connect('/admin', array('admin'=>true, 'controller' => 'clients', 'action' => 'index'));
Router::connect('/', array('admin'=>false, 'controller' => 'users', 'action' => 'login'));
What am I doing wrong? Thanks.
I misunderstood your question the first time. I tested your code and didn't get the expected result either. The reason might be that the regex parser doesn't support negative lookahead assertion. But I still think you can solve this with reordering the routes:
The CakeBook describes which routes are automatically generated if you use prefix routing. In your case these routes have to be assigned manually before the '/*'-route to catch all admin actions. Here is the code that worked for me:
// the previously defined routes
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/admin', array('controller' => 'clients', 'action' => 'index', 'admin' => true));
// prefix routing default routes with admin prefix
Router::connect("/admin/:controller", array('action' => 'index', 'prefix' => 'admin', 'admin' => true));
Router::connect("/admin/:controller/:action/*", array('prefix' => 'admin', 'admin' => true));
// the 'handle all the rest' route, without regex
Router::connect(
'/*',
array('admin'=>false, 'controller' => 'clients', 'action' => 'view'),
array()
);
Now I get all my admin controller actions with the admin prefix and /test1/test2 gets redirected to the client controller.
I think the solution is described in the bakery article on routing - "Passing parameters to the action" (code not tested):
Router::connect(
'/clients/view/:var1/:var2/*',
array(
'controller' => 'clients',
'action' => 'view'
),
array(
'pass' => array(
'var1',
'var2'
)
)
);
The controller action would look like:
public function view($var1 = null, $var2 = null) {
// do controller stuff
}
Also you have too look at the order of your routes (read section "The order of the routes matters"). In your example the '/*' stops all other routes if it comes first, if you assign the rule after the others it handles only requests which didn't match any other route.

How to route domain.com/locale/controller to domain.com/controller in Kohana?

I'm trying to implement localization in my website. Currently, the basic (English) website is at http://domain.com/controller/action and I want each localization to be at http://domain.com/locale/controller/action. Basically, if a user visit the latter URL, Kohana will use the same controller and action than for the English version. In code, I will simply swap the strings.
Currently, I tried by adding the following route but that didn't work:
// This is my default route:
Route::set('default', '(<controller>(/<action>(/<overflow>)))', array('overflow' => '.*?'))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
// This the route for the localizations:
Route::set('locale', '(<locale>(/<controller>(/<action>(/<overflow>))))', array('overflow' => '.*?'))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
With this setup, if I visit http://domain.com/es/controller/action, I will get a 404 error. Any idea how I should setup my routes to make this work?
Edit:
Just to complete matino and John Himmelman's answer, if I simply swap the rules as suggested, it will work. However, the "locale" route would then become the catch-all route and you will always have to specify the locale, even if all you need is the default one (in my case "en" / English). To fix that, you can limit the "locale" parameter to the locales you support. For example:
Route::set('locale', '(<locale>(/<controller>(/<action>(/<overflow>))))', array('locale' => '(fr|zh|en)', 'overflow' => '.*?'))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
Route::set('default', '(<controller>(/<action>(/<overflow>)))', array('overflow' => '.*?'))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
In that case, only URLs that start with "fr", "zh" or "en" will be supported. Additionally, unsupported locales will return a 404 errors, and "domain.com/controller/action" will correctly display the default, English locale.
Kohana applies routes in the order they appear in your bootstrap. This is why your default/catch-all route should always be defined last.
From KO 3.0 routing doc:
It is important to understand that routes are matched in the order
they are added, and as soon as a URL matches a route, routing is
essentially "stopped" and the remaining routes are never tried.
Because the default route matches almost anything, including an empty
url, new routes must be place before it.
As suggested, swapping routes will resolve the issue.
// This the route for the localizations:
Route::set('locale', '(<locale>(/<controller>(/<action>(/<overflow>))))', array('overflow' => '.*?'))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
// This is my default route:
Route::set('default', '(<controller>(/<action>(/<overflow>)))', array('overflow' => '.*?'))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));

Kohana 3: Routing with subdirectories error, controller does not exist

So I'm trying to build a route with sub directories and following the Kerkness wiki guide but keep getting errors. If someone could point out what I'm doing wrong I would greatly appreciate it.
http://kerkness.ca/wiki/doku.php?id=routing:building_routes_with_subdirectories
The code:
Route::set('default', '(<directory>(/<controller>(/<action>(/<id>))))', array('directory' => '.+?'))
->defaults(array(
'directory' => 'admin',
'controller' => 'main',
'action' => 'index',
));
The url:
/admin/weather/feedback
The file:
/application/classes/controller/admin/weather/feedback.php
class Controller_Admin_Weather extends Controller_Admin_Base {
The error:
ReflectionException [ -1 ]: Class controller_admin_weather does not exist
Weather needs to be the controller not feedback. Make a weather.php in the admin folder and put the controller as Controller_Admin_Weather and then the action action_feedback.
As #mikelbring said, your controller class is named wrongly. A class in that file should be called Controller_Admin_Weather_Feedback
Do you really need so many optional segments in your route?
Also; if there are no variable elements to the urls you can just stick with defaults like this:
Route::set('my_route_name', 'admin/weather/feedback')
->defaults(array(
'directory' => 'admin/weather',
'controller' => 'feedback',
'action' => 'index',
));
If your class was in /application/classes/controller/admin/weather.php and had an action_feedback(...) method, you could use the following route
Route::set('my_route_name', 'admin/weather/feedback')
->defaults(array(
'directory' => 'admin',
'controller' => 'weather',
'action' => 'feedback',
));

Categories