as the title says I want to use a middleware inside a controller function. I have resource controllers, which their functions inside will have different access rights so I can't use a middleware in the web.php file, I have to use or apply it separately in each function to limit access, my googling hasn't been successful in getting a solution to that so far. Any help please and thanks in advance.
P.S. I believe no code is necessary here.
Middleware could also be applied to just one function, just add the method name in your controller constructor
public function __construct()
{
// Middleware only applied to these methods
$this->middleware('loggedIn', [
'only' => [
'update' // Could add bunch of more methods too
]
]);
}
OR
public function __construct()
{
// Middleware only applied to these methods
$this->middleware('loggedIn')->only([
'update' // Could add bunch of more methods too
]);
}
Here's the documentation
There are 3 ways to use a middleware inside a controller:
1) Protect all functions:
public function __construct()
{
$this->middleware('auth');
}
2) Protect only some functions:
public function __construct()
{
$this->middleware('auth')->only(['functionName1', 'functionName2']);
}
3) Protect all functions except some:
public function __construct()
{
$this->middleware('auth')->except(['functionName1', 'functionName2']);
}
Here you can find all the documentation about this topic: Controllers
I hope this can be helpful, regards!
Use the following code inside your controller constructor. The following code will use the auth middleware:
public function __construct() {
$this->middleware('auth');
}
Also you can simply add middleware at your routes. For example I need to add middleware for my method "registration_fee()" inside "RegisterController", so it will looks like this:
Route::get('/pay_register_fee', 'Auth\RegisterController#registration_fee')
->name('pay_register_fee')->middleware(['guest', Register::class, RegistrationFee::class]);
"RegistrationFee" is middleware that I want to add.
P.S. Not forget import class or write full path to middleware.
Related
I have been declaring all the routes for my application inside web.php , but it is now getting quite large. I find that I am losing a lot of time shifting between web.php and each controller and this is hurting productivity.
I feel like it would be better to define routes inside of the controller, perhaps ideally delegating some URL to a controller and then allowing the controller to handle the "sub routes" since this would allow me to use inheritance when I have two similar controllers with similar routes.
It is not possible given how laravel works. Every request is passed onto router to find its designated spot viz. the controller with the method. If it fails to find the route within the router, it just throws the exception. So the request never reaches any controller if the route is not found. It was possible in earlier versions on Symphony where you would configure the route in the comment of a particular controller method.
Sadly with laravel it works how it works.
But for me, I just like to have the routes in a separate file.
Alternate solution, easier way to sort all the routes.
You can move your route registration into controllers if you use static methods for this. The code below is checked in Laravel 7
In web.php
use App\Http\Controllers\MyController;
.....
MyController::registerRoutes('myprefix');
In MyController.php
(I use here additional static methods from the ancestor controller also posted below)
use Illuminate\Support\Facades\Route;
.....
class MyController extends Controller {
......
static public function registerRoutes($prefix)
{
Route::group(['prefix' => $prefix], function () {
Route::any("/foo/{$id}", self::selfRouteName("fooAction"));
Route::resource($prefix, self::selfQualifiedPath());
}
public function fooAction($id)
{
........
}
In Controller.php
class Controller extends BaseController {
....
protected static function selfAction($actionName, $parameters = [], $absolute = false)
{
return action([static::class, $actionName], $parameters, $absolute);
}
protected static function selfQualifiedPath()
{
return "\\".static::class;
}
protected static function selfRouteName($actionName)
{
//classic string syntax return "\\".static::class."#".$actionName;
// using tuple syntax for clarity
return [static::class, $actionName];
}
}
selfAction mentioned here is not related to your question, but mentioned just because it allows making correct urls for actions either by controller itself or any class using it. This approach helps making action-related activity closer to the controller and avoiding manual url-making. I even prefer making specific functions per action, so for example for fooAction
static public function fooActionUrl($id)
{
return self::selfAction('foo', ['id' => $id]);
}
Passing prefix into registerRoutes makes controller even portable in a sense, so allows inserting it into another site with a different prefix in case of conflict
I am using api throttle in my routes/api.php (as you can see in the code) but I am wondering if I can use it in the controller on methods.
Route::resource('/user/{user}/post', 'UserPostController')->middleware(['auth:api', 'throttle:5,1']);
Better to use the routes to specify the middleware for the routes. Still you think to use / specify inside your controller you can define __construct() menthod in your controller like:
public function __construct()
{
$this->middleware('throttle:5,1')->only('index');
}
This will work on the index action of your controller only.
For more details check the documentation Controller Middlewares
you can override route for example
Route::resource('/user/{user}/post', 'UserPostController')->middleware(['auth:api', 'throttle:5,1']);
//add route after resource
Route::get('/user/create', 'UserPostController#create')->middleware(['auth:api', 'throttle:5,1']);
second way add condition in controller
public function __construct()
{
$this->middleware('auth:api');
$this->middleware('throttle:10,1')->only('create');
}
I have laravel 5.6 project
and I have registered middleware called permissions. I need to assign this middleware in a controller, but not for the whole controller- just for one function without using __construct().
I mean I want to assign this in:
public function index()
{
$this->middleware('permission');
}
I've tried it like this, but its not working. It's worked when I use it inside:
public function __construct()
{
$this->middleware('permission');
}
But I don't need it like that.
Thanks.
Middleware can only be registered in the constructor. You can use the only() method though, like:
function __construct()
{
$this->middleware('permission')->only('index');
}
I believe you can pass an array of middlewares as well. There's also the except() method that does the opposite.
Here is your solution:
public function __construct()
{
$this->middleware('permission')->only('index');
}
I have a few things that I want to present on every page, like $gameAccounts = Auth::user()->gameAccounts()->get();
What would be the best approach to present this variable globally, on each page?
If you need it only for the views you can use a view composer in your AppServiceProvider
public function boot()
{
View::composer('layouts.base', function ($view) {
$view->with('gameAccounts', Auth::user()->gameAccounts);
});
}
If you need it globally you can store it in a config also in AppServiceProvider.
For shared functionality I would recommend to write a trait. The trait can be used throughout your controllers and provide the same functionality for all.
Example:
trait GameSettingsTrait
{
public function getUserGameAccounts()
{
return Auth::user()->gameAccounts()->get();
}
}
In your controller do:
class IndexController extends Controller
{
use GameSettingsTrait;
...
Another approach would be to put the logic in the base controller in app/Http/Controllers/Controller.php. Btw, there you can see that it already uses traits for other functionality.
You need to use view composer.
Look at the doc.
https://laravel.com/docs/5.2/views#view-composers
Use view composer is a best way to do this.
Just add this rows to your AppServiceProvider.php inside boot method:
public function boot()
{
//
view()->composer('*', function ($view) {
$view->with('user', Auth::user()->gameAccounts()->get());
});
}
I'm wondering how I can set up middleware using a controller constructor and also reference middleware parameters as I've done successfully in my routes file.
I have this working fine in routes.php:
Route::group(['middleware' => 'user-type:user'], function () {
// routes
});
Now I want to do this within a controller constructor, but I'm getting some issues...
public function __construct()
{
$this->middleware = 'event-is-active:voting';
}
And when I visit a link with the above applied I get the following error:
ErrorException in ControllerDispatcher.php line 127:
Invalid argument supplied for foreach()
Of course I'm doing this wrong - I couldn't see how to do it in the docs and reading the source didn't help, but perhaps I overlooked something. So I'm wondering what is the right way and is it even possible? Any help would be most appreciated, thanks!
You are using wrong syntax for setting middleware from controller constructor.
First of all you have to use laravel 5.1 to use middleware parameter.
Now you can set middleware in controller in constructor only.
Like
function __construct()
{
$this->middleware('event-is-active:voting');//this will applies to all methods of your controller
$this->middleware('event-is-active:voting', ['only' => ['show', 'update']]);//this will applies only show,update methods of your controller
}
Please note that in above code show and update are the example name. you have to write actual name which you are using in your controller.
Let say you are using
1. getShowUser($userId)
2. postUpdateUser($userId)
than you have to apply middleware in these methods as mentioned below:
function __construct()
{
$this->middleware('event-is-active:voting', ['only' => ['getShowUser', 'postUpdateUser']]);
}
Try this
function __construct()
{
$this->middleware('user-type:param1,param2', ['only' => ['show', 'update']]);
}