What I'm trying to do is group multiple prefixes with one middleware:
Route::group(['middleware' => ['centralize']], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setLocale()], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setCountry()], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setCity()], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setArea()], function () {
//routes
});
});
});
});
});
I have added the centralize middleware to kernel:
protected $routeMiddleware = [
...
'centralize'=> \App\Http\Middleware\Centralize::class,
...
];
But the middleware is not being called at all, is there is something missing here?
EDIT: it goes directly to the view of the home, I am doing dd inside of the middleware but it never reaches there!
EDIT: middleware code:
<?php
namespace App\Http\Middleware;
use App\Utilities\Centralization;
use Closure;
use Illuminate\Http\RedirectResponse;
class Centralize
{
/**
* #var \Illuminate\Http\Request
*/
private $request;
/**
* #var array
*/
private $params;
private $location;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(\Illuminate\Http\Request $request, Closure $next)
{
$this->request = $request;
dd('hit');
$this->params = explode('/', $request->getPathInfo());
$this->figureLocale();
$this->figureCountry();
$this->figureCity();
$this->figureArea();
$this->figureLocation();
$redirection = implode('/', $this->params);
if ($request->getPathInfo() !== $redirection) {
return new RedirectResponse($redirection, 302, ['Vary' => 'Accept-Language']);
}
\View::share([
'countries' => Centralization::getCountries(),
'cities' => Centralization::getCities(),
'areas' => Centralization::getAreas(),
'location' => $this->location
]);
return $next($request);
}
private function figureLocale()
{
//...
}
private function figureCountry()
{
//..
}
private function figureCity()
{
//...
}
private function figureArea()
{
//...
}
private function figureLocation()
{
//...
}
}
EDIT: I also have tried:
Route::middleware(['centralize'])->group(function () {
Route::group(['prefix' => \App\Utilities\Centralization::setLocale()], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setCountry()], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setCity()], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setArea()], function () {
//..
});
});
});
});
});
But with the same result , it never hits the middleware!
EDIT: clearing cache using artisan and manual doesn't work either!
Group route middleware called like this:
In routes/web.php
Route::group(['middleware' => ['centralize']], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setLocale()], function () {
Route::group(['prefix' => \App\Utilities\Centralization::setCountry()], function () {
//routes
});
});
});
In app/Http/kernal.php
protected $routeMiddleware = [
'centralize' => \App\Http\Middleware\CentralizeMiddleware::class,
];
In app/Http/Middleware/CentralizeMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CentralizeMiddleware
{
public function handle($request, Closure $next)
{
if (//Your Condition) {
//If true
}
else {
return $next($request);
}
}
}
You mentioned in one edit that:
it goes directly to the view of the home
So the URL you are visiting is actually /. And as clarified in the comments, the "home" route was defined nested inside the prefixes. But that means it is really a route for something like /fr/france/paris/somewhere/, and not a route for /.
The prefix in the route means "this route applies to URIs with this prefix". If a URI does not include that prefix, this routing is not applied.
So that means there is no route for /, and visiting it will:
not fire the centralize middleware;
not find a matching route, so throw a 404;
If you want to apply your centralize middleware to your home route, you'll need to place it inside that group, but outside the prefixes:
Route::middleware(['centralize'])->group(function () {
Route::get('/', 'HomeController#index')->name('home');
Route::group(['prefix' => \App\Utilities\Centralization::setLocale()], function () {
// ...
});
});
Related
How does it(route:caching) work under hood and will it breake logic if I cached my routes.
I have a webhook which send me data to one single route. The data are difference only by objects fields. Will it correct to split it to different routes or I am need to make index method which will be redirect my logic by methods
Route::group(['namespace' => 'Webhook'], function () {
if (Request::has('message')) {
Route::post('/', 'WebhookController#message');
}
if (Request::has('callback_query')) {
Route::post('/', 'WebhookController#callback');
}
});
You can shorten the routes code to this:
Route::group(['namespace' => 'Webhook'], function () {
Route::post('/', 'WebhookController#handle');
});
And do the "heavy work" in the controller:
class WebhookController extends Controller
{
public function handle(Request $request)
{
if ($request->has('message')) {
return $this->message();
}
if ($request->has('callback_query')) {
return $this->callback();
}
}
public function message();
public function callback();
}
This is equivalent to:
Route::group(['namespace' => 'Webhook'], function () {
Route::post('/', function(Request $request) {
if ($request->has('message')) {
return (new WebhookController)->message();
}
if ($request->has('callback_query')) {
return (new WebhookController)->callback();
}
});
});
You can use middleware for such kind of logics.
Laravel Middleware
I use this guide: https://mydnic.be/post/how-to-build-an-efficient-and-seo-friendly-multilingual-architecture-in-laravel-v2
I have these routes and middleware:
$locale = request()->segment(1);
Route::middleware('localized')->prefix($locale)->group(function() {
Route::get('/contacts', 'ContactController#index');
Route::get('/page/{page}', 'PageController#index');
});
And middleware localized from Kernel.php -> routeMiddleware:
public function handle(Request $request, Closure $next)
{
if (!array_key_exists($request->segment(1), config('translatable.locales'))) {
$segments = $request->segments();
$segments = Arr::prepend($segments, config('app.fallback_locale'));
if($request->session()->has('language')) {
$segments[0] = session('language');
}
return redirect()->to(implode('/', $segments));
}
return $next($request);
}
When I access to: site.test/contacts he redirect me on locale: site.com/en/contacts
When I access to site.test/page/test I got 404 not found, If I access to: site.com/en/page/test then page working. Problem with redirect on locale with route model binding.
In Controller Page I have:
public function index(Page $page)
{
return view('page', compact('page'));
}
In translatable.php:
'locales' => [
'de' => 'Deutsch',
'en' => 'English',
],
In AppServiceProvider:
public function boot()
{
if(array_key_exists(request()->segment(1), config('translatable.locales'))) {
app()->setLocale(request()->segment(1));
}
}
I was able to work around this but this cost us access to the session, which you checked for to know if the session has "language" if yes, then prepend locale value should be set to the language value in the session. Below is what I did;
In Routes File
$locale = request()->segment(1);
Route::prefix($locale)->group(function() {
Route::get('/contacts', function(){
echo "hello contact";
});
Route::get('/page/{page}', function(Request $request, $page){
return "hello Page {$page}";
});
});
In MiddleWare File I did
public function handle(Request $request, Closure $next)
{
if (!array_key_exists($request->segment(1), config('translatable.locales'))) {
$segments = $request->segments();
$segments = Arr::prepend($segments, config('app.fallback_locale'));
// Remove the session check as we don't have access to session yet
/*if($request->session()->has('language')) {
$segments[0] = session('language');
}*/
return redirect()->to(implode('/', $segments));
}
return $next($request);
}
Now in Kennel.php File for Middleware, Add your middleware class in the $middleware array
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
...
\App\Http\Middleware\Localized::class, //This is the Localized Middlewere class
];
Then try access site.test/page/1000 ... it will be redirected to site.test/{app.fallback_locale}/page/1000. In my case site.test/en/page/1000
UPDATE
After reading through this issue on git for laravel, I then thought of adding the session before the Localized middle class and it worked. I'm not sure if this is good practice but it got the job done.
In MiddleWare File I did
public function handle(Request $request, Closure $next)
{
if (!array_key_exists($request->segment(1), config('translatable.locales'))) {
$segments = $request->segments();
$segments = Arr::prepend($segments, config('app.fallback_locale'));
// We can have session back on
if($request->session()->has('language')) {
$segments[0] = session('language');
}
return redirect()->to(implode('/', $segments));
}
return $next($request);
}
Now in Kennel.php File for Middleware, Add Session middleware before Localized Middleware class
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
...
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\Localized::class, //This is the Localized Middlewere class
];
this is my web route php:
Route::get('settings', 'Settings\SettingsController#edit')->name('admin.settings.edit');
and I call this route name like below:
<a href="{{ route('admin.settings.edit') }}" class="nav-link ">
<span class="title">Settings</span>
</a>
but I got this error:
Route [admin.settings.edit] not defined. (View:
C:\xampp7\htdocs\template\resources\views\layouts\admin\sidebar.blade.php)
(View:
C:\xampp7\htdocs\template\resources\views\layouts\admin\sidebar.blade.php)
(View:
C:\xampp7\htdocs\template\resources\views\layouts\admin\sidebar.blade.php)
rouet:list returns this error message: `Class App\Http\Controllers\Admin\Settings\SettingsController does not exist
but I have this controller:
namespace App\Http\Controllers\Admin\SettingsController;
use App\Http\Controllers\Controller;
use App\Shop\Brands\Repositories\BrandRepository;
use App\Shop\Brands\Repositories\BrandRepositoryInterface;
use App\Shop\Brands\Requests\CreateBrandRequest;
use App\Shop\Brands\Requests\UpdateBrandRequest;
class SettingsController extends Controller
{
public function __construct(){}
public function index()
{}
public function create(){}
public function store(){}
/**
*
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit()
{
dd("milad");
return view('admin.brands.edit', ['brand' => '']);
}
/**
* #param UpdateBrandRequest $request
* #param $id
*
* #return \Illuminate\Http\RedirectResponse
* #throws \App\Shop\Brands\Exceptions\UpdateDiscountCodesErrorException
*/
public function update(UpdateBrandRequest $request, $id)
{
// $brand = $this->brandRepo->findBrandById($id);
//
// $brandRepo = new BrandRepository($brand);
// $brandRepo->updateBrand($request->all());
//
// return redirect()->route('admin.brands.edit', $id)->with('message', 'Update successful!');
}
public function destroy()
{}
}
`
updated
all my web route php:
/**
* Admin routes
*/
Route::namespace('Admin')->group(function () {
Route::get('admin/login', 'LoginController#showLoginForm')->name('admin.login');
Route::post('admin/login', 'LoginController#login')->name('admin.login');
Route::get('admin/logout', 'LoginController#logout')->name('admin.logout');
});
Route::group(['prefix' => 'admin', 'middleware' => ['employee'], 'as' => 'admin.' ], function () {
Route::namespace('Admin')->group(function () {
Route::group(['middleware' => ['role:admin|superadmin|clerk, guard:employee']], function () {
Route::get('/', 'DashboardController#index')->name('dashboard');
Route::namespace('Products')->group(function () {
Route::resource('products', 'ProductController');
Route::get('remove-image-product', 'ProductController#removeImage')->name('product.remove.image');
Route::get('remove-image-thumb', 'ProductController#removeThumbnail')->name('product.remove.thumb');
});
Route::namespace('Customers')->group(function () {
Route::resource('customers', 'CustomerController');
Route::resource('customers.addresses', 'CustomerAddressController');
});
Route::namespace('Categories')->group(function () {
Route::resource('categories', 'CategoryController');
Route::get('remove-image-category', 'CategoryController#removeImage')->name('category.remove.image');
});
Route::namespace('Orders')->group(function () {
Route::resource('orders', 'OrderController');
Route::resource('order-statuses', 'OrderStatusController');
Route::get('orders/{id}/invoice', 'OrderController#generateInvoice')->name('orders.invoice.generate');
});
Route::resource('addresses', 'Addresses\AddressController');
Route::resource('countries', 'Countries\CountryController');
Route::resource('countries.provinces', 'Provinces\ProvinceController');
Route::resource('countries.provinces.cities', 'Cities\CityController');
Route::resource('couriers', 'Couriers\CourierController');
Route::resource('attributes', 'Attributes\AttributeController');
Route::resource('attributes.values', 'Attributes\AttributeValueController');
Route::resource('brands', 'Brands\BrandController');
Route::resource('discounts', 'DiscountCodes\DiscountCodesController');
Route::resource('comments', 'Comments\CommentsController');
Route::resource('messages', 'Messages\MessagesController');
Route::resource('pages', 'Pages\PagesController');
Route::resource('blog-categories', 'BlogCategories\BlogCategoriesController');
Route::resource('blog-posts', 'BlogPosts\BlogPostsController');
Route::resource('scores-categories', 'ScoresCategories\ScoresCategoriesController');
Route::resource('scores-levels', 'ScoresLevels\ScoresLevelsController');
Route::resource('affiliate-categories', 'AffiliateCategories\AffiliateCategoriesController');
Route::resource('products-codes', 'ProductsCodes\ProductsCodesController');
Route::get('settings', 'SettingsController#edit')->name('admin.settings.edit');
});
Your controller namespace is wrong.
namespace App\Http\Controllers\Admin\SettingsController;
Change it to:
namespace App\Http\Controllers\Admin\Settings;
and your route to:
Route::get('settings', 'Admin\Settings\SettingsController#edit')->name('admin.settings.edit');
If i go to http://www.yourdomain.com/admin/login i see my login page.
If i go to http://www.yourdomain.com/admin/example i have the redirect to http://www.yourdomain.com/login without the admin.
My web routes:
Auth::routes();
Route::prefix('admin')->group(function() {
Route::get('/login','Auth\AdminLoginController#showLoginForm')->name('admin.login');
Route::post('/login','Auth\AdminLoginController#login')->name('admin.login.submit');
Route::get('/manifiesto','AdminController#getIndex')->name('admin.dashboard');
Route::get('/logout','Auth\AdminLoginController#logout')->name('admin.logout');
Route::get('/trabajadores','AdminController#showTrabajadores')->name('admin.trabajadores');
Route::get('/clientes','AdminController#showClientes')->name('admin.clientes');
Route::get('/proyectos','AdminController#showProyectos')->name('admin.proyectos');
Route::get('/administradores','AdminController#showAdmins')->name('admin.administradores');
});
When i put some url with the /admin before and user isn't logged, i want to redirect to /admin/login.
Thanks.
More info:
App/http/Controllers/Auth/AdminLoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Auth;
class AdminLoginController extends Controller
{
protected $loginPath = 'admin/login';
public function __construct()
{
$this->middleware('guest:admin', ['except' => ['logout']]);
}
public function showLoginForm()
{
return view('backend.public.pages.login');
}
public function login(Request $request)
{
//validate the form data
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:6'
]);
//attempt to log the user in
if (Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password], $request->remember)){
//if successful, then redirect to their intended location
return redirect()->intended(route('admin.dashboard'));
}
return redirect()->back()->withInput($request->only('email','remember'));
}
public function logout()
{
Auth::guard('admin')->logout();
return redirect('/');
}
}
App\Http\Middleware\AdminAuthenticate.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminAuthenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest())
{
if ($request->ajax())
{
return response('Unauthorized.', 401);
}
else
{
return redirect()->guest('admin/login'); // <--- here
}
}
return $next($request);
}
}
Create an middleware
php artisan make:middleware AuthAdmin
Check for guest in the handle method of the middleware
public function handle($request, Closure $next)
{
if (Auth::guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('admin/login');
}
}
return $next($request);
}
Add a key to the middleware in app/Http/Kernel.php in $routeMiddleware array
'auth_admin' => \App\Http\Middleware\AuthAdmin::class
Attach the auth_admin middleware to the group
Route::group(['prefix' => 'admin', 'middleware' => 'auth_admin'], function() {
// Your admin routes except login
});
write bellow code in your route.php file
Route::group(array('prefix' => 'admin'), function() {
Route::controller('login', 'AdminloginController');
});
Route::group(array('before' => 'admin_ajax', 'prefix' => 'admin'), function()
{
//route for pages which are render after login
});
Route::get('/admin', function() {
return View::make('admin.loginform');
});
And Write bellow code in your filter.php file
Route::filter('admin_ajax', function() {
if (!Auth::admin()->check()) {
return Redirect::to('admin/login');
} else {
}
});
And if you are using laravel 5.4
Route::get('/manage', function () {
return redirect('manage/login');
});
Route::group(['prefix' => 'manage'], function() {
//login bypass for the below listed controllers
Route::resource('login', 'AdminLoginController#showLoginForm');
Route::post('dologin', 'AdminLoginController#login');
});
All you can do is add the auth middleware like this :
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function() {
Route::get('/login','Auth\AdminLoginController#showLoginForm')->name('admin.login');
Route::post('/login','Auth\AdminLoginController#login')->name('admin.login.submit');
Route::get('/manifiesto','AdminController#getIndex')->name('admin.dashboard');
Route::get('/logout','Auth\AdminLoginController#logout')->name('admin.logout');
Route::get('/trabajadores','AdminController#showTrabajadores')->name('admin.trabajadores');
Route::get('/clientes','AdminController#showClientes')->name('admin.clientes');
Route::get('/proyectos','AdminController#showProyectos')->name('admin.proyectos');
Route::get('/administradores','AdminController#showAdmins')->name('admin.administradores');
});
But by default this will redirect to /login, if you want to override this you have two chocies depending on if you have other type of users that uses the /login route or not !!
If NO ONE uses /login route
1- You need to modify App\Http\Middleware\Authenticate::handle() method and change /login to admin/login.
2- Then you need to add $loginPath property to your \App\Http\Controllers\Auth\AuthController class.
Authenticate
namespace App\Http\Middleware;
class Authenticate {
/**
* 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('admin/login'); // <--- here
}
}
return $next($request);
}
}
AuthController
namespace App\Http\Controllers\Auth;
class AuthController extends Controller
{
protected $loginPath = 'admin/login'; // <--- here
// ... other properties, constructor, traits, etc
}
If there is someone using /login route
You must create you own middleware and do what it takes for auth checking in the handle method with redirecting to your admin/liging route :)
In this case :
Add the following line in $routeMiddleware property at app/Http/Kernel.php file
'adminAuth' => \App\Http\Middleware\YourNewMiddleware::class,
Don't forget to add your new middleware in route group as follow
Route::group(['prefix' => 'admin', 'middleware' => 'adminAuth'], function()
{
// your admin routes
});
Make an another middleware for admin. follow the step
Make a file named AdminAuthenticate in app/Http/Middleware location and copy the content of Authenticate in New file
change the Class name as AdminAuthenticate
Change the content of handle function as show below
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('/admin/login');
}
}
return $next($request);
}
Add the following line in $routeMiddleware array at app/Http/Kernel.php file
'AdminAuth' => \App\Http\Middleware\AdminAuthenticate::class,
Now everything is okay. just add your new middleware in route group as follow
Route::group(['prefix' => 'admin', 'middleware' => 'AdminAuth'], function()
{
// all admin routes
});
Or you can add new middleware to constructor function of every admin controller as like below
$this->middleware('AdminAuth');
I use Laravel 5.2 and have a problem with middleware.
There is the code in the routes.php
use Illuminate\Contracts\Auth\Access\Gate;
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/', 'HomeController#index');
});
Route::group(['prefix'=>'admin', 'middleware' => 'admin'], function(){
Route::get('/', function(){
return view('admin.index');
});
Route::get('/user', function(){
return view('admin.user');
});
});
Kernel.php:
protected $routeMiddleware = [
...
'admin' => \App\Http\Middleware\AdminPanel::class,
];
AdminPanel.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use App\Role;
class AdminPanel
{
public function handle($request, Closure $next)
{
$user = Auth::user();
dd($user);
if($user){
$role = Role::whereName('admin')->first();
if($user->hasRole($role)){
return $next($request);
}
}
return redirect('/');
}
So, $user = Auth::user() always return null.
Thanks for suggestions!
I faced a situation where Auth::user() always returns null, it was because I was trying to get the User in a controller's constructor.
I realized that you can't access the authenticated user in your controller's constructor because the middleware has not run yet.
As an alternative, you can define a Closure based middleware directly in your controller's constructor.
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
class ProjectController extends Controller
{
protected $user;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
}
Any route that uses Auth() must be encapsulated in the web middleware. You're close, just move your Route::group(['prefix' => 'admin'], ...) into the group above.
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/', 'HomeController#index');
// Moving here will ensure that sessions, csrf, etc. is included in all these routes
Route::group(['prefix'=>'admin', 'middleware' => 'admin'], function(){
Route::get('/', function(){
return view('admin.index');
});
Route::get('/user', function(){
return view('admin.user');
});
});
});
Define middleware in the constructer of your controller and it will do the trick here
public function __construct()
{
$this->middleware('auth:api');
}
I had the same problem because i did not set the table name.
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'users';
I found a solution in an old code
function getAuth($guard, $get)
{
return auth($guard)->user()->$get;
}
add this ^ as a helper function and use it wherever you want
ex:
getAuth('user', 'id');
just include your authentication middleware in call
$user = auth('middleware')->user()
Route::middleware('auth:api')->group(function () {
Route::get('/details', 'UserController#details');
});
My Auth::user() return null in view when
I don't have users table in database
I don't have id field as primary key of table users