Bind middleware to controller in laravel 5 - laravel

I want to use middleware in my controller , but I don't know route beforehand, as I take slug from my DB.
Is it possible in laravel 5?
Thank you in advance

Inside your controller's constructor, do the following:
public function __construct()
{
//This will apply to every method inside the controller
$this->middleware('auth');
//This will apply only to the methods listed inside the array
$this->middleware('log', ['only' => ['fooAction', 'barAction']]);
//This will apply only to the methods except the ones listed inside the array
$this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
}
You can read about that here

Related

laravel Controller error when using Request in function

I make controller by using php artisan make:controller newsController --resource
And after that when I go to my controller in function index, I want to add Request $request
public function index(Request $request)
{
}
It's return error:
Declaration of
App\Http\Controllers\Admin\NewsController::index(Illuminate\Http\Request
$request) should be compatible with
App\Http\Controllers\Controller::index()
How to fix it? I try many way but it still didn't work!
EDIT — Controller
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
UPDATED — Routes
Route::post('admin/news', 'Admin\NewsController#store');
Route::resource('admin/news', 'Admin\NewsController');
It's quite simple, just create your Resource controller without the index route Or Create new get route, like this:
Route::resource('admin/news', 'Admin\NewsController', ['except' => ['index']]);
Then add your route before the resource declaration, something like this:
Route::post('admin/news', 'Admin\NewsController#index');
Route::resource('admin/news', 'Admin\NewsController', ['except' => ['index']]);
Hope this helps you!!
This doesn't require any Laravel work arounds.
Fix:
a) Remove the index method from the base controller
or
b) Make the index method in the base controller take a Illuminate\Http\Request as an argument and use that same method signature in every controller's index method that inherited from the base in the entire application.
or
c) Figure out why there is an index method defined in the base in the first place and, if needed, move it to a trait to use in child classes instead. (allows you to override the method completely)
b is not a good option, it is just to illustrate a point
Issue demonstrated:
class Foo
{
public function index()
{
//
}
}
class Bar extends Foo
{
public function index(\Illuminate\Http\Request $request)
{
}
}
Declaration of Bar::index(Illuminate\Http\Request $request) should be compatible with Foo::index()
You want to override the index action.
You also want to pass parameters into this index action.
The App\Http\Controllers\Controller::index() does not take parameters.
So they are not "compatible".
Try this "helper-funtion" way:
public function index() {
$request = request() // use the helper function
// ...you code here...
}
You can disable index from resources and define route with different method name before or after resource:
Route::get('resources', 'ResourceController#getResources');
Route::resource('resources', 'ResourceController', $restResource)->except(['index']);

Laravel - middleware on routes in controller

I have a route resource
Route::resource('campaign', 'CampaignController');
I want to restrict some of these routes to the users.
For example the index page lists all the campaigns and they should not see this only their own ones.
I have a custom middleware that simply checks the if the user is an admin
However I cannot apply this to individual methods.
public function index()
{
$this->middleware('checkuser');
}
Just the constructor
public function __construct()
{
$this->middleware('checkuser');
}
How do I get around this and apply to individual route in the controller
Sorry my mistake I should have read the docs you can add exceptions or allowed.
$this->middleware('auth');
$this->middleware('log', ['only' => ['fooAction', 'barAction']]);
$this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
}

Passing two models to the Authorize middleware (also called can)

I am trying to pass two models to the Authorize middleware, used under the name can.
routes/api.php
Route::middleware('can:reach,profile,photo')->resource('users/{user}/profiles/{profile}/photos', 'PhotoController');
Then I try to retrieve arguments like so:
app/Policies/PhotoPolicy.php
public function reach(User $user, Profile $profile, Photo $photo)
{
return $profile->id === $photo->profile->id;
}
But the middleware is totally ignored. I checked the definition of the middleware and I cannot see why this would not work.
Thanks in advance.
I think you have to add the middleware to the resource, not the opposite. Or, you can create a group.
Example:
Route::group(['middleware' => 'can:reach,profile,photo'], function($router){
$router->resource('users/{user}/profiles/{profile}/photos', 'PhotoController');
});

How to bind a model to resource store method in Laravel 5.3

I am trying to assign a Product model for store route which is made by Route::resource method
public function store(Request $request, Product $product)
I already worked with Route Model Binding a little, and it works very nice with
public function show(Product $product)
But I can't force a store method to use Product model.
Ok, since somebody marked this question as favourite I will explain what I did to make it work
This is how we declare our routes, we need to place out specific route before Route::resource call
Route::post('foo/{baz}', [
'as' => 'foo.store',
'uses' => 'FooController#store']
);
Route::resource('foo', 'FooController');
Our Foo controller store method:
public function store(Baz $baz, Request $request){
}
The $baz variable is just passed after url slash in form action url. it can be like that
<form action="foo/5">
Keep in mind that "foo&baz=5" won't work
For some reason I didn't have to, or at least didn't try to bind a Foo model with controller - it just works.
The order of routes and parameters in controller method if important for PHP reflection

Laravel 5 Authentication: make Controller decides which methods are public

This is a very long question for (I think) a very simple answer, but I am a total newbie in Laravel and I need to know if I am addressing it the right way.
What I did
I followed the Intermediate Tutorial and modified it just a little bit, and now I have a simple task list that uses authentication. I had this in my TaskController constructor:
public function __construct(TaskRepository $tasks)
{
$this->middleware('auth');
}
This checks if the user is logged in before launching any methods, so I just need to call them like this in my routes file:
Route::get('/home', 'TaskController#index');
Route::get('/tasks', 'TaskController#indexUser');
Then I wanted to remove the authentication requirement for the index method, so that all users can see the /home page (where I list all the tasks), and only authenticated users can see the /tasks page (where I list only the user tasks and allow to delete them). I managed to do it like this:
1) I removed $this->middleware('auth') from the TaskController constructor
2) I modified my routes file to look like this:
Route::get('/home', 'TaskController#index');
Route::get('/tasks', [
'middleware' => 'auth',
'uses' => 'TaskController#indexUser'
]);
Ok, this works, but:
What I want to achieve
I don't want to have this logic in my routes file, I want that my Controller decides which methods are public and which not. But I got stuck. I think it should be something like this:
class TaskController extends Controller
{
/**
* Display a list of all current tasks
*/
public function index()
{
return view('tasks.index', [
'tasks' => Task::orderBy('created_at', 'asc')->get()
]);
}
/**
* Display a list of all of the logged user's task.
*
*/
public function indexUser(Request $request)
{
if (Auth::check() {
return view('tasks.index_user', [
'tasks' => $this->tasks->forUser($request->user()),
]);
} else {
//This is what I don't know how to do:
redirect_to_login
}
}
}
How can I achieve this?
You can decide which controller method should execute the middleware:
public function __construct()
{
$this->middleware('auth', ['only' => ['indexUser', 'update'] ];
}
just add in only the method you want to protect.
When a user try to access a method will automatically redirect to the login page.
Here you can find the documentation: https://laravel.com/docs/5.1/controllers#controller-middleware
You can do the following if you want this logic in your controller:
if (!Auth::check()) {
return redirect('/path/to/login/page');
}
This way you don't have giant if else statement in your controller. (Handy if your controller contains more logic then the sample above)
I personally would go for the answer Christian Giupponi provided. Cause it makes much more sense to handle this logic in the construct function then in your controller.

Resources