Accessing the user object in a base controller in Laravel 7? - laravel

I have a base controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Auth;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct()
{
$user = Auth::user();
if (!empty($user))
{
$uid = $user->id;
DB::table("users")
->where("id", $uid)
->update(array(
'last_time_page_accessed' => time(),
));
}
}
}
The problem is, even if I am logged in, it doesn't reach the $uid = $user->id part, because the $user object is always empty.
This is how I call it from the main controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Redirect;
use Auth;
use DB;
use App\Files;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
class ChatController extends Controller
{
public function __construct()
{
parent::__construct();
$this->middleware('auth');
}
}
What am i missing? Why can't it access it?
UPDATE
I tried switching these, and it also didn't work:
public function __construct()
{
$this->middleware('auth');
parent::__construct();
}

As apokryfos pointed out, the authenticated user is not yet available when the controller is constructed, so auth()->user() will always be null.
What you're trying to do is a perfect use case for Middleware.
You can use something like this. If you want this code to run for every route, you may register your Middleware as global Middleware for every web route.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class StoreLastTimeUserAccessedPage
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if ($user = Auth::user()) {
$user->update([
'last_time_page_accessed' => time()
]);
}
return $next($request);
}
}

Related

Laravel user roles with middleware not working

I have a Laravel project where I'm using middleware to create users roles like admin/moderator, and I want to restrict access to routes only. I have users table with a role column where my user role is 'admin'. When I go to /posts page in web.php I should be able to access it since I'm admin, but for some reason I get 404 not found. Can someone please help me?
web.php
<?php
use Illuminate\Support\Facades\Route;
Route::get('types', function () {
Route::get('/posts',[\App\Http\Controllers\ProductController::class,'posts']);
})->middleware('roles:admin');
app/Http/Controllers/ProductController.php
public function posts(){
$product = Product::orderBy('created_at', 'desc')->paginate(21);
return view('posts', ['products' => $product]);
}
app/Http/Middleware/UserRoles.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class UserRoles
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, ...$roles)
{
return collect($roles)->contains(auth()->user()->roles) ? $next($request) : back();
}
}
Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use App\Http\Middleware\UserRoles;
class Kernel extends HttpKernel
{
protected $routeMiddleware = [
'roles' => UserRoles::class,
];
}
You has a problem in web.php - get in get is not allowed. Use Route::group or Route::middleware
Route::middleware('roles:admin', function () {
Route::get('/posts',[\App\Http\Controllers\ProductController::class,'posts']);
});

Prevent login to user and custom guards at the same time

I am using a custom guard for a different type of user using a custom guard labelled business_user.
I have noticed I am able to login to as both normal users (web) and my business_users.
I've read in the Pusher documentation that I used to create my custom guards in the first place to add additional middleware into my "LoginController".
But I don't actually even have a LoginController, I've created my own controllers for each user type. AuthController (for web) and BusinessController (for business_user).
I have created a third controller labelled LoginController with the following code:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/dashboard';
public function __construct()
{
$this->middleware('guest')->except('logout');
$this->middleware('guest:business_user')->except('logout');
}
}
I also updated my RedirectIfAuthenticated as follows:
class RedirectIfAuthenticated
{
public function handle($request, Closure $next, $guard = null)
{
if ($guard == "business_user" && Auth::guard($guard)->check()) {
return redirect('/dashboard');
}
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
I also have a RedirectIfAuthenticated middleware inside my Middleware folder.
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if ($guard == "business_user" && Auth::guard($guard)->check()) {
return redirect('/dashboard');
}
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
}
When I land on my user login page, it still allows me to attempt logging in. Can someone tell me how to resolve this?
In LoginController, you can override authenticated method.
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
auth()->login($user); // this method will login with default guard
return redirect()->intended($this->redirectPath());
}
I think because the order of middleware
<?php
public function __construct()
{
$this->middleware('guest')->except('logout'); // this procress first and redirect to login page
$this->middleware('guest:business_user')->except('logout');
}
So, I think you can check directly in __construct() of LoginController or in login view (blade file)
#if (Auth::check('business_user'))
You are already logged in (or perform a redirect somewhere)
#else
//display login form
#endif

How to fix "Laravel redirect to the same login page" and middleware return false all time?

Work in the server (same code) but in localhost, it returns false always I have tried many ways.
I have tried Laravel build-in function login and so far the result always returns false while debugging.
//Middleware RedirectIfAdmin
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
$auth=Auth::guard('admin');
if (Auth::guard($guard)->check()) {
return redirect('admin/dashboard');
}
return $next($request);
}
}
I will add other code also if needed please tell me I am a new to ask question here. Please guide me.
Can you add the code from where you are calling the method handle?
namespace App\Http\Middleware;
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAdmin
{
public function handle($request, Closure $next, $guard = 'admin')
{
if (Auth::guard($guard)->check()) {
return redirect('admin/dashboard');
}
return $next($request);
}
}

Passing a collection to a mailable| Laravel 5.4

I am trying to get a mailable setup which has a collection of files. Mail controller looks like:
<?php
namespace App\Mail;
use App\Document;
use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;
class OrderComplete extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $order;
public $documents;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(User $user, Order $order, Document $document)
{
//
$this->user = $user;
$this->order = $order;
$this->documents = $document;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('emails.customers.complete');
}
}
Controller calling the mailable looks like;
use App\Document;
// other code...
$documents = Document::where('order_id', $orderId)
->where('product', 'like', '%response')
->get();
Mail::to($customer)
->send(new OrderComplete($customer, $order, $documents));
But I keep getting this error:
Type error: Argument 3 passed to App\Mail\OrderComplete::__construct() must be an instance of App\Document, instance of Illuminate\Database\Eloquent\Collection given, called in /Users/ap/sites/propair/app/Http/Controllers/OrderController.php on line 253
I'm pretty confused as I thought this should work?
thanks
This function declaration:
public function __construct(..., Document $document)
means PHP will enforce that $document is an instance of App\Document.
If you want to pass it a collection instead, you'll need to do:
public function __construct(..., \Illuminate\Database\Eloquent\Collection $documents)

Laravel5 default pagination

I have an error when simply put this
->paginate(15);
what is wrong with my code below
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Order;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator as Paginator;
class OrderController extends Controller {
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
$orders = Order::with('customer')->get()->paginate(5);
return view('order.index', compact('orders'));
}
}
appreciate if you someone can highlight to me what have I done wrong?
Remove the get() when you use paginate()
$orders = Order::with('customer')->paginate(15);

Resources