laravel route variables passing null values give url error - php

I have a route that has 3 optional variables declared as null in Controller
Route::get('gegonota/{gid?}/{cid?}/{nid?}', [
'uses' => 'GegonosController#index',
'as' => 'gegonota'
]);
and even i change the order of the parameter the problem still exists.
public function index($gid = null, $cid = null, $nid = null)
When values of the variables are null are not showing in the url like
http://localhost:8000/gegonota///1
and gives me route errors like it didnt find the specific url.
I have to check and substitute null to 0 so that has something in the url and give no error.
Which is laravel way to do that avoiding all the trouble.
thanks

You may be interested in using Optional Path Parameter as stated in Laravel doc. This means you'll have:
Route::get('gegonota/{gid}/{cid}/{nid?}', [
'uses' => 'GegonosController#index',
'as' => 'gegonota'
]);
Hope this solves the issue.
Update
Even though I cannot say this is the fix since you said rearranging the variable did not solve the issue. I would rather pass those optional variables as request parameters to make things easy, i.e my url would look like:
http://localhost:8000/gegonota/?gid=&cid=&nid=
Therefore, I can already set the default for each of the expected parameters as null rather than deal with inconsistency that may arise from having this kind of wierd /// in my url:
//In a controller
public funtion index()
{
//put them in an array
$my_variables = request()->only(['gid', 'cid', 'nid']);
//or this way
$gid = request()->get('gid');
$cid = request()->get('cid');
$nid = request()->get('nid');
//they are default to null if not existing or have no value
}
This means your route declaration is simple, i.e:
Route::get('gegonota', [
'uses' => 'GegonosController#index',
'as' => 'gegonota'
])
Unless there is an exceptional need to pass those optional variable to the path, its clearly easier and better to have it as request parameters.
Hope this is better.

Related

Laravel give array to route, not all values are required

I'm getting this error
Missing required parameters for [Route: payment.checkPayment] [URI: {unique_link}/{paymentrequest}/{info}].
Here I encode the array. Note is optional, is also nullable in database.
$info = json_encode(["name" => $request->name, "note" => $request->note]);
This is where I'm sending it to the route
route('payment.checkPayment', [$uniquelink, $paymentrequest, $info])
Route
Route::get('/{unique_link}/{paymentrequest}/{info}', ['as' => 'payment.checkPayment', 'uses' => 'PaymentController#checkPayment']);
How would I fix this? It seems to me I'm sending all of the parameters.
You need to use key-value arrays instead of array-lists as you do:
use:
route('payment.checkPayment', ['unique_link'=>$uniquelink, 'paymentrequest'=>$paymentrequest, 'info'=>$info]);
Reference Laravel Named routes
NOTE it seems you use json-encoded value for the info field, but NOT SURE if this will generate a valid URI. Better check it.

laravel router argument behaviour

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&para2=abc
I hope it is helpful and I now understand why laravel remove Route::controllers from 5.3 version.

URL hit the wrong controller LARAVEL

In route.php I defined a route to a controller with 2 tokens on it.
Route::get('/{category}/{slug}', 'projectController#detail');
Everything is working fine till when there is a call to a URL that have the same structure but has nothing to do with the one that has to be caught by that route shown below.
So when I have for example "/admin/tags", the controller below is triggered because it has the same structure of "/{category}/{slug}" and of course it gives me an error, because it doesn't find a variable.
So now I fixed the problem moving that route on the bottom, but I believe I have to do something to prevent this behavior in advance, cause if I have multiple routes with different tokens everything would be triggered every time and there would be a mess.
So, what is it supposed to do in these cases?
P.S. I'm super beginner with Laravel
use some constraint to the route, reference parameters-regular-expression-constraints. For example:
Route::get('user/{name}', function ($name) {
//
})
->where('name', '[A-Za-z]+');
Or you can make the most specific before unspecific one. For example, in this sequence:
Route::get("/admin/tags", '......');
Route::get('/{category}/{slug}', 'projectController#detail');
if route need two token like that, i'm usually add prefix so my routes looks like this
Route::get('/categories/{category}/slug/{slug}', 'ProjectController#detail');
or
Route::get('/categories/{category}/{slug}', 'ProjectController#detail');
I was having the same issue.
I have constraints on every path parameter (as you always should) and unfortunately the conflict occurs between the following:
Route::get('{userId}/{path}', [
'as' => 'products',
'uses' => 'HomeController#click'
])->where(['id' => '[0-9]+', 'path' => '[0-9a-fA-F]+']);
Route::get('link/{link_path}', [
'as' => 'product-link',
'uses' => 'UserController#productLink'
])->where(['link_path' => '[0-9a-fA-F]+']);
Where even though the one path has the prepended 'link/' in the path it still tried to hit the other. By placing the route with the prepended 'link/' above the other route it took priority and works.
Personally I think if you have a condition that isn't met on the route where clause it should skip the route and move on to the next. It doesn't really make sense to me to put a conditional that doesn't actually get passed up if the conditions aren't met.
Hopefully this helps anyone else having this issue.

Laravel using named routes

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.

Getting parameter from url in Zend

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.

Categories