How can I passed a parameter in my middleware? I'm always getting this error
Here are the structure of my middlware
<?php
namespace App\Http\Middleware;
use Closure;
class SubDomainAccess
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $subdomain)
{
dd($subdomain); // Just trying to output the result here
return $next($request);
}
}
And on the Kernel.php under the $routeMiddleware I added this
'subdomain.access' => \App\Http\Middleware\SubDomainAccess::class,
Now on my web.php route file I added this
Route::group(['domain' => '{subdomain}.' . config('site.domain')], function () {
Route::get('/', ['as' => 'site.home', 'uses' => 'Site\Listing\ListingController#showListing'])->middleware('subdomain.access');
});
Also I tried this
Route::group(['domain' => '{subdomain}.' . config('site.domain')], function () {
Route::group(['middleware' => 'subdomain.access'], function () {
Route::get('/', ['as' => 'site.home', 'uses' => 'Site\Listing\ListingController#showListing']);
});
});
I tried this but nothings working. The only thing I haven't tried is placing the middleware in my controller constructor. But I don't wan't it that way as I think this is messy and it's more elegant if its within the route file.
Hope you can help me on this. Thanks
Ok so I managed to find a way to get the parameters without passing a third parameter on the middleware handle function thanks to this link
So what I did to retrieve the subdomain parameter is this
$request->route()->parameter('subdomain')
or if all parameter
$request->route()->parameters()
['middleware' => 'subdomain.access'] is wrong, try to use ['middleware' => 'subdomain:access'] with a : instead.
https://mattstauffer.co/blog/passing-parameters-to-middleware-in-laravel-5.1
Get URI from $request object and then return domain. No need to pass subdomain as params to middleware.
namespace App\Http\Middleware;
use Closure;
class SubDomainAccess
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $subdomain)
{
$sudomain = $this->getSubDomain($_SERVER['HTTP_HOST']);
return $next($request);
}
/**
* Get Subdomain name
* #param $uri
* #return bool
*/
private function getSubDomain($uri)
{
if(!empty($uri))
{
$host = explode('.', $uri);
if(sizeof($host) > 2)
return $host[0];
}
return false;
}
}
Hi i am doing a website in laravel.
I am trying to do like a function that needs to execute before any controller.
Example :
I have function like
function xyz(){
//do code here
}
This function need to execute when user on site by refreshing page or doing some ajax requst.
I am aware with the codeigniter there is a way to do this using hook
$hook['pre_controller'] = array(
'class' => 'MyClass',
'function' => 'Myfunction',
'filename' => 'Myclass.php',
'filepath' => 'hooks',
'params' => array('beer', 'wine', 'snacks')
);
What is the way in laravel to do this ?
You can use Laravel Middleware to achieve this. The middleware can be registered as global for all controllers / routes, and will let you execute that function (or you can register it for subset of routes by using router groups).
Example:
<?php
namespace App\Http\Middleware;
use Closure;
class MyMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
// call your function
$this->xyz();
return $next($request);
}
public function xyz()
{
// do something
}
}
See the Laravel documentation on Middleware.
For that, you need to declare the function in the public construct part of your controller. For example, if you had a Controller for all pages as follows and you need to check if a user is above a certain age.
class PageController extends Controller
{
public function __construct()
{
Run this function for every function in controller
$this->middleware('age');
}
public function index()
{
//my public static page
}
}
Create a middleware with the artisan command
php artisan make:middleware AgeMiddleware
in your AgeMiddleware, you can have a function as follows.
class AgeMiddleware
{
/**
* Run the request filter.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($request->input('age') <= 200) {
//Do whatever you want, in this case I redirect home
return redirect('home');
}
return $next($request);
}
}
tried to implement a simple user register/login function on my site using the laravel default controllers (auth/password), but as soon as I login, the class RedirectIfAuthenticated handle function prevents all access to auth url's, thus I cannot logout anymore. Is there a bug and I need to write an exception on the handle function or have I missed something?
Here is how the class looks like by default:
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)
{
//dd($next($request));
if (Auth::guard($guard)->check()) {
return redirect('/articles');
}
return $next($request);
}
}
The AuthController's constructor should look similar to this:
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
The guest middleware is handled by the RedirectIfAuthenticated class and, in order to have the logout functionality working, you should choose one:
call the logout method from your AuthController.
call whichever method you use for logout and exclude it in AuthController's constructor:
public function __construct()
{
$this->middleware('guest', ['except' => '<whichever_method>']);
}
For potentially more-advanced reasons and needs, I will show a different idea.
Inside any middleware, a person could implement their own except list. Here is a reference:
<?php
namespace App\Http\Middleware;
use Closure;
class CustomThing
protected $except = [
'api/logout',
'api/refresh',
];
public function handle($request, Closure $next)
{
foreach ($this->except as $excluded_route) {
if ($request->path() === $excluded_route) {
\Log::debug("Skipping $excluded_route in this middleware...");
return $next($request);
}
}
\Log::debug('Doing middleware stuff... '. $request->url());
}
}
I will leave it up to imagination to extend that to support other types of URLs. For example, investigate matchers such as $request->url(), $request->fullUrl(), and $request->is('admin/*').
A person could investigate the vendor code for the VerifyCsrfToken middleware and make their custom one support something like this:
protected $except = [
'api/logout',
'api/refresh',
'foo/*',
'http://www.external.com/links',
];
If you want it to be a reuseable solution, make that matching algorithm a Trait and import it into any middleware you want to exclude routes from.
When user logs in and is authenticated, I use Auth::user()->username; to show username of user on dashboard. However, for some reason when session expires the class Auth doesn't seem to work and dashboard page throws error as trying to get property of non-object for Auth::user()->username;. How can I redirect the user back to the login page when he clicks any link or refreshes the page after the session has expired?
I tried the Authenticate.php middleware but it always redirects back to login page,whatever you put the credentials either correct or incorrect.However,when I don't use this middleware it logins the user.Am I missing something?
Route.php
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
/*
Actions Handled By Resource Controller
Verb Path Action Route Name
GET /photo index photo.index
GET /photo/create create photo.create
POST /photo store photo.store
GET /photo/{photo} show photo.show
GET /photo/{photo}/edit edit photo.edit
PUT/PATCH /photo/{photo} update photo.update
DELETE /photo/{photo} destroy photo.destroy
Adding Additional Routes To Resource Controllers
If it becomes necessary to add additional routes to a resource controller beyond the default resource routes, you should define those routes before your call to Route::resource:
Route::get('photos/popular', 'PhotoController#method');
Route::resource('photos', 'PhotoController');
*/
// Display all SQL executed in Eloquent
// Event::listen('illuminate.query', function($query)
// {
// var_dump($query);
// });
define('ADMIN','admin');
define('SITE','site');
Route::group(['namespace' => ADMIN], function () {
Route::get('/','UserController#showLogin');
});
////////////////////////////////////Routes for backend///////////////////////////////////////////////////
Route::group(['prefix' => ADMIN,'middleware' => 'auth'], function () {
Route::group(['namespace' => ADMIN], function () {
//Route::get('/','EshopController#products');
//sumit routes for user registration
//Route::resource('users','UserController');
Route::get('/users/destroy/{id}','UserController#destroy');
Route::get('UserProf','UserController#userProf');
Route::get('users','UserController#index');
Route::get('/users/create','UserController#create');
Route::get('/users/adminEdit/{id}','UserController#adminEdit');
Route::post('/users/adminUpdate','UserController#adminUpdate');
Route::post('/users/store','UserController#store');
Route::get('/users/edit/{id}','UserController#edit');
Route::post('/users/update/{id}','UserController#update');
//airlines route
Route::get('airlines','AirlinesController#index');
Route::get('/airlines/create','AirlinesController#create');
Route::post('/airlines/store','AirlinesController#store');
Route::get('/airlines/edit/{id}','AirlinesController#edit');
Route::post('/airlines/update','AirlinesController#update');
Route::get('/airlines/destroy/{id}','AirlinesController#destroy');
//end sumit routes
//flight routes
Route::get('flights','FlightController#index');
Route::get('showFlightBook','FlightController#showFlightBook');
Route::get('flights/create','FlightController#create');
Route::post('flights/store','FlightController#store');
Route::get('flights/book','FlightController#book');
Route::get('flights/edit/{id}','FlightController#edit');
Route::post('flights/update','FlightController#update');
Route::get('flights/destroy/{id}','FlightController#destroy');
//Route::resource('flight','FlightController');
//hotels route
Route::get('hotels','HotelsController#index');
Route::get('/hotels/create','HotelsController#create');
Route::post('/hotels/store','HotelsController#store');
Route::get('/hotels/edit/{id}','HotelsController#edit');
Route::post('/hotels/update','HotelsController#update');
Route::get('/hotels/destroy/{id}','HotelsController#destroy');
//end sumit routes
//book-hotel routes
Route::get('hotel-book','HotelBookController#index');
Route::get('showHotelBook','HotelBookController#showHotelBook');
Route::get('hotel-book/create','HotelBookController#create');
Route::post('hotel-book/store','HotelBookController#store');
Route::get('hotel-book/book','HotelBookController#book');
Route::get('hotel-book/edit/{id}','HotelBookController#edit');
Route::post('hotel-book/update','HotelBookController#update');
Route::get('hotel-book/destroy/{id}','HotelBookController#destroy');
//Route::resource('hotel','HotelController');
//close flight routes
//for admin login
//Route::get('initlogin','UserController#lgnPage');
Route::get('login','UserController#showLogin');
// Route::get('privilegeLogin','UserController#privilegeLogin');
// Route::post('privilegeCheck','UserController#privilegeCheck');
Route::post('login','UserController#doLogin');
Route::get('/dashboard','DashController#index');
Route::get('logout','UserController#doLogout');
//user login
//Route::get('userLogin','UserController#showUserLogin');
//Route::post('userLogin','UserController#doUserLogin');
Route::get('/userDashboard','DashController#userIndex');
Route::get('Logout','UserController#doUserLogout');
//password reset
Route::get('forget-pass','UserController#showReset');
//Route::get('home', 'PassResetEmailController#index');
});
});
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
Authenticate.php:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Authenticate {
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest())
{
if ($request->ajax())
{
return response('Unauthorized.', 401);
}
else
{
// return redirect()->guest('auth/login');
return redirect()->guest('/');
}
}
return $next($request);
}
}
All you have to do is just put this constructor at the top of the controller for your dashboard. It seems Laravel has a middleware that handles this already. At least I can confirm from 5.4 and up.
public function __construct()
{
$this->middleware('auth');
}
If the session expires then you can redirect to log in like as
open this file app/Exceptions/Handler.php add this code
public function render($request, Exception $exception)
{
if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
return redirect('/login');
}
return parent::render($request, $exception);
}
If you want a middleware to be run during every HTTP request to your application, simply list the middleware class in the $middleware property of your app/Http/Kernel.php class.
So, to protect every route from being accessed without authentication do this
protected $middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
'App\Http\Middleware\Authenticate',// add this line according to your namespace
];
it will redirect the user if not logged in. UPDATE Keep in mind that adding auth middleware as global will create redirect loop so avoid it.
Or if you want specific routes to be protected then attach the middleware auth to that route
Route::get('admin/profile', ['middleware' => 'auth', function () {
//
}]);
I think you are not attaching the auth middleware to your routes.
Create a middleware like this
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Authenticate
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
return $next($request);
}
}
Then Group the routes and protect them like this
Route::group(['middleware' => 'auth'], function()
{
Route::get();
Route::get();
Route::get();
Route::get();
}
Offcourse, in the routes you have to specify your links etc, it will only allow the user when he is authenticated and if not then login page will be shown
To make session redirect to your login just add ->middleware('auth') in your router files as shown below I am using laravel 5.3
Ex:
Route::post('controllerName','folderName\fileName#fnNmae')->middleware('auth');
Or visit https://laravel.com/docs/5.3/authentication
I have a middleware like this:
<?php
namespace App\Http\Middleware;
use App\Contracts\PermissionsHandlerInterface;
use Closure;
class PermissionsHanlderMiddleware {
public $permissionsHandler;
function __construct(PermissionsHandlerInterface $permissionsHandler) {
$this -> permissionsHandler = $permissionsHandler;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
$routeAction = $request->route()->getActionName();
/*
do some operations
*/
return $next($request);
}
}
but $request->route() always returns null, I think its because the router hasn't been dispatched with the request.
Note: I added my middleware to Kernal.php global middlewares to run before each request as the following
protected $middleware = [
.
.
.
'App\Http\Middleware\PermissionsHanlderMiddleware',
];
I want to get route action name before the execution of $next($request) to do some permission operations. How can i do this ?
You cannot get the route action name if the router has not yet been dispatched. The router class has not yet done its stuff - so you cannot do $router->request() - it will just be null.
If it runs as routeMiddleware as $routeMiddleware - then you can just do $router->request()
You can get the URI string in the middleware before the router has run - and do some logic there if you like: $request->segments(). i.e. that way you can see if the URI segment matches a specific route and run some code.
Edit:
One way I can quickly think of is just wrap all your routes in a group like this:
$router->group(['middleware' => 'permissionsHandler'], function() use ($router) {
// Have every single route here
});
This is the solution I did in my project:
...
public function handle($request, Closure $next) {
DB::beginTransaction();
$nextRequest = $next($request); //The router will be dispatched here, but it will reach to controller's method sometimes, so that we have to use DB transaction.
$routeName = $request->route()->getRouteName();
if ($checkPassed) {
DB::commit();
return $nextRequest;
} else {
DB::rollback();
}
}
This is also fine.
$request->path(); // path
$request->route()->getName()//name of the route