How to use multiple method in single route in laravel - laravel

I want to use more than one method in a single route using laravel. I'm try this way but when i dd() it's show the plan string.
Route::get('/user',[
'uses' => 'AppController#user',
'as' => 'useraccess',
'roles'=> 'HomeController#useroles',
]);
When i dd() 'roles' option it's show the plan string like this.
"roles" => "HomeController#useroles"
my middleware check the role this way.
$actions=$request->route()->getAction();
$roles=isset($actions['roles'])? $actions['roles'] : null;

The simplest way to accept multiple HTTP methods in a single route is to use the match method, like so:
Route::match(['get', 'post'], '/user', [
'uses' => 'AppController#user',
'as' => 'useraccess',
'roles'=> 'HomeController#useroles',
]);
As for your middleware, to check the HTTP request type, a tidier way would be:
$method = request()->method();
And if you need to check for a specific method:
if (request()->isMethod('post')) {
// do stuff for post methods
}

Here's how you can do multiple methods on a single route:
Route::get('/route', 'RouteController#index');
Route::post('/route', 'RouteController#create');
Route::put('/route', 'RouteController#update');
/* Would be easier to use
* Route::put('/route/{route}', 'RouteController#update');
* Since Laravel gives you the Model of the primary key you've passed
* in to the route.
*/
Route::delete('/route', 'RouteController#destroy');
If you've written your own middleware, you can wrap the routes in a Route::group and apply your middleware to those routes, or individual routes respectively.
Route::middleware(['myMiddleware'])->group(function () {
Route::get('/route', 'RouteController#index');
Route::post('/route', 'RouteController#create');
Route::put('/route', 'RouteController#update');
});
Or
Route::group(['middleware' => 'myMiddleware'], function() {
Route::get('/route', 'RouteController#index');
Route::post('/route', 'RouteController#create');
Route::put('/route', 'RouteController#update');
});
Whichever is easier for you to read.
https://laravel.com/docs/5.6/routing#route-groups

Related

Pass function variable INSIDE route declaration

