How do I pass extra parameters in the URL to KohanaPHP (version 3.1+) like so...
http://example.com/blog/edit/4000/3200
...where "blog" is the blog.php in the controllers folder, "edit" is a controller method, 4000 is parameter 1 which I can use for who wants to edit the record, and 3200 is parameter 2 which I can use for the record ID?
I get the blog and edit parts. The problem is the 4000 and 3200. When I run that URL, I get an error: "404 - Unable to find a route match blog/edit/4000/3200"
Am I forced to have to do something unusual with the .htaccess file, or pass the parameters as query params after a question mark?
This explains what to do:
http://kohanaframework.org/3.1/guide/kohana/routing
But essentially, I need to edit the application\bootstrap.php file and change this:
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index'
));
to this:
Route::set('default', '(<controller>(/<action>(/<param1>)(/<param2>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index'
));
And now in my blog.php controller file, I can now pass 2 parameters into the "action_edit" class method like so:
public function action_edit() {
$sParam1 = $this->request->param('param1');
$sParam2 = $this->request->param('param2');
$this->response->body('param1=' . $sParam1 . ' param2=' . $sParam2);
}
You need a route like this in your bootstrap.php:
Route::set('blog_edit', 'blog/edit/<param1>(/<param2>)')
array(
'param1' => '[[:digit:]]{1,}',
'param2' => '[[:digit:]]{1,}',
))
->defaults(array(
'controller' => 'blog',
'action' => 'edit',
));
Note: the "()" makes param2 optional.
In your controller you can access the parameters as method arguments or via the Request object:
class Controller_Blog
{
public function action_edit($param1, $param2)
{
// or
$param1 = $this->request->param('param1');
$param2 = $this->request->param('param2');
// [...]
}
}
I haven't tested this code but it should be very close to what you need.
Referenced from "Kohana PHP 3.0 (KO3) Tutorial Part 6"
Related
I'm trying to use my index controller to create a url structure like this: mydomain.com/vehiclemake/vehiclemodel/vehiclemodelyear
I don't know how to alter the default route, or alter a duplicate that will work as intended. Every time I load the page once a make has been added to the url, it gives me a blank screen and the logs tell me it can't find a controller with the name of the vehicle make that was in the url. Below is the default and what I've tried.
Route::set('vehicle', '(/<make>(/<model>(/<model_year>)))')
->defaults(array(
'controller' => 'index',
'action' => 'index',
));
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'index',
'action' => 'index',
));
I've tried looking for an answer here on stackoverflow but I haven't found a question that's similar to mine that has an answer.
I'm not sure if I understand your question right.
Anyway, you won't need the first / before .
Besides that, this structure will require a controller for every make and in that controller an action for every model. I think something like the code below will work for the uri: /ferrari/testarossa/1992
class Ferrari extends controller {
public function action_testarossa() {
// whatever you'd like to do
echo $this->request->param('model_year');
}
}
I think the default in routing always is, but I'm not sure.
1. controller
2. action
3. whateveryoudefine
4. whateveryoudefine
Hope this helps!
You must plan your routing so that one URL cannot be matched to 2 routes. I suggest:
Route::set('vehicle', '/<make>(/<model>(/<model_year>))')
->defaults(array(
'controller' => 'vehicle',
'action' => 'index',
));
Route::set('mainpage', '/')
->defaults(array(
'controller' => 'index',
'action' => 'index',
));
Route::set('default', '<controller>(/<action>(/<id>))', ['controller'=>'(index|user)'])
->defaults(array(
'controller' => 'index',
'action' => 'index',
));
Note that I removed 1 pair of brackets. And for default route correct controllers are: index and user.
I am using CakePHP 1.3 and have some troubles with prefix routing.
I configured routes like that:
Router::connect(
'/listing/*',
array(
'controller' => 'dsc_dates',
'action' => 'listing',
)
);
Router::connect(
'/modular/listing/*',
array(
'controller' => 'dsc_dates',
'action' => 'listing',
'prefix' => 'modular'
)
);
in my controller there are two functions:
function modular_listing($order = null,$orderDirection = null, $items=null, $location_id=null) {
$this->layout='module';
$this->setAction('listing',$order, $orderDirection, $items, $location_id);
}
function listing($order = null,$orderDirection = null, $items=null, $location_id=null){...}
The prefix action should just change some things and then operate like the normal 'listing' method. Until here it works fine.
But if i create relative links (with HTML Helper) Router::url() uses 'modular_listing' as action which does not fit into my routes. It should be 'listing' instead of 'modular_listing'.
The controller params are correct with 'listing' as action but the router params still says 'modular_listing'.
So relative links:
$this->Html->link('example',array('parameter'));
will end up in:
/dsc_dates/modular_listing/parameter
How can I get the correct links so that the router uses 'listing' as action?
UPDATE:
It is not an alternative to add 'controller' and 'action' to the url array of the link generation. In fact I have problems with the automatically generated relative links from the paginator.
I couldn't tell if you wanted the generated Html->link() routes with the leading controller or not, so I did both:
Controller (note the renderer):
// DscDatesController.php
public function listing($param = null) {
$this->set('param', $param);
$this->render('listing');
}
public function modular_listing($param = null) {
//
$this->setAction('listing', $param);
}
Routes:
// routes.php
Router::connect(
// notice no leading DS
'listing/*',
array(
'controller' => 'DscDates',
'action' => 'listing'
)
);
Router::connect(
'/modular/listing/*',
array(
'controller' => 'DscDates',
'action' => 'listing'
)
);
View:
// DscDates/listing.ctp
<?php
// generates /dsc_dates/listing/:param
echo $this->Html->link(
'example',
array('controller'=>'dsc_dates', 'action'=>'listing', $param));
// generates /listing/:param
echo $this->Html->link(
'example',
array('action'=>'listing', $param));
About wildcards, DS and routing order:
CakePHP broken index method
HTH :)
Is it possible to have pages route without the controller in the URL but still have other controllers work? Example:
Access pages like this: http://domain.com/about/
Instead of like this: http://domain.com/pages/about/
But still have access to http://domain.com/othercontroller/action/
Doing the following works for having the pages without /pages/ in the URL but if I try to access any other controller it doesn't work:
From: Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
To: Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'index'));
Is there a way to setup the Router so that it runs controller/action if it exists. If it does not it runs the pages controller/action?
I think the short answer is, no - it's not possible in the manner you're hoping*. Routing isn't really "logic" driven, so unless you can come up with a way to match the things you want in both respects you can't do "if controller exists, then _, else _" kind of thing.
*You could, however add each "page" as a row in your routes file. That would allow "about", "contact" ...etc to be accessed directly, while things that don't exactly match them are handled by the remaining routes.
I know I'm late, but here's my tip for someone looking for this.
In routes.php
foreach(scandir('../View/Pages') as $path){
if(pathinfo($path, PATHINFO_EXTENSION) == "ctp"){
$name = pathinfo($path, PATHINFO_FILENAME);
Router::connect('/'.$name, array('controller' => 'pages', 'action' => 'display', $name));
}
}
This will create a route for every ctp file in the View/Pages folder.
I actually solved this the opposite way from Dave's answer above, by adding a route for each controller, rather than each page. (I won't be adding new controllers very often, but I will be adding new content on a regular basis.)
// define an array of all controllers that I want to be able to view the index page of
$indexControllers = array('posts','events','users');
//create a route for each controller's index view
foreach ($indexControllers as $controller) {
Router::connect(
'/' . $controller,
array(
'controller' => $controller,
'action' => 'index'
)
);
}
//create a route to remove 'view' from all page URLs
Router::connect(
'/:title',
array(
'controller' => 'contents',
'action' => 'view'
),
array(
'pass' => array('title'),
'title' => '[a-z0-9_\-]*'
)
);
I have one route that looks like this:
Router::connect('/Album/:slug/:id',array('controller' => 'albums', 'action' => 'photo'),array('pass' => array('slug','id'),'id' => '[0-9]+'));
and another like this:
Router::connect('/Album/:slug/*',array('controller' => 'albums','action' => 'contents'),array('pass' => array('slug')));
for what doesn't match the first. In the 'contents' action of the 'albums' controller, I take care of pagination myself - meaning I retrieve the named parameter 'page'.
A URL for the second route would look like this:
http://somesite.com/Album/foo-bar/page:2
The Above URL indeed works, but when I try to use the HTML Helper (url,link) to output a url like this, it appends the controller and action to the beginning, like this:
http://somesite.com/albums/contents/Album/foo-bar/page:2
Which i don't like.
The code that uses the HtmlHelper is as such:
$html->url(array('/Album/' . $album['Album']['slug'] . '/page:' . $next))
See below url it is very help full to you
http://book.cakephp.org/2.0/en/development/routing.html
Or read it
Passing parameters to action
When connecting routes using Route elements you may want to have routed elements be passed arguments instead. By using the 3rd argument of Router::connect() you can define which route elements should also be made available as passed arguments:
<?php
// SomeController.php
public function view($articleId = null, $slug = null) {
// some code here...
}
// routes.php
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]+'
)
);
And now, thanks to the reverse routing capabilities, you can pass in the url array like below and Cake will know how to form the URL as defined in the routes:
// view.ctp
// this will return a link to /blog/3-CakePHP_Rocks
<?php
echo $this->Html->link('CakePHP Rocks', array(
'controller' => 'blog',
'action' => 'view',
'id' => 3,
'slug' => 'CakePHP_Rocks'
));
My controller action requires a parameter, but I can't get KO3's router to pass this parameter in the Default route. This sort of thing works with other routes. Here is an example to clarify...
In bootstrap.php...
Route::set('default', '(<controller>(/<action>(/<the_required_param>)))')
->defaults(array(
'controller' => 'DefaultController',
'action' => 'index',
'the_required_param' => 'some_default_value',
));
In controller file...
class Controller_DefaultController extends Controller
{
public function action_index($the_required_param)
{
echo 'value: ' . $the_required_param;
}
}
Another way to get the specified param would be:
$this->request->param('the_required_param');
You should also ensure you define your routes in order and ensure it matches what it's supposed to.
The problem was being caused by a greedy route (would match any uri), so the Router never reached the Default route. Below is an example for reference...
// The parenthesis caused this route to match any uri
Route::set('route-4-params', '(<controller>/<action>/<p1>/<p2>/<p3>/<p4>)');
Route::set('default', '(<controller>(/<action>))')
->defaults(array(
'controller' => 'default_controller',
'action' => 'index',
'the_required_param' => 'somevalue',
));