My route setup :
Zend_Controller_Front::getInstance()
->getRouter()
->addRoute('view', new Zend_Controller_Router_Route('controller/action/:name'))
My link in view :
$this->url(array("name" => "John"), "view", TRUE);
// returns "controller/action/John" as should
Now, when I am at controller/action/John, how do I get the name from URL ? I tried
$this->getRequest()->getParam("name");
but the name param isn't there - getRequest() returns only controller, action and module params.
When you set up your route configuration the route definition should either directly match the controller/action names or be set with defaults. Actually setting the defaults in any case is just good practice and helps you avoid issues like this.
So, in your case according to the comments your route should probably look like this.
$defaults = array(
'controller'=> 'offers',
'action' => 'view',
'name' => ''
);
$route = new Zend_Controller_Router_Route('offers/view/:name',$defaults);
As mentioned in the comments you can always check what route has been used with Zend_Controller_Front::getInstance()->getRouter()->getCurrentRouteName(). If it doesn't show your expected route the Router isn't able to find a match and moves on until it usually ends in the "default" route.
As a side note to your question: When you use $this->url(array("name" => "John"), "view", TRUE) you only create the link based on the route. This method is only part of the view and does nothing in terms of dispatching to a controller or action.
For those who found this question and for future reference, you can get params from route using this : $this->params()->fromRoute('param1', 0); in Zend Framework 2 at least. This is what I was looking for in this question.
Related
I notice that when you use URL:::action, and set some arguments, sometimes laravel would cast them as GET requests, sometimes not.
Is there anyone know why and how to controller it?
echo URL::action('Campaign\\CampaignController#getIndex',['para' => 1]),"<br>";
echo URL::action('Campaign\\CampaignController#getOtherAction',['para' => 1]),"<br>";
echo URL::action('Campaign\\CampaignController#getOtherAction2',['para' => 1]),"<br>";
Output:
/campaign?para=1
/campaign/other-action/1
/campaign/other-action2/1
Note the getIndex gets argument as GET (?para=1)
This happens because system cannot differentiate requests to getIndex from others if they pass it as url segment.
Means
/campaign/other-action/1 translates to other-action as a method with 1 as param
By your expectation
/campaign/other-action/1 translates to getIndex as a method with other-action/1 as param
Index methods are not suppose to have URL segments as inputs. If you need url segments as inputs then you will have to pass it as a get parameter and thats what laravel is doing for you.
According to your first route output,
if the url is /campaign/1 which means it will expect a method named get1. Another example: if the url is /campaign/param system would expect a method getParam
NOTE for fellow stackoverflow-ers:Consider asking questions before downvoting
I actually found the reason.
when you are using route::controllers method, laravel would assume you have multiple parameters attached to each action
Route::controllers([
'order' => 'Order\OrderController',
'campaign' => 'Campaign\CampaignController'
]);
For example:
campaign/other-action/{VALUE1?}/{VALUE2?}/{VALUE3?}...
So when you pass ['para' => 1, 'para2' => 'abc'], laravel will try to match parameters to action. in this case: campaign/other-action/1/abc
Avoiding to use Route::controllers, an help you take control on laravel router argument behaviour.
For example, in routes.php:
Route::get('campaign/other-action/{id}','Campaign\CampaignController#getOtherAction2')
when you give
echo URL::action('Campaign\\CampaignController#getOtherAction2',['id'=>366, 'para' => 1, 'para2' => 'abc']);
you will get what you want:
campaign/other-action/366?para=1¶2=abc
I hope it is helpful and I now understand why laravel remove Route::controllers from 5.3 version.
Regarding the use of named routes, these 2 lines allow me to access the same page so which is correct?
// Named route
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// Much simpler
Route::get('apples', 'TestController#getApples');
Is there any reason I should be using named routes if the latter is shorter and less prone to errors?
Named routes are better, Why ?
It's always better to use a named route because insstsead of using the url you may use the name to refer the route, for example:
return Redirect::to('an/url');
Now above code will work but if you would use this:
return Redirect::route('routename');
Then it'll generate the url on the fly so, if you even change the url your code won't be broken. For example, check your route:
Route::get('apples', 'TestController#getApples');
Route::get('apples', array('as' => 'apples.show', 'uses' => 'TestController#getApples'));
Both routes are same but one without name so to use the route without name you have to depend on the url, for example:
return Redirect::to('apples');
But same thing you may do using the route name if your route contains a name, for example:
return Redirect::route('apples.show');
In this case, you may change the url from apples to somethingelse but still your Redirect will work without changing the code.
The only advantage is it is easier to link to, and you can change the URL without going through and changing all of its references. For example, with named routes you can do stuff like this:
URL::route('apples');
Redirect::route('apples');
Form::open(array('route' => 'apples'));
Then, if you update your route, all of your URLs will be updated:
// from
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// to
Route::get('new/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
Another benefit is logically creating a URL with a lot parameters. This allows you to be a lot more dynamic with your URL generation, so something like:
Route::get('search/{category}/{query}', array(
'as' => 'search',
'uses' => 'SearchController#find',
));
$parameters = array(
'category' => 'articles',
'query' => 'apples',
);
echo URL::route('search', $parameters);
// http://domain.com/search/articles/apples
The only reason to name the route is if you need to reference it later. IE: from your page in a view or something, check whether you are in that route.
I'm new with Kohana and finding their documentation to be lacking (lots of incomplete writings, lots of broken links, etc.). I just want to create a route like so:
Route::set('test1', 'blah/<id>')
->defaults(array(
'controller' => 'Blah',
'action' => 'foo',
));
So if the URL is localhost/blah/8342342 it will run through this controller and action. The problem is I get a 404 error. If I change the URI in the Route::set to be blah/foo/<id> it works fine. I only want the /blah/ directory though, not 'blah/foo'. Is this possible or do you need to have both the controller and action in the URL?
Another question, does the first directory in your URI (in this case /blah) HAVE to match the controller name? For example, if the first directory in the URI is "blah/", does that mean my controller must be named "Blah.php"? From my tests it seems that this is the case, but I don't know why it would be set up that way. What if I wanted the URI "contact/" to go through controller Blah?
so I'm using zend_router to route my index page in my controller to an action other than the index action:
$route = new Zend_Controller_Router_Route(
'/controller/:page',
array(
'action' => 'not-index',
'controller' => 'controller',
'page' => 1,
),
);
And the reason why I'm adding :page into the path is because there's pagination in that index and I'd like to have paginator to work even if the user only enters '/controller' into the browser, so it's got to be there (see: http://www.joewebster.co.uk/articles/zend-framework/7-zend-pagination-and-zend-router)...
the problem is....now other actions within the controller will redirect to that page as well and not to the proper action
so suppose I enter '/controller/other-action' to the browser, it goes to 'controller/not-index' with page = other-action instead of 'controller/other-action' due to that routing definition....is there a way to limit the :page in that router definition to integers only, ie. if I enter '/controller/2' then go to 'controller/not-index' with page = 2, and if I enter '/controller/other-action' it'll actually go to 'controller/other-action'
I think you might want to take a look at the Regex_router:
http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes.regex
That should help you achieving your goal. I'm afraid the standard Router isn't flexible enough.
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',
));