Laravel dynamic controller middleware - laravel

Hi so I have some routes that are saved in the database each of these has its own controller with its middleware and it is routed via this route;
Route::get('{any}', 'RoutingController#index')->where('any', '.*');
and I try to create the new controller as follows;
$container = app();
$route = $container->make(\Illuminate\Routing\Route::class);
$controllerInstance = $container->make($controller);
return (new ControllerDispatcher($container))->dispatch($route, $controllerInstance, $action);
So my HomeController has a middleware here;
public function __construct()
{
$this->middleware('guest');
}
However this doesn't get honoured as I'm guessing its not a new request. Is there any way I can honour this middleware?

The controller dispatcher is not what you want because the middleware is a layer above the controller. You need to run the entire route:
In your RoutingController
public function index() {
//Override your route with what it really needs to do
$route = Route::get(
{any},
'\App\Http\Controllers\HomeController#index'
)->where('any', '.*');
//Re-handle the request. It should hit your new route.
app()->make(\Illuminate\Contracts\Http\Kernel::class)->handle(request());
}
The idea is you overwrite your general route with what it needs to do based on the request. This should only affect a single request.

Related

How to get User()->id in Controllers (Laravel 8+)

I am trying to select tasks by user('id'), but I can't get it in a Controller, where I selecting data from DB.
I have tried many thing and some of them from stackoverflow, but it isn't working.
I tried:
1. $userId = Auth::check() ? Auth::id() : true;
2. Auth::user()->id;
3. public function getUserId(){
on Model} - and then get this value on Controllers
and some other things
I have the simplest code:
I installed registration: npm artisan ui --auth something like that
I installed vuejs (on Laravel)
I created api on Laravel, and some logic on vue
I didn't touch "app.blade.php" it's the same as it was.
I can get data, user: name, id and all what I want in file "app.blade.php" but I need those data in folder->file: App\Http\Controllers{{SomeController}}, but I don't know how.
Was someone in this situation?
How can I get user id in Controllers?
Thanks guys for earlier.
If you need user id, just use one of this :
auth()->id();
using Auth facade's
\Auth::id();
or, using Request instance
$request->user()->id
Follow this simple controller code, i showed 3 different way here :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class SomeController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function getUserId(Request $request)
{
$user = Auth::user(); // Retrieve the currently authenticated user...
$id = Auth::id(); // Retrieve the currently authenticated user's ID...
$user = $request->user(); // returns an instance of the authenticated user...
$id = $request->user()->id; // Retrieve the currently authenticated user's ID...
$user = auth()->user(); // Retrieve the currently authenticated user...
$id = auth()->id(); // Retrieve the currently authenticated user's ID...
}
}
Auth::user()->id;
This should work if you have Auth middleware on that controller method where you try to get it, please check do you added that middleware.
For checking you can use php arisan route:list command.
Is someone still searching an answer on this question. I have some explanation how can you do this.
Laravel has a Router which routes authorization process through that Controller which you want, so you should redirect that process on your Router and in Controller create constructor which allows you to take user id.
How can you do that?:
1. First of all you should find Controller and Route which responsible for authorization and registration users.
In my case it was:
a)App\Http\Controllers\HomeController
b)routes\web.php
2. Second, you should redirect your authorization Router to the Controller where you trying to get Auth::id();
In my case it was:
App\Http\Controllers\TasksController
so, in routes\web.php I did this:
//was
Route::get('/', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
//was
Auth::routes();
//was
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
//added
Auth::routes();
//added
Route::get('/home', [App\Http\Controllers\TasksController::class, 'index'])->name('home');
perhaps you should have index function on that controller
3. Third you should add constructor in your controller where you want to get user id, this constructor I took from HomeController, it already was there.
In my case it was:
public function __construct()
{
$this->middleware('auth');
}
code with function on my TasksController:
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$userId = Auth::check() ? Auth::id() : true;
}
And now I can take user id.
PS: constructor I added on the top in class TasksController in Controller

JWT Auth doesn't work when __construct method in controller

In a Laravel Application, the JWT middleware doesn't work properly. I found out, that there is no auth check, when the controller has a __construct method.
class ProjectController extends Controller
{
public $company;
public $user;
public function __construct(Request $request)
{
$this->company = $request->user()->company;
$this->user = $request->user();
}
Api routes:
Route::group(['middleware' => 'jwt.auth'], function () {
Route::resource('/projects', 'Project\\ProjectController');
});
When i comment the __construct method, the system return a 401 as expected. But if the __construct method is not commented, the system returns a 500 because the company can not be found.
Why the __construct method doesn't work with jwt?
This has nothing to do with the jwt middleware, this is intended behavior from laravel, you can read more about it here.
Laravel collects all route specific middlewares first before running
the request through the pipeline, and while collecting the controller
middleware an instance of the controller is created, thus the
constructor is called, however at this point the request isn’t ready
yet.
You can find Taylor's reasoning behind it here:
It’s very bad to use session or auth in your constructor as no request
has happened yet and session and auth are INHERENTLY tied to an HTTP
request. You should receive this request in an actual controller
method which you can call multiple times with multiple different
requests. By forcing your controller to resolve session or auth
information in the constructor you are now forcing your entire
controller to ignore the actual incoming request which can cause
significant problems when testing, etc.
So the solution would be to get the user and company from the request in each controller method, but if you want to keep it in the constructor you could implement the following workaround:
class ProjectController extends Controller
{
public $company;
public $user;
public function __construct(Request $request)
{
$this->middleware(function ($request, $next) {
$this->company = $request->user()->company;
$this->user = $request->user();
return $next($request);
});
}
}

Auth::user() is null in new route

i'm using laravel 6 and have 2 route in my app; index and dashboard.
My routes/web is:
Auth::routes();
Route::middleware(['auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
i added dashboard route recently.
Auth::user() is null when i dump it in dashboard route but doesn't in index. What's the
Your Controller is instantiated before the middleware stack has ran; this is how Laravel can know what middleware you have set via the constructor. Because of this you will not have access to the authenticated user or sessions at this point. Ex:
public function __construct()
{
$this->user = Auth::user(); // will always be null
}
If you need to assign such a variable or access this type of information you would need to use a controller middleware which will run in the stack after the StartSession middleware:
public function __construct()
{
$this->middleware(function ($request, $next) {
// this is getting executed later after the other middleware has ran
$this->user = Auth::user();
return $next($request);
});
}
When the dashboard method is called, the middleware stack has already passed the Request all the way through to the end of the stack so all the middleware needed for Auth to be functioning and available has already ran at that point which is why you have access to Auth::user() there.
I think that this has something to do with the 'web' middleware. If you take a look into the Kernel.php (In app\Http) you will find the web middleware group.
This will show you that it actually calls a middleware called StartSession. Based on your route file (where web is not included as a middleware) I would think that you don't have a session in your Controller and there for no access to it.
I don't quite understand why this only happens in your /dashboard route, because the issue should also be in your /index route (unless you added the web middleware somewhere in your TodoController).
I think that this should do the trick:
Route::middleware(['web', 'auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
If you fire php artisan make:auth command.
It's doesn't matter where you define because of it's only define auth route
Route::middleware(['auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
Auth::routes();

Setting the route parameter in the middleware in Laravel

I am developing a Laravel application. I am doing route model binding in the middleware.
I have the routes like this
Route::group([ 'prefix' => 'department/{department}', 'middleware' => [ 'auth.department' ] ], function () {
Route::post('employee/create', 'EmployeeController#store')->name('employees.store');
});
This is my auth.department middleware (AuthDepartment)
class AuthDepartment
{
public function handle($request, Closure $next)
{
$department = Department::find($request->department);
//do something with the department
//I want to set the $department (Department model) in the place of {department} in the route.
return $next($request);
}
}
This is EmployeeController
class EmployeeController extends Controller {
public function store($department)
{
}
}
As you can see in the code, I am using $department parameter to get the department id from the route. But instead of getting the integer as the parameter, I want to bind the model like this.
class EmployeeController extends Controller {
public function store(Department $department)
{
}
}
With my current code, it is not working. I tried to set the route parameter in the middleware as follow to match (bind model) the value in the action.
$request->route()->setParameter('department', $department)
But it is just not working. How can I set/ replace the route parameter with a model in the middleware which can be binded to the parameter in the action of the controller? Is it possible? What could be the better approach?
If I used
$request->route()->setParameter('department', $department)
to set the parameter, I cannot set type in the action of the controller like this.
store(Department $department)
But this is fine
store(Department $department)
But I want this
store(Department $department)
Laravel already has this built in. It is called Route Model Binding.
https://laravel.com/docs/5.7/routing#route-model-binding
Remove the middleware and instead keep your controller as it is. Laravel will automatically use the ID in the request to find the model and give you an instance of it. If the model cannot be found, Laravel will throw a 404 response for you.

Passing page URL parameter to controller in Laravel 5.2

In my application I have a page it called index.blade, with route /index. In its URL, it has some get parameter like ?order and ?type.
I want to pass these $_get parameter to my route controller action, query from DB and pass its result data to the index page. What should I do?
If you want to access the data sent from get or post request use
public function store(Request $request)
{
$order = $request->input('order');
$type = $request->input('type');
return view('whatever')->with('order', $order)->with('type', $type);
}
you can also use wildcards.
Exemple link
website.dev/user/potato
Route
Route::put('user/{name}', 'UserController#show');
Controller
public function update($name)
{
User::where('name', $name)->first();
return view('test')->with('user', $user);
}
Check the Laravel Docs Requests.
For those who need to pass part of a url as a parameter (tested in laravel 6.x, maybe it works on laravel 5.x):
Route
Route::get('foo/{bar}', 'FooController#getFoo')->where('bar', '(.*)');
Controller:
class FooController extends Controller
{
public function getFoo($url){
return $url;
}
}
Test 1:
localhost/api/foo/path1/path2/file.gif will send to controller and return:
path1/path2/file.gif
Test 2:
localhost/api/foo/path1/path2/path3/file.doc will send to controller and return:
path1/path2/path3/file.doc
and so on...

Resources