Laravel: How to properly rewrite an authentification route in an MVC? - php

I have to setup my authentication for my reservations system in Laravel.
The basic routing methods by Laravel and a lot of tutorials is by writing the function for the route inside the web.php like this Laraval example:
Route::get('/flights', function () {
// Only authenticated users may access this route...
})->middleware('auth');
However, I was told this isn't the best way to set up routing and that I should use a controller to manage routes.
But that means I have to setup authentification methods inside the controller and to be honest, I don't have the vision to do this..
I thought I could do it like this (My Code)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Auth;
class PagesController extends Controller
{
public function home() {
return view('home');
}
public function reservations() {
return view('reservations')
->middleware(['auth']);
}
public function newreservations() {
return view('reservations_new');
}
}
combined with this web.php setup:
Route::get('/reservations.html', [PagesController::class, 'reservations']);
Route::get('/reservations.html/login', [AuthenticatedSessionController::class, 'create']);
Route::post('/reservations.html/login', [AuthenticatedSessionController::class, 'store']);
Route::get('/reservations_new.html', [PagesController::class, 'newReservations']);
but then I got the error:
Method Illuminate\View\View::middleware does not exist.
So any tips/tricks/methods to do it the right way?

There is no right or wrong way as long as you follow the same principal.
I personally do this:
Route::middleware('auth')->group(function () {
// Authenticated routes
});
you can check this extended discussion
also if you want to use middlewares in controller, this is the right way
class UserController extends Controller
{
/**
* Instantiate a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}

Related

Auth middleware optional in Laravel

I have my controller ExampleController:
class ExampleController extends Controller
{
function __construct()
{
$this->middleware('auth:student')->only(['store', 'update', 'destroy']);
}
public function index()
{
if(CheckUser::student()) {
dd("Is student");
}
dd("Isn't student");
}
/**
* Another method's not relevant.
**/
}
I'm trying to add some logic if is student.
But have one problem, I just can access: Auth::user() if I set the middleware. But this specific method can be accessed without has logged in.
My question
Is possible to create a not required middleware for what if logged get user information?
Note: I'm using Laravel passport with multi auth.
If you want to protect specific methods that are in your controller and leave out others in the same controller
You may try to protect your endpoint on the routes files (api.php or web.php) rather than on the Constructor
//protected routes
Route::group(['middleware' => 'auth:api'], function () {
Route::post('customer/picture/add', 'Mobile\AuthController#addProfilePicture');
Route::post('customer/phone/update', 'Mobile\AuthController#updatePhoneNumber');
});
//unprotected routes
Route::get('customer/login', 'Mobile\AuthController#getLoginForm');

How to pass a model instance to all controllers and views based on a route parameter

I am working on a Laravel control panel project where we should be able to toggle from one site to another and get the detail of the site based on the ID passed in the route.
In itself this is quiet easy to do but as I will have several controllers using this technique it means for each controller and each controller instance I will have collect the site instance and it does not look very user friendly due to the many repetitions.
Here is what I have:
Route:
Route::get(
'cp/site/{website}/modules/feeds',
'App\Http\Controllers\Modules_sites\Feeds\FeedController#index'
)->name('module_site.feeds.index');
Model:
class Website extends Model
{
use HasFactory;
protected $primaryKey ='site_id';
}
The database is simple with an id (site_id) and name
Controller:
public function index(Website $website)
{
dd($website -> name);
}
The above is working fine but I am going to end with dozens of methods across multiple controllers doing the same thing, and what if changes are required.
I have looked at the ID of using the AppServiceProvider to create the Website instance and then pass it to the controllers and views but I can't do this as the route is not defined at this stage and I only seem to be able to pass this to the view.
Essentially, I am looking to create something similar to the auth()->user() method that is available from controllers and routes without the needs to pass it to each controller.
Is this possible?
Perhaps you could use middleware to set this value? Something like this to put it in the session globally:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckWebsite
{
public function handle(Request $request, Closure $next): mixed
{
$request->session()->put("website", $request->route("website"));
return $next($request);
}
}
Or this on a per-controller basis:
<?php
namespace App\Http\Controllers\Modules_sites\Feeds;
use App\Http\Controllers\Controller;
use Closure;
use Illuminate\Http\Request;
class FeedController extends Controller
{
public function __construct()
{
$this->middleware(function (Request $request, Closure $next) {
$this->website = $request->route("website");
return $next($request);
});
}
public function index()
{
dd($this->website->name);
}
}
Also worth mentioning that routes are not defined like that in Laravel 8 any longer. It should look like this:
Route::get(
'cp/site/{website}/modules/feeds',
[FeedController::class, 'index']
)->name('module_site.feeds.index');
With an appropriate import for the controller class.
as you primary key is not id so it will not work automatically you need to tell laravel to search by column name
code will be
Route::get('cp/site/{website:site_id}/modules/feeds', 'App\Http\Controllers\Modules_sites\Feeds\FeedController#index')->name('module_site.feeds.index');
you need to use {website:site_id}
ref link https://laravel.com/docs/8.x/routing#customizing-the-default-key-name