Let's say I have a function in my controller which retrieves users looking something like this:
public function index($category) {
// retrieve users depending on category or all
}
Now is there a way to make named routes to include the function parameter like so:
Route::get('passengers', 'Controller#index(1)')->name('passengers');
Route::get('attendees', 'Controller#index(2)')->name('attendees');
This way they can all use the same function
No you can not pass a parameter the action name, and there is a problem in you routing logic :
Route::get('/{categoryName}', 'Controller#index')->name('index');
And in the controller you will for example get the category by name like this :
public function index($categoryName) {
$category = Category::where('name', $categoryName)->first();
// use $ category as you please ;)
}
In the blade :
route('index', ['categoryName' => $category->name])
If the named route defines parameters, you may pass the parameters as the second argument to the route function. The given parameters will automatically be inserted into the URL in their correct positions
https://laravel.com/docs/5.5/routing#named-routes
So, use route() helper like this:
route('passengers', ['category' => 1])
Then you need to add {category} to the route. Also, it's really better to use show() instead of index() here. So, your route will look like this:
Route::get('passengers/{category}', ['as' => 'passengers', 'uses' => 'Controller#show']);
Yes, you can define the param in the url like so:
Route::get('passengers/{yourParam}', 'Controller#index')->name('passengers');
View in docs
Route::get( '{category}', [ 'as' => 'users', 'uses' => 'Controller#index' ]);
Remember to add this route at the end of your routes file in order to not to collide with any other route.
Now in your controller
use Illuminate\Http\Request;
public function index(Request $request)
{
$category = $request->query('category');
// $category will be passengers, attendees, etc
}
Your routes will be
/passengers can be accessed as route('users', ['category' => 'passengers'])
/attendees can be accessed as `route('users', ['category' => 'attendees'])

Laravel optional prefix routes with regexp

Is there a way to create routes with prefixes so I can have routes like this
/articles.html -> goes to listing Controller in default language
/en/articles.html -> goes to the same controller
/fr/articles.html -> goes to the same controller
My current problem is that by doing:
Route::group(['prefix=>'/{$lang?}/',function(){});
a route like this: /authors/author-100.html will match a prefix 'authors` , and for sure there is no language called "authors".
I use laravel 5.5
There doesn't seem to be any good way to have optional prefixes as the group prefix approach with an "optional" regex marker doesn't work. However it is possible to declare a Closure with all your routes and add that once with the prefix and once without:
$optionalLanguageRoutes = function() {
// add routes here
}
// Add routes with lang-prefix
Route::group(
['prefix' => '/{lang}/', 'where' => ['lang' => 'fr|en']],
$optionalLanguageRoutes
);
// Add routes without prefix
$optionalLanguageRoutes();
This should be sufficient using the where Regex match on the optional route parameter:
Route::get('/{lang?}, 'SameController#doMagic')->where('lang', 'en|fr');
You can do the same on Route Group as well, else having all the options as in this answer evidently works.
An update to show the use of prefix:
Route::group(['prefix' => '{lang?}', 'where' => ['lang' => 'en|fr']],function (){
Route::get('', 'SameController#doNinja');
});
As far as I am concerned this should be sufficient even when there is no lang as well as when there is one, just maybe this group could come before other routes.
You can use a table to define the accepted languages and then:
Route::group([
'prefix' => '/{lang?}',
'where' => ['lang' => 'exists:languages,short_name'],
], function() {
// Define Routes Here
});
Another working solution would be to create an array of langs and loop over it:
$langs = ['en', 'fr', ''];
foreach($langs as $lang) {
Route::get($lang . "/articles", "SomeController#someMethod");
}
For sure this makes your route file less readable, however you may use php artisan route:list to clearly list your routes.

Unused parameters in routes Laravel 5.1

I write api for mobile, since I have more than one version, I don't want to copy-paste the same routes, hence I decided to do something like this:
Route::model('callRequestNote', CallRequestNote::class);
Route::group([
'prefix' => 'api/v{version}/mobile',
'where' => ['version' => '[1|2]'],
], function () {
Route::delete('/notes/{callRequestNote}', MobileNotesController::class . '#destroy');
// other duplicated routes
});
public function destroy($version, CallRequestNote $callRequestNote)
{
//
}
I use version parameter only in BeforeMiddleware, hence I don't need it in controller. My question is how to replace those parameters and make CallRequestNote as a first argument and get rid of $version?

Redirect to current URL while changing a query parameter in Laravel

Is there a built-in way to do something like this?
Let's say I have a search-page that has a few parameters in the URL:
example.com/search?term=foo&type=user
A link on that page would redirect to an URL where type is link. I'm looking for a method to do this without manually constructing the URL.
Edit:
I could build the URL manually like so:
$qs = http_build_query(array(
'term' => Input::get('term'),
'type' => Input::get('type')
));
$url = URL::to('search?'.$qs);
However, what I wanted to know is if there is a nicer, built-in way of doing this in Laravel, because the code gets messier when I want to change one of those values.
Giving the URL generator a second argument ($parameters) adds them to the URL as segments, not in the query string.
You can use the URL Generator to accomplish this. Assuming that search is a named route:
$queryToAdd = array('type' => 'user');
$currentQuery = Input::query();
// Merge our new query parameters into the current query string
$query = array_merge($queryToAdd, $currentQuery);
// Redirect to our route with the new query string
return Redirect::route('search', $query);
Laravel will take the positional parameters out of the passed array (which doesn't seem to apply to this scenario), and append the rest as a query string to the generated URL.
See: URLGenerator::route(),
URLGenerator::replaceRouteParameters()
URLGenerator::getRouteQueryString()
I prefer native PHP array merging to override some parameters:
['type' => 'link'] + \Request::all()
To add or override the type parameter and remove another the term:
['type' => 'link'] + \Request::except('term')
Usage when generating routes:
route('movie::category.show', ['type' => 'link'] + \Request::all())
You can do it with Laravel's URLGenerator
URL::route('search', array(
'term' => Input::get('term'),
'link' => Input::get('type')
));
Edit: be sure to name the route in your routes.php file:
Route::get('search', array('as' => 'search'));
That will work even if you're using a Route::controller()
From Laravel documentation:
if your route has parameters, you may pass them as the second argument
to the route method.
In this case, for return an URI like example.com/search?term=foo&type=user, you can use redirect function like this:
return redirect()->route('search', ['term' => 'foo', 'type' => 'user']);
Yes, there is a built in way. You can do your manipulation in Middleware.
The $request passed to the handle method of all middleware has a query property. As an InputBag, it comes with a few methods; Namely, for your intentions: ->set().
Pretty self explanatory, but here's an example:
public function handle(Request $request, Closure $next)
{
$request->query->set('term','new-value');
// now you pass the request (with the manipulated query) down the pipeline.
return $next($request);
}
The Input component should also contain query parameters.
i.e Input::get('foo');

Laravel, Routing Wildcards to filter and then controller

I am trying to capture a wildcard from URL and then first pass it to a filter then route to controller. I am not sure how to plot the question exactly but here is what I've tried so far.
Route::get('test/(:any?)', array('as' => 'testroute', 'uses' => 'test#result', 'before' => "test_filter:$1"));
Route::filter('test_filter', function($id = NULL)
{
if($id)
echo "This id is " . $id; // Prints "This id is $1"
});
and
Route::get('test/(:any?)', array('as' => 'testroute', function($id = NULL)
{
if($id)
echo "this id is " . $id; // Does not do anything
}, 'uses' => 'test#result'));
Basically, I want to check if there is an id appended to the URL and set a cookie if there is one. But regardless of the case, I want this route to be handled by a controller no matter if there is any id appended or not.
I have to do the same thing with so many routes so I'd prefer something like a filter rather than modifying the controller's codes.
I know that I can directly pass the wildcard element to a closure, or I can feed this as a parameter to any controller but in that case I'll have to modify the controller codes, which I can't at the moment.
Can I do it through filters ? or any other way in which i wont have to modify the controller codes ?
Try passing an anonymous right after the before
Route::get('test/(:any?)',
array(
'as' => 'testroute',
'uses' => 'test#result',
'before' => "test_filter",
function($my_cookie_value)
{
// Set cookie here
}
)
);
Taken from here
I'd use a middleware http://laravel.com/docs/5.1/middleware (or filter for older Laravel versions) and add the route/s into a group which has the middleware as you can see in here http://laravel.com/docs/5.1/routing#route-group-middleware.
The middleware will be executed before the route code, where you can add a logic to manage your cookie.

Resources