Laravel 5 multiple optional parameters in route - php

I have a problem with Laravel 5, and to be precise, I can't find the solution for it.
In C# (ASP.NET MVC) it's easy to solve.
For example, I have these routes (I'll just type the route content, and the function header, for the sake of simplicity)
/{category}/Page{page}
/Page{page}
/{category}
The function is defined inside Product controller.
function header looks like this:
public function list($page = 1, $category = null)
the problem is, whenever I enter just one argument, it doesn't send the value for the parameter by the name I set in the route, but rather, it pushes values by function parameter order.
So, when I open /Page1, it works properly, value of 1 is sent to $page variable,
but when I access /Golf(made up on the spot), it also sends the value to the $page variable.
Any possible idea how to avoid this, or do I really need to make different functions to handle these cases?
In C#, it properly sends the value, and keeps the default value for undefined parameter.
Hope you have an answer for me.
Thank you in advance and have a nice day :)

So, as you've seen the parameters are passed to the function in order, not by name.
To achieve what you want, you can access these route parameters from within your function by type hinting the request object to it like this:
class ProductController extends Controller
{
function list(Request $request){ # <----------- don't pass the params, just the request object
$page = $request->route('page'); # <--- Then access by name
$category = $request->route('category');
dd("Page: $page | Category: $category");
}
}
Then of course you would set all 3 of your routes to hit that same controller method:
Route::get('/{category}/Page{page}', 'ProductController#list');
Route::get('/Page{page}', 'ProductController#list');
Route::get('/{category}', 'ProductController#list');
Hope this helps..!

if you want to get the parameters in your controller, you can use this:
public function list() {
$params = $this->getRouter()->getCurrentRoute()->parameters();
}
for /aaa/Page3, the $params would be array(category => 'aaa', page => '3')
for /Page3, the $params would be array(page => '3')
for /aaa, the $params would be array(category => 'aaa')

Related

How To Implement "defaults()" For Multiple Params In A Route - Laravel

So I have a POST URL with two parameters and I want to assign default values for both parameters .
I know you can implement this way for a URL with a single param:
Route::post('activity-log/datatable/{tag_access?}/{page_access?}',
'SettingsController#datatable_activity_log')
->defaults('tag_access', 'activity-log');
But how do i go about it with a URL that looks like this:
Route::post('activity-log/datatable/{tag_access?}/{page_access?}',
'SettingsController#datatable_activity_log')
You can achieve it by following way:
Keep your route as you want like this:
Route::post('activity-log/datatable/{tag_access?}/{page_access?}','SettingsController#datatable_activity_log')
Now, In controller function you can take these parameters with default value like this,
public function datatable_activity_log($tag_access='activity-log', $page_access='activity-log', Request $request){
// Here write your logic
}
This may not be the best way to achieve what you want but this is one of the way.
From what I see regarding the usage of defaults you can either do one at a time:
Route::post('activity-log/datatable/{tag_access?}/{page_access?}',
'SettingsController#datatable_activity_log')
->defaults('tag_access', 'activity-log')
->defaults('page_access', 'defaultValue');
An alternative (since defaults is public) is to do:
$route = Route::post('activity-log/datatable/{tag_access?}/{page_access?}',
'SettingsController#datatable_activity_log');
$route->defaults = [ 'tag_access' => 'activity-log', 'page_access' => 'defaultValue' ];
My personal favourite is what #Sagar Gautam suggest which is to use default function parameters.

Codeigniter - How to get url variable value inside contoller function?

I have URL like this: http://localhost/sitename/some-post-title/code=24639204963309423
Now I have one findUser function in my controller file
public function findUser() {
// I have tried with $_GET['code']
}
and I am trying to get code variable value inside this function. I have tried with $_GET['code'] but did not worked.
Any Idea how to get value inside controller function?
Thanks.
Are you trying to get a path segment variable or a GET variable? It looks like you're going for a bit of both.
Natively in CI, you can use $this->input->get if you update your url to look more like
http://localhost/sitename/some-post-title/?code=24639204963309423
(Note the question mark).
Alternatively, you can modify your URL to look like this
http://localhost/sitename/some-post-title/code/24639204963309423
And then use URI segments like so
$data = $this->uri->uri_to_assoc();
$code = $data['code'];
If you do not want to change your URL, you will have to break that string up manually like so
$data = $this->uri->segment(3);
$data = explode($data, '=');
$code = $data[1];
I would argue the second option is the most SEO-friendly and pretty solution. But each of these should be functionally identical.
If your URI contains more then two segments they will be passed to your function as parameters.
For example, lets say you have a URI like this:
example.com/index.php/products/shoes/sandals/123
Your function will be passed URI segments 3 and 4 ("sandals" and "123"):
<?php
class Products extends CI_Controller {
public function shoes($sandals, $id)
{
echo $sandals;
echo $id;
}
}
?>
If you are using GET to get parameters, you can do like this:
$this->input->get('get_parameter_name');
Typically there is a one-to-one relationship between a URL string and its corresponding controller class/method. The segments in a URI normally follow this pattern:
example.com/class/function/id/
More details for Controllers find here and for GET find here

How to forward with GET parameters?

How to forward with GET parameters?
I have two actions in same controller. I do some magic in the first action, and if all goes well, I want it to forward to the other one, but with GET parameters created in the first one.
What I have now is this:
return $this->forward('AppBundle:default:tracked', array(), array(
'tracking_code' => $tracking_code,
'company' => $tp_company_name
)));
Empty array in there because of a desperate effort to get it to work. Documentation tells that second array is for the query parameters, but nothing really happens, so I must be doing something wrong.
The second action tries to get the parameters like this:
/**
* #Route("/tracked", name="tracked")
*/
public function trackedAction()
{
$request = Request::createFromGlobals();
// If there is the required variables in the GET:
if($request->query->has('tracking_code') && $request->query->has('company'))
But no, variables never get there it seems.
Reason I have this kind of setup, is that user can get into the trackedAction from another place as well.
I think the proper way to get your parameters in your second action would be to do like this :
return $this->forward('AppBundle:default:tracked', array(
'tracking_code' => $tracking_code,
'company' => $tp_company_name
)));
And your second action would be :
/**
* #Route("/tracked/{tracking_code}/{company}", name="tracked")
*/
public function trackedAction($tracking_code=null, $company=null)
{
...
}
I used the $tracking_code = null because you specified this could be accessed from another place, that maybe does not provide these parameters. This way it works for both of them.
Hope this helps.
The way that Symfony controller forwarding works is by duplicating the current the Request with the options that you pass and then re-dispatching it through the HttpKernel component. You can see this in the code. Because it's a sub-request, your second action is creating a Request from globals (i.e. $_GET etc.) which haven't changed.
The solution is to change your second action method signature to:
public function trackedAction(Request $request)
This means that the $request variable will be "local" to your action and will contain the variables you want.
In practice you should always pass the Request in to your actions this way as it makes your controllers a lot more testable and prevents strange issues like this.
Alternatively to all of the above, you could use a redirect instead which would do an HTTP redirect rather than just forwarding within the Symfony request system.

Using Laravel 5 Method Injection with other Parameters

So I'm working on an admin interface. I have a route set up like so:
Route::controllers([
'admin' => 'AdminController',
]);
Then I have a controller with some methods:
public function getEditUser($user_id = null)
{
// Get user from database and return view
}
public function postEditUser($user_id = 0, EditUserRequest $request)
{
// Process any changes made
}
As you can see, I'm using method injection to validate the user input, so URL's would look like this:
http://example.com/admin/edit-user/8697
A GET request would go to the GET method and a POST request to the POST method. The problem is, if I'm creating a new user, there won't be an ID:
http://examplecom/admin/edit-user/
Then I get an error (paraphrased):
Argument 2 passed to controller must be an instance of EditUserRequest, none given
So right now I'm passing an ID of 0 in to make it work for creating new users, but this app is just getting started, so am I going to have to do this throughout the entire application? Is there a better way to pass in a validation method, and optionally, parameters? Any wisdom will be appreciated.
You can reverse the order of your parameters so the optional one is a the end:
public function postEditUser(EditUserRequest $request, $user_id = null)
{
}
Laravel will then resolve the EditUserRequest first and pass nothing more if there's no user_id so the default value will kick in.

How to access values of multiple parameters passed to Laravel controller

I am trying to figure out how to access two (or more) parameters passed to a Laravel controller. I know how to create the route, and the URL is created correctly, but then I can only access the first passed parameter in my controller.
Route:
Route::get('managers/{id}/{parameter2}', array('as'=>'dosomething', 'uses'=> 'ManagersController#dosomething'));
where the first parameter is obviously the $id for managers, and the second parameters is to be processed by the controller.
View:
Do Something
generates the URL:
http://domain/managers/1/2
where 1 is easily accessed as the $id for managers, but when I try to access the 2nd parameter "2" using $parameter2, e.g. using a simple return: "id=$id and parameter2=$parameter2" statement, I get an "unidentified variable: $parameter2" error.
What am I doing wrong?
Is there a better way to pass multiple parameters? I'm especially asking the "better way?" question because what I want to do is use the 2nd parameter to change a value in a database table, and using a 'get' method, somebody could change the parameter value in the URL and therefore cause mischief. Must I use a 'post' method? I'd love to be able to use a link, since that works much better with the design of my application.
Thanks!
I was asked to include the controller, which I'm happy to do. Initially, just for testing, as I mentioned, my controller was a simple return to display the values of the two passed parameters. But here is what I want to be able to do, including the actual name of the function ("update_group" rather than "dosomething") --
ManagersController:
public function update_group($id)
{
DB::table('groups')->where('id','=',$parameter2)->update(array('manager_id'=>$id));
return Redirect::route('managers.show', array('id'=>$id));
}
The update table works perfectly if I replace $parameter2 with an actual value, so that syntax is fine. The issue is that Laravel says that $parameter2 is an undefined variable, despite the fact that the URL contains the value of $parameter2 as you can see above.
And since it occurs to me that the answer to this may involve adding a function to the Manager model, here is the current
Manager.php
class Manager extends Eloquent {
protected $table = 'managers'; ... (mutator and error functions)
}
Just change
public function update_group($id)
to
public function update_group($id, $parameter2)
All looks ok in your route. Seeing the controller code would help, but likely, you may not have a second parameter in your controller's dosomething() method.
public function dosomething($id, $parameter2){
var_dump($id).'<br />';
var_dump($paremter2);
}
If that isn't the case, you can try dumping it from the route's callback to further diagnose.
Route::get('managers/{id}/{parameter2}', function($id, $parameter2)
{
var_dump($id).'<br />';
var_dump($paremter2);
});
Depending on your use case, you can pass them in a query string like so: but it isn't really the 'best way', unless you're doing something like building an API that won't use the same variables in the same order all the time.
/managers?id=1&paramter2=secondParameter
var_dump(Request::query('id')).'<br />';
var_dump(Request::query('paramter2'));

Categories