I have a rule defined in Kohana 3 routing but the ID parameter is not being passed to the method.
I have this in the bootstrap.php file:
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
and controller
public function action_home($id=NULL)
{
echo $id;
}
But in the following link example, the ID is usually NULL:
http://example.com/index/123
The ID should be 123 but it isn't. I don't know why.
Yeah the Ko3 routes are ridiculous.
Try removing that $id=null since K03 will assign the vars as parameters:
public function action_home()
{
echo $this->request->param('id');
}
See if that helps.
They were removed from Kohana, please see: http://dev.kohanaframework.org/issues/4357
As zombor stated:
They just don't fit into how Kohana is designed. They should not have been included in 3.0 in the first place.
Also it isn't supposed to handle all routes with the default one. You should define as many as you need.
Related
In Kohana 3.2 I'm using the default route for a simple controller/action/id setup:
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'home',
'action' => 'index',
'id' => '0',
));
Per the documentation it's pretty easy to wire up controllers and actions to a simple route like this, but route parameters (in this case id) are never accessible in the controllers.
So for example I have a route:
/user/info/123
And the controller handling that route gets called successfully:
public function action_info()
{
$id = $this->request->param('id');
echo "id=" . $id; //nothing
echo "is_null=" . is_null($this->request->param('id')); //1
}
But $this->request->param('id') is always set to null.
This seems like about the simplest example I can come up with, what could I be doing wrong here?
Turns out the company I'm working with extended Kohana with a request->param() function to do something without realizing that was already a function in Kohana, and this broke the built in functionality. Using the built in Kohana request function fixes this problem.
So this turns out to be a non-question as this is the correct way to get request parameters after all. :)
Have you tried this?
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'home',
'action' => 'index',
'id' => '\d+',
));
I am using PHP 5.5 and Kohana 3.3
I am developing a website structure that always has the language preference of the user as the first "item" of a uri.
For example:
mydomain.com/en/products
mydomain.com/de/store
Now, I am sure that some users will try and be clever and type things in like:
mydomain.com/products
which is fine, I just would like them to be rerouted to
mydomain.com/en/products to keep everything consistent.
The code I have below is working as long as the uri has only one "directory" in the URI e.g.
mydomain.com/products
mydomain.com/store
but not for uris like down further subdirectories like:
mydomain.com/products/something
mydomain.com/store/purchase/info
Here are my routes:
Route::set('home_page', '(<lang>)')
->defaults(array(
'controller' => 'Index'
));
Route::set('default', '(<lang>(/<controller>(/<action>(/<subfolder>))))')
->defaults(array(
'controller' => 'Index',
'action' => 'index'
));
Here is the code in my parent controller that every other controller inherits from:
public function before()
{
$this->uri = $this->request->uri();
$this->lang = $this->request->param('lang');
//If user directly inputted url mydomain.com without language information, redirect them to language version of site
//TODO use cookie information to guess language preferences if possible
if(!isset($this->lang))
{
$this->redirect('en/', 302);
}
//If the first part of path does not match a language redirect to english version of uri
if(!in_array($this->lang, ContentManager::getSupportedLangs()))
{
$this->redirect('en/'.$this->uri, 302);
}
}
You could replace the two routes given with this one:
Route::set('default', '(<lang>/)(<controller>(/<action>(/<subfolder>)))',
array(
'lang' => '(en|fr|pl)'
))
->defaults(array(
'controller' => 'Index',
'action' => 'index'
));
where the string (en|fr|pl) is the concatenation of your supported languages, i.e. '('.implode('|', ContentManager::getSupportedLangs()).')'.
If this solution remains obscure I'm happy to explain it in more detail but I hope you can see on reflection that your problem arose because your first route, home_page, was being matched by e.g. mydomain.com/products.
Your controllers' before() function should be revised as well. The redirects won't work as things stand because you're going to end up redirecting to e.g. en/ru/Index. So why not keep it simple and use:
public function before()
{
$default_lang = 'en';
$this->lang = $this->request->param('lang', $default_lang);
}
I'm trying to make a route rule to make my request to the main page in kohana. It's sth of this kind: http://my_site/
And got into trouble here. In docs they write i can make this or that, lots of variants, but no example for mine. Simply saying if i try to do this way
Route::set('main/index', '')
->defaults(array(
'controller' => 'main',
'action' => 'index',
));
then if i write Route::get('main/index')->uri() on page http://my_site/hi i get a link to the same page. If i do it this way
Route::set('main/index', null)
->defaults(array(
'controller' => 'main',
'action' => 'index',
));
No result again, uri callback should have a valid value.
In official manual they suggest this variant
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
But i need a rule with a strict match i.e. just http://my_site/, not http://my_site/(<controller>(/<action>(/<id>)))
Is there a way to help me out from this without rewriting Route class?
Thanks in advance
Route::set('main/index', '')
->defaults(array(
'controller' => 'main',
'action' => 'index',
));
Works just for for me if I make sure that route is set before any other route that may match an empty uri. Routes are checked for a match in the order they are added.
If you want to know what if your route was matched (on a development server) you can set the default controller to a non-existing one like 'bogus'. Then Kohana wil throw a Http_Exception_404 and the exception handler will serve you an error page. (Turn on kohana errors if it does not.) On that page click on the 'arguments' link of the first trace of the stack trace. You should then see something like the following:
object Request(18) {
...snip...
protected _route => object Route(5) {
protected _callback => NULL
protected _uri => string(0) ""
protected _regex => array(0)
protected _defaults => array(1) (
"controller" => string(5) "bogus" // the non-existing bogus controller default
)
protected _route_regex => string(6) "#^$#uD"
}
...snip...
}
I got the above by placing the following route before I add any other route (which could match that uri too):
Route::set('main/index', '')
->defaults(array(
'controller' => 'bogus',
));
Also make sure no other route uses the 'main/index' name as it will overwrite the older one. Actually, I just took a look at the code of Route::uri() and guess what. Static routes (routes that have no '<' or '(' in them) should return the current url. Since an empty string is a static route the result Route::uri of that route would always be only the host. Which suggests me you are overriding the 'main/index' route assuming the uri was set to an empty string.
Also when using a NULL as the uri for a route it is assumed it came from the cache and you end up whith an empty route when it did not came from the cache.
Your Route::get('main/index')->uri() returns a relative uri, which in this case would be an empty string. What you want to do is use the url method of the Route class: Route::url('main/index'). This will give you an url that has gone through Url::site as well.
searching for this question, I found this question/answer:
Kohana 3 get current controller/action/arguments
I recently switched to Kohana after using codeigniter for a while.
In Codeigniter, you could just do (in a Controller):
public function action_nameAction($param1, $param2 = null, ...){
$something = $param1;
}
by calling www.mysite.com/controllerName/param1/param2
I really liked this approach and don't really understand the point of Kohana's approach with redefining the routes...
If there is a solution to have the Codeigniter approach in Kohana, I would like some clues on how to implement it.
If not, please could someone explain me the interest of having to redefine new routes for every case that doesnt fall into the default route...
Route::set('default', '(<controller>(/<action>(/<id1>(/<id2>))))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
$id = $request->param('id1');
$id = $request->param('id2');
I believe I know how to do this, but wanted to verify with my awesome community peeps. =)
Here's an example:
I have a Controller class called 'tami', with an action 'index'.
I know that if I want someone to access that controller/action combo via an URL other than "/tami/" or "/tami/index", then I should add a route, via something like this:
Route::set('pretty_tami', 'these-are-my-initials(/<action>)')
->defaults(array(
'controller' => 'tami',
'action' => 'index',
));
But, users can still access this page via /tami/.
How can I turn off the default routing, so that the only valid routes are the ones I define?
I assume I can just remove the default route found in kohana/application/bootstrap.php. Is that correct? Or would that break something else?
I'd say exactly the same as #simshaun — either remove the default route (leaving other controllers unreachable) or check in the before() function in Controller_Tami for the uri to see if it's what you're after.
If you're using Kohana 3.1, you can now use lambda logic/anonymous functions to define your routes.
Something like this would take the extra routing logic out of the controller (which is good as we're keeping it in one place):
Route::set('default', function($uri)
{
if ($uri == 'tami' OR $uri == 'tami/index')
{
// Route not allowed by the default methods
throw new Kohana_404_Exception("Route not permitted");
}
},
'(<controller>(/<action>(/<id>)))'
);
Something I haven't yet used but it looks amazingly powerful.
I think the easiest way would be to remove the default route in your bootstrap file, yes. However, any controllers that you have not manually specified a route for can no longer be accessed.
What I would do is create a class, e.g. Controller_Derouter that Controller_Tami extends. Use the before() method in Controller_Derouter to test if the controller was accessed from the default route, and if so, throw a 404. I think you should be able to do that by comparing $this->request->controller against the first URI segment.
Edit: The solution mentioned above is unnecessary if you ever only plan on disabling the default route for just the Tami controller. If that's the case, you could just implement the before() method directly in the Tami controller.
Maybe like this?
Route::set('pretty_tami', 'these-are-my-initials/<action>')
->defaults(array(
'controller' => 'tami',
));
So there wouldn't be a default action. And you probably want to update the default route (if you still have one) with a regex to exclude tami.
Route::set('default', '(<controller>(/<action>(/<id>)))', array('controller' => '/^(?!tami)/'))
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));