Laravel5 passing route args as middleware args - php

I would like the route argument to be passed as a middleware argument, something like this
Route::get('foo/{id}', ['middleware' => 'bar:{id}', function(){
});
How to do this?

You can get it from the request variable:
Route::get('foo/{id}', ['middleware' => 'bar', function(){
});
public function handle($request, Closure $next) {
$id = $request->id;
}
https://laracasts.com/discuss/channels/general-discussion/how-to-get-url-parameters-at-middleware?page=1
The
bar:id
is used when you want to pass the string id to the middleware.

If you set the middleware up in the controller's constructor, it's possible to pass dynamic middleware variables.
public function __construct()
{
$this->middleware('bar:'.request()->id);
}

Related

How can you create wildcard routes on Lumen?

Let's say I have a controller called TeamsController. Controller has following method, that returns all teams user has access to.
public function findAll(Request $request): JsonResponse
{
//...
}
Then I have bunch of other controllers with the same method. I would like to create a single route, that would work for all controllers, so I would not need to add a line for each controller every time I create a new controller.
I am unable to catch the controller name from URI. This is what I have tried.
$router->group(['middleware' => 'jwt.auth'], function () use ($router) {
// This works
//$router->get('teams', 'TeamsController#findAll');
// This just returns TeamsController#findAll string as a response
$router->get('{resource}', function ($resource) {
return ucfirst($resource) . 'Controller#findAll';
});
});
You return a string instead of calling a controller action:
I believe Laravel loads the controllers this way (not tested)
$router->group(['middleware' => 'jwt.auth'], function () use ($router) {
$router->get('{resource}', function ($resource) {
$app = app();
$controller = $app->make('\App\Http\Controllers\'. ucfirst($resource) . 'Controller');
return $controller->callAction('findAll', $parameters = array());
});
});
But again, I don't really think it's a good idea.

How to pass URL parameter from route to middleware?

If I have middleware like:
<?php namespace App\Http\Middleware;
class SomeMiddleware
{
public function handle($request, Closure $next, $id = null)
{
//
}
}
In kernel.php:
'someMiddleware' => \App\Http\Middleware\SomeMiddleware::class,
In routes.php :
Route::put('post/{id}', ['middleware' => 'someMiddleware']);
How I can pass id captured in {id} to my middleware?
I know that I can pass some custom parameter like this:
Route::put('post/{id}', ['middleware' => 'someMiddleware:16']);
But in laravel documentation there is no described how to pass argument captured in route pattern.
I think that you can get the parameter from inside the middleware like this:
//your middleware's method
public function handle($request, Closure $next)
{
//get the ID
$id = $request->id
}

Laravel use route parameter in middleware

Couldn't find anything that specifically matches my situation. I have a route group defined as:
Route::group(['prefix' => 'api/v1/{access_token}'], function(){
...
}
The above group has several resource routes inside. I am trying to create a custom middleware that will validate the access_token parameter and return a 400 response if the parameter is not valid. I would like to be able to so something like this in my controllers:
class ProductController extends Controller {
/**
* Instantiate a new ProductController
*/
public function __construct()
{
$this->middleware('verifyAccessToken');
}
...
}
My question is not "how do I define custom middleware", but rather, how can I gain access to the access_token parameter from within the handle function of my custom middleware?
EDIT: While the question suggested as a duplicate is similar and has an answer, that answer seems to be outdated and/or unsatisfactory for what I am trying to accomplish.
You can just access it from your $request object using the magic __get method like this:
public function handle($request, Closure $next)
{
$token = $request->access_token;
// Do something with $token
}
http://laravel.com/docs/master/middleware#middleware-parameters
For simple
public function yourmethod($access_token){
$this->middleware('verifyAccessToken', $access_token);
}
I think you can't do it in __construct() method.
Just stick the middleware on the Route::group
Route::group(['prefix' => 'api/v1/{access_token}', 'middleware' => 'verifyAccessToken'], function(){
});
Then in your middleware, as Thomas Kim pointed out, you can use the $request object to gain access to the token that was passed to the route.
public function handle($request, Closure $next)
{
$token = $request->access_token;
// Do something with $token
}

Laravel 5: Middleware before & after into routes

I have two Middlewares: beforeCache & afterCache, boths registered on Kernel.
I want to call them into routes in this order:
1. beforeCache
2. myController
3. afterCache
If I define a route like this:
Route::get('especies/{id}', [
'middleware' => 'beforeCache',
'uses' => 'MyController#myMethod',
'middleware' => 'afterCache',
]);
beforeCache don't executes because afterCache is redefining the same array key middleware.
How should I do that? Thanks!
I'll assume you're using 5.1 in this, but what you're doing is essentially trying to define an array of attributes on the route. The brackets [] are just a shorthand version of saying array(...).
From the documentation (http://laravel.com/docs/5.1/middleware#defining-middleware) specifically the Before / After Middleware you simply just need to return a certain way.
For Before middlewares you do your code and return the next request after your code executes.
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
For After middleware you handle the rest of the request and then your code executes and finally return the response.
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
The route would end up looking like this,
Route::get('especies/{id}',[
'middleware' => [
'beforeCache',
'afterCache'
],
'uses' => 'MyController#myMethod'
]);
class BeforeMiddleware implements Middleware {
public function handle($request, Closure $next)
{
// Do Stuff
return $next($request);
}
}
class AfterMiddleware implements Middleware {
public function handle($request, Closure $next)
{
$response = $next($request);
// Do stuff
return $response;
}
}
1-The before middleware operates and then passes on the request.
2-The after middleware allows the request to be processed, and then operates on it

How to do restful ajax routes to methods in Laravel 5?

So I have a route that looks like this:
Route::any('some/page', ['as' => 'some-page', 'uses' => 'SomePageController#index']);
However, I also have ajax calls at the same URL (using a request parameter called ajax like: some/page/?ajax=my_action) that I want to hit methods on my controller:
index already routes: 'SomePageController#index'
ajax = my_action needs to route: 'SomePageController#ajaxMyAction'
ajax = my_other_action needs to route: 'SomePageController#ajaxMyOtherAction'
ajax = blah_blah needs to route: 'SomePageController#ajaxBlahBlah
...
What's the elegant solution to setting this up in my routes.php file?
After inspection of Laravel's Http Request and Route classes, I found the route() and setAction() methods could be useful.
So I created a middleware to handle this:
<?php namespace App\Http\Middleware;
class Ajax {
public function handle($request, Closure $next)
{
// Looks for the value of request parameter called "ajax"
// to determine controller's method call
if ($request->ajax()) {
$routeAction = $request->route()->getAction();
$ajaxValue = studly_case($request->input("ajax"));
$routeAction['uses'] = str_replace("#index", "#ajax".$ajaxValue, $routeAction['uses']);
$routeAction['controller'] = str_replace("#index", "#ajax".$ajaxValue, $routeAction['controller']);
$request->route()->setAction($routeAction);
}
return $next($request);
}
}
Now my route looks like:
Route::any('some/page/', ['as' => 'some-page', 'middleware'=>'ajax', 'uses' => 'SomePageController#index']);
And correctly hits my controller methods (without disturbing Laravel's normal flow):
<?php namespace App\Http\Controllers;
class SomePageController extends Controller {
public function index()
{
return view('some.page.index');
}
public function ajaxMyAction(Requests\SomeFormRequest $request){
die('Do my action here!');
}
public function ajaxMyOtherAction(Requests\SomeFormRequest $request){
die('Do my other action here!');
}
...
I think this is a fairly clean solution.
You can't make this dispatch in the routing layer if you keep the same URL. You have two options :
Use different routes for your AJAX calls. For example, you can prefix all your ajax calls by /api. This is a common way :
Route::group(['prefix' => 'api'], function()
{
Route::get('items', function()
{
//
});
});
If the only different thing is your response format. You can use a condition in your controller. Laravel provides methods for that, for example :
public function index()
{
$items = ...;
if (Request::ajax()) {
return Response::json($items);
} else {
return View::make('items.index');
}
}
You can read this http://laravel.com/api/5.0/Illuminate/Http/Request.html#method_ajax and this http://laravel.com/docs/5.0/routing#route-groups if you want more details.

Categories