how to add optional parameter to laravel named routes? - php

Using Laravel 4.2 and according to routing documentation
We can define a named route as
Route::get('user/profile', array('as' => 'profile', 'uses' => 'UserController#showProfile'));
And define an optional parameter with this other way
Route::get('user/{name?}', function($name = null)
{
return $name;
});
I want to add an optional parameter to a named route. How to combine both ?

Try this
Route::get('user/{name?}', function($name = null)
{
return $name;
})->name('foo');
Update
sorry the name method not exists in Laravel 4.2
You can do it in another way
Route::get('user/profile/{name?}', array('as' => 'profile', 'uses' => 'UserController#showProfile'))
or
Route::get('user/profile/{name?}', array('as' => 'profile', function($name = null) {
// your code here
})

You can define route common for all functions..
like:
Route::controller('uses', 'UserController');
And define function with optional parameters:
public function getView($param = 0)
//your code here
}
using this you can use optional parameters in a function on which you required.with help of ajax call on function.

Related

Conditional routing based on Middleware

I need to call different controller for the same url based on a middleware. The url has to be the same, so redirecting in the middleware is not an option. The code below is sample, controllers for dozens for routes are already finished, so checking the session value there is not an option either.
Tried to create two different middleware (has/hasnt the session value), but the latter route group overwrites the previous anyway. Any clue? Maybe a different approach needed?
route.php looks like this:
Route::group(array('namespace' => 'Admin', 'prefix' => 'admin', 'middleware' => 'auth'), function () {
// set of default routes
Route::get('/', array('as' => 'admin', 'uses' => 'FirstController#index'))->middleware('admin');
Route::get('/profile', array('as' => 'profile', 'uses' => 'FirstController#profile'))->middleware('admin');
Route::group(array('middleware' => 'sessionhassomething'), function () {
// set of the same routes like above but overwritten if middleware validates
Route::get('/', array('as' => 'admin', 'uses' => 'SecondController#index'))->middleware('admin');
Route::get('/profile', array('as' => 'profile', 'uses' => 'SecondController#profile'))->middleware('admin');
});
});
SessionHasSomething middleware:
class sessionHasSomething {
public function handle($request, Closure $next)
{
if(session()->has("something_i_need_to_be_set")) {
return $next($request);
}
// return what if not set, or ...?
}
}
Thanks in advance!
If you are only checking if session()->has('something'), it is possible to use route closures to add a condition within the route which needs to be dynamic.
Below is an example:
Route::get('/', function() {
$controller = session()->has('something')) ? 'SecondController' : 'FirstController';
app('app\Http\Controllers\' . $controller)->index();
});
->index() being the method within the controller class.
We almost have the same issue and here's what I did. (I didn't use middleware).
In my blade.php, I used #if, #else and #endif
<?php
use App\Models\User;
$check = User::all()->count();
?>
#if ($check == '0')
// my html/php codes for admin
#else
// my html/php codes for users
#endif
you can also do that in your controller, use if,else.

L5.3 - Call route from another route

I've a simple route into the file web.php:
Route::get('first/{param?}', [
'uses' => 'App\Http\Controllers\MyController#index',
'as' => 'myControllerIndex'
]);
Now, I'd like to create a second route that uses the first route but passing specific params.
I tried something like this:
Route::get('second', function () {
return file_get_contents(route('myControllerIndex', ['param' => 'book1']));
});
but it doesn't work.
Can anyone help me?
Thank you.
You could use a redirect
Route::get('second', function () {
return redirect()->route('myControllerIndex', ['param' => 'book1']);
});
Or you can access the controller directly
Route::get('second', function () {
return app('App\Http\Controllers\MyController')->index('book1');
});

How to pass extra parameters to controller from Laravel route

I'm trying to handle basic validation of my API calls in the Laravel's routes. Here is what I want to achieve:
Route::group(['prefix' => 'api/v1/properties/'], function () {
Route::get('purchased', 'PropertiesController#getPropertyByProgressStatus', function () {
//pass variable x = 1 to the controller
});
Route::get('waiting', 'PropertiesController#getPropertyByProgressStatus', function () {
//pass variable x = 2 to the controller
});
});
Long story short, depending on the segment of the URI after api/v1/properties/ I want to pass a different parameter to the controller. Is there a way to do that?
I was able to get it to work with the following route.php file:
Route::group(['prefix' => 'api/v1/properties/'], function () {
Route::get('purchased', [
'uses' => 'PropertiesController#getPropertyByProgressStatus', 'progressStatusId' => 1
]);
Route::get('remodeled', [
'uses' => 'PropertiesController#getPropertyByProgressStatus', 'progressStatusId' => 1
]);
Route::get('pending', [
'uses' => 'PropertiesController#getPropertyByProgressStatus', 'progressStatusId' => 3
]);
Route::get('available', [
'uses' => 'PropertiesController#getPropertyByProgressStatus', 'progressStatusId' => 4
]);
Route::get('unavailable', [
'uses' => 'PropertiesController#getPropertyByProgressStatus', 'progressStatusId' => 5
]);
});
and the following code in the controller:
public function getPropertyByProgressStatus(\Illuminate\Http\Request $request) {
$action = $request->route()->getAction();
print_r($action);
Pretty much the $action variable is going to let me access the extra parameter that I passed from the route.
I think that you can do it directly in the controller and receiving the value as a parameter of your route:
First you need to specify the name of the parameter in the controller.
Route::group(['prefix' => 'api/v1/properties/'], function ()
{
Route::get('{parameter}', PropertiesController#getPropertyByProgressStatus');
In this way, the getPropertyByProgressStatus method is going to receive this value, so in the controller:
class PropertiesController{
....
public function getPropertyByProgressStatus($parameter)
{
if($parameter === 'purchased')
{
//do what you need
}
elseif($parameter === 'waiting')
{
//Do another stuff
}
....
}
I hope it helps to solve your issue.
Take a view for this courses: Learn Laravel or Create a RESTful API with Laravel
Best wishes.
----------- Edited ---------------
You can redirect to the route that you want:
Route::group(['prefix' => 'api/v1/properties/'], function () {
Route::get('purchased', function () {
return redirect('/api/v1/properties/purchased/valueToSend');
});
Route::get('waiting', function () {
return redirect('/api/v1/properties/waiting/valueToSend');
});
Route::get('purchased/{valueToSend}', PropertiesController#getPropertyByProgressStatus);
});
Route::get('waiting/{valueToSend}', PropertiesController#getPropertyByProgressStatus);
});
});
The last two routes response to the redirections and send that value to the controller as a parameter, is the most near that I think to do this directly from the routes.

Pass fixed variable from route to controller in Laravel

I'm trying to pass a variable through my route to my controller, but I have multiple routes (categories) leading to the same controller i.e.
Route::get('/category1/{region}/{suburb?}', 'SearchController#search');
Route::get('/category2/{region}/{suburb?}', 'SearchController#search');
Making /category1, 2, etc. to be a parameter /{category} is not an option and I don't want to make separate controller function for each category.
How do I send the first segment of the url to my search controller? i.e. category1 or category2?
At present controller is as follows:
public function search($region, $suburb = null) { }
Thanks!
You can specify a mask for your {category} parameter so that it must fit the format "category[0-9]+" in order to match the route.
Route::get('/{category}/{region}/{suburb?}', 'SearchController#search')
->where('category', 'category[0-9]+');
Now, your example url (from the comments) www.a.com/var1/var2/var3 will only match the route if var1 matches the given category regex.
More information can be found in the documentation for route parameters here.
Edit
Yes, this can work with an array of string values. It is a regex, so you just need to put your array of string values into that context:
Route::get('/{category}/{region}/{suburb?}', 'SearchController#search')
->where('category', 'hairdresser|cooper|fletcher');
Or, if you have the array built somewhere else:
$arr = ['hairdresser', 'cooper', 'fletcher'];
// run each array entry through preg_quote and then glue
// the resulting array together with pipes
Route::get('/{category}/{region}/{suburb?}', 'SearchController#search')
->where('category', implode('|', array_map('preg_quote', $arr)));
Edit 2 (solutions for original request)
Your original question was how to pass the hardcoded category segment into the controller. If, for some reason, you didn't wish to use the solution above, you have two other options.
Option 1: don't pass the value in, just access the segments of the request in the controller.
public function search($region, $suburb = null) {
$category = \Request::segment(1);
dd($category);
}
Option 2: modify the route parameters using a before filter (L4) or before middleware (L5).
Before filters (and middleware) have access to the route object, and can use the methods on the route object to modify the route parameters. These route parameters are eventually passed into the controller action. The route parameters are stored as an associative array, so that needs to be kept in mind when trying to get the order correct.
If using Laravel 4, you'd need a before filter. Define the routes to use the before filter and pass in the hardcoded value to be added onto the parameters.
Route::get('/hairdresser/{region}/{suburb?}', ['before' => 'shiftParameter:hairdresser', 'uses' => 'SearchController#search']);
Route::get('/cooper/{region}/{suburb?}', ['before' => 'shiftParameter:cooper', 'uses' => 'SearchController#search']);
Route::get('/fletcher/{region}/{suburb?}', ['before' => 'shiftParameter:fletcher', 'uses' => 'SearchController#search']);
Route::filter('shiftParameter', function ($route, $request, $value) {
// save off the current route parameters
$parameters = $route->parameters();
// unset the current route parameters
foreach($parameters as $name => $parameter) {
$route->forgetParameter($name);
}
// union the new parameters and the old parameters
$parameters = ['customParameter0' => $value] + $parameters;
// loop through the new set of parameters to add them to the route
foreach($parameters as $name => $parameter) {
$route->setParameter($name, $parameter);
}
});
If using Laravel 5, you'd need to define a new before middleware. Add the new class to the app/Http/Middleware directory and register it in the $routeMiddleware variable in app/Http/Kernel.php. The logic is basically the same, with an extra hoop to go through in order to pass parameters to the middleware.
// the 'parameters' key is a custom key we're using to pass the data to the middleware
Route::get('/hairdresser/{region}/{suburb?}', ['middleware' => 'shiftParameter', 'parameters' => ['hairdresser'], 'uses' => 'SearchController#search']);
Route::get('/cooper/{region}/{suburb?}', ['middleware' => 'shiftParameter', 'parameters' => ['cooper'], 'uses' => 'SearchController#search']);
Route::get('/fletcher/{region}/{suburb?}', ['middleware' => 'shiftParameter', 'parameters' => ['fletcher'], 'uses' => 'SearchController#search']);
// middleware class to go in app/Http/Middleware
// generate with "php artisan make:middleware" statement and copy logic below
class ShiftParameterMiddleware {
public function handle($request, Closure $next) {
// get the route from the request
$route = $request->route();
// save off the current route parameters
$parameters = $route->parameters();
// unset the current route parameters
foreach ($parameters as $name => $parameter) {
$route->forgetParameter($name);
}
// build the new parameters to shift onto the array
// from the data passed to the middleware
$newParameters = [];
foreach ($this->getParameters($request) as $key => $value) {
$newParameters['customParameter' . $key] = $value;
}
// union the new parameters and the old parameters
$parameters = $newParameters + $parameters;
// loop through the new set of parameters to add them to the route
foreach ($parameters as $name => $parameter) {
$route->setParameter($name, $parameter);
}
return $next($request);
}
/**
* Method to get the data from the custom 'parameters' key added
* on the route definition.
*/
protected function getParameters($request) {
$actions = $request->route()->getAction();
return $actions['parameters'];
}
}
Now, with the filter (or middleware) setup and in use, the category will be passed into the controller method as the first parameter.
public function search($category, $region, $suburb = null) {
dd($category);
}

Pass get parameter to controler in Laravel

How do I pass a get variable to a controller in Laravel?
I have:
$languages = array('zh');
$locale = Request::segment(1);
if (in_array($locale, $languages)) {
App::setLocale($locale);
} else {
$locale = null;
}
Route::group(array('prefix' => $locale), function() {
...
Route::get('/search/{q}', array('as' => 'search', 'uses' => 'ProductsController#index'));
...
});
If I try to return q from within the controller using Input::get('q'); I get nothing.
Route::get('/search/{q}', array('as' => 'search', 'uses' => 'ProductsController#index'));
the {q} here isn't GET variable.
you can take the value like this.
public function index($q)
{
echo $q;
}
It's not a GET parameter but an URL parameter. There's a little difference in that.
Url paramters will be passed (in the order they appear) to the controller action.
So all you have to do, is use the argument that gets automatically passed to the function in the controller.
public function index($q){
echo $q;
}

Categories