Laravel 5.7 Login Form Route

I made a fresh install of Laravel 5.7, and I'm trying to change the view it renders when I go to /login.
When I list my routes, it says that the route /login uses logic from 'LoginController#showLoginForm', but I can't see it in the controller:
php artisan route:list
and when I go to the LoginController, this showLoginForm method doesn't seem to exist...
LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/dashboard';
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
Where is the boilerplate that I can change for this?
When you "use AuthenticatesUsers" it extends functionality and also brings the showLoginForm to the controller.
If you want to add code to that function you just need to overwrite it.
If youre using an IDE like PHPStorm you can control click through the "use" declaration to see whats being imported, or you can go manually look inside Illuminate\Foundation\Auth\AuthenticatesUsers
it is in :
use AuthenticatesUsers;
find it and override in loginController
this is that code on vendor:
public function showLoginForm()
{
return view('auth.login');
}
Login form view is located in resources/views/auth/login.blade.php
You can easily change it
showLoginForm() exists on trait AuthenticatesUsers
Just try override showLoginForm() method :)
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/dashboard';
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function showLoginForm() {
// Your code
}
}

Laravel Packages Route

i made some laravel packages, the packages work well if user is not log in, but when user has login and visiting route from packages laravel consider that the user has not log in yet, i ensure that user has successfully log in, because another menu/route not come from the packages it work well. what wrong here ? is i am missing something ?
here is my controller
namespace Offices\Referensi;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class ReferensiController extends Controller
{
function tes()
{
echo "Halo";
}
}
here is my service provider
class ReferensiServiceProvider extends ServiceProvider
{
public function boot()
{
include __DIR__.'/routes.php';
}
public function register()
{
$this->app->make('Offices\Referensi\ReferensiController');
}
}
and here is the routes.php
<?php
Route::group(['middleware' => ['auth']], function() {
Route::get('referensi/area','Offices\Referensi\ReferensiController#tes');
});
never mind, i know the problem, i just missing the web middleware on the route file, so the routes.php should be
<?php
Route::group(['middleware' => ['web','auth']], function() {
Route::get('referensi/area','Offices\Referensi\ReferensiController#tes');
});

Laravel 5: Controller subdirectory and Route Group with multiple Controller does not work

Its might be a bug in laravel but not sure, need your suggestions about to resolve this.
The issue is when you use more than one controller under route:group with controller subdirectory except one controller other would be 404s.
Here's my detail code review for senerio:
Routes
#routes.php
#Settings
Route::group(array('prefix' => 'setting'), function() {
#Index
Route::controller('/', 'Setting\IndexController',[
'getIndex'=>'index/setting'
]);
#company detail
Route::controller('company', 'Setting\CompanyController',[
'getInfo'=>'info/company',
'getEdit'=>'update/company'
]);
});
Controllers
IndexController.php
#/app/Http/Controllers/Setting/IndexController.php
namespace App\Http\Controllers\Setting;
use App\Http\Controllers\Controller;
class IndexController extends Controller {
public function getIndex(){
return "setting.index";
}
}
CompanyController.php
namespace App\Http\Controllers\Setting;
use App\Http\Controllers\Controller;
class CompanyController extends Controller {
public function getInfo(){
return ('setting.company.index');
}
public function getEdit(){
return ('setting.company.edit');
}
}
Currently its not working but when you comment one route::controller other will work fine and viceversa.
and also if remove one route:controller and add route like:
Route::get('/', array('as' => 'index/setting', 'uses' => 'Setting\IndexController#getIndex'));
than both will work fine.
But I need to use route:controller for all controllers under route:group.
So, if still there something missing to explain let me know, I will update further in depth.
Any help would be appreciable.

Categories