Laravel | Middleware binding not accessible in controller - php

I have a middleware which just grabs the sub domain and binds it to the Store model.
<?php
namespace App\Http\Middleware;
use Closure;
use App\Models\Store;
class SubDomain
{
/**
* 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)
{
$sub_domain = array_first(explode('.', $request->getHost()));
app()->bind(Store::class, function () use ($sub_domain) {
return Store::query()->where('sub_domain', $sub_domain)->firstOrFail();
});
return $next($request);
}
}
However, when I am inside of a controller I am trying to extend it so I can always do $this->store->id or something alike however, the Store isn't getting found.
<?php
namespace App\Http\Controllers;
use App\Models\Store;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
/**
* #var Store
*/
protected $store;
/**
* Controller constructor.
*
* #param Store $store
*/
public function __construct(Store $store)
{
$this->store = $store;
}
}
The store is always just a basic model with no data.
This is my route:
Route::group(['middleware' => ['auth', 'sub_domain'], 'prefix' => 'admin'], function () {
Route::get('/dashboard', 'Admin\DashboardController#index');
});
And I have registered the sub_domain middleware inside of the Kernel.

The service container and model do not work how you are expecting in your code. So try with the following code snippet inside the controller's method. You may get what you are looking for.
$store = app(Store::class);
dd($store);

You want to bind an instance of a model so use app()->instance(Store::class, $store)
ref: https://laravel.com/docs/5.7/container#binding

Related

Laravel route middleware outputting my log

I'm trying to run some middleware on my routes via my package's service provider before the routes run in my Laravel project but I'm not seeing my var_dump despite running php artisan route:list showing that the BeforeMiddleware is applied. Am I using the wrong middleware?
My service provider:
<?php
namespace Company\FudgeInboundManagementBridge;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Company\FudgeInboundManagementBridge\Http\Middleware\BeforeMiddleware;
class FudgeInboundManagementBridgeServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
$this->registerFiles();
}
/**
* Register files
*/
protected function registerFiles(): void
{
Route::middleware(BeforeMiddleware::class)->group(function () {
$this->loadRoutesFrom(__DIR__.'/routes/fudge-routes.php');
});
$this->publishes([
__DIR__ . '/config/FudgeInboundManagementBridge.php' => config_path('FudgeInboundManagementBridge.php'),
], 'config');
}
}
My middleware:
<?php
namespace Company\FudgeInboundManagementBridge\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class BeforeMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
var_dump('hello from before middleware - bridge');
die;
// return $next($request);
}
}
Seems like it's not triggering?

Laravel 5.5 multi language application

I followed this article on how to make your site multi language.
But I don't understand why I always get an error when I surf to hoemstead.app/lang/en for example.
The error:
Sorry, the page that you're looking for does not exist
My LanguageController
use Config;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;
class LanguageController extends Controller
{
public function switchLang($lang)
{
if (array_key_exists($lang, Config::get('languages'))) {
Session::put('applocale', $lang);
}
return Redirect::back();
}
}
My routes:
Route::get('lang/{lang}', ['as'=>'lang.switch', 'uses'=>'LanguageController#switchLang']);
My Language Middleware
use Closure;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;
class Language
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Session::has('applocale') AND array_key_exists(Session::get('applocale'), Config::get('languages'))) {
App::setLocale(Session::get('applocale'));
}
return $next($request);
}
}
I've also added this middleware to my Kernel.php file
My Languages.php file in the config folder
return [
'en' => 'English',
'nl' => 'Nederlands',
'fr' => 'Français',
];

Creating Multiple Auth Providers in Lumen

I am trying to create multiple Auth Guards and services for my API. I want specific group to be available to specific users (more like RBAC without sessions).
If a user tries to access a group that has admin:auth as middleware its privileges will be checked. If it has api:auth then no privilege check.
I can't understand how to do this. I have added the following lines in the bootstrap/app.php
$app->routeMiddleware([
'admin' => App\Http\Middleware\Admin::class,
'api' => App\Http\Middleware\Api::class,
]);
And:
$app->register(App\Providers\AdminServiceProvider::class);
$app->register(App\Providers\ApiServiceProvider::class);
and created the Files Admin.php and APi.php in Middleware folder with the following content (basically same as Authenticate.php with name changes)
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Factory as Auth;
class Admin
{
/**
* The authentication guard factory instance.
*
* #var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Auth\Factory $auth
* #return void
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/**
* 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 ($this->auth->guard($guard)->guest()) {
return response('Unauthorized.', 401);
}
return $next($request);
}
}
And the AdminServiceProvider and ApiServiceProvider in the App\Providers folder with just this in function boot():
var_dump($this->app['api']);exit;
And this on top:
namespace App\Providers;
use App\User;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
class ApiServiceProvider extends ServiceProvider
But I get the Following Error:
What am I missing? I have already done composer dump-autoload, no difference.
Regards
Well what I ended up using is more like a work around, but I think this might be how it is supposed to be used.
So what I did was that I created two groups (a parent and a child) with the middlewares I needed as follows:
$app->group(["middleware" => "middleware1"], function() use ($app){
$app->group(["middleware" => "middleware1"], function() use ($app){
$app->post("/signin", "AppController#signin");
}
}
This way, the signin route is reached after going through 2 middlewares.
Regards

Extending Laravel base controller

I am a newbie in Laravel framework and I want to extend a base controller which in turn extends controller. However, I discovered that when I do that, my controller no longer recognises my session variables.
Here is my code
namespace App\Http\Controllers\Settings;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Auth\PermissionController;
use App\Fee;
class FeeController extends PermissionController
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
dd(session('userdata')['user_urls']);
$data['title']="Fees";
$data['fees']=Fee::all();
return view('settings.fee.index',$data);
}
And this is my PermissionController code
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PermissionController extends Controller {
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct(Request $request) {
if(!session('userdata')['user_urls']->contains($request->path())){
dd(session('userdata')['user_urls']);
}
}
}
But I realize that my session('userdata')['user_urls'] becomes null at the PermissionController. But if I make FeeController to extend Controller, my session variables are intact.
I need to use the session variables for some control at the permission controller.
I am running Laravel 5.3 on a MAC OSX and PHP 7
I have figured out the problem. Actually, PermissionController is not registered in the web middleware group so that session is not persisting in the PermissionController. So the solution to your question is just make a trait named as Permission instead of the controller and use it in FeesContorller.
trait Permission{
public function permission(Request $request) {
if($request->session()->get('name') != null){
echo "Hello World";
}
}
}
And FeesController like this:
class FeesController extends Controller
{
use Permission;
public function index(Request $request)
{
$this->permission($request); // the method of the trait.
echo "\n".$request->session()->get('name');
}
}
Output:
If the name attribute is set in session then :
Hello World
Passion Infinite
Otherwise
No Output // null
I have solved the same problem with middleware. I have created a middleware that takes care of the authorization of requests by checking the session to ensure that the controller action being accessed is available in session.
This is the middleware
namespace App\Http\Middleware;
use Closure;
class PermissionMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$currentAction = \Route::currentRouteAction();
list($nothing,$route_action) = explode('App\Http\Controllers\\', $currentAction);
$user_actions=session('userdata')['user_urls'];
if((empty($user_actions))||!$user_actions->contains($route_action)){
return redirect('denied');
}
return $next($request);
}
}
This is the controller
namespace App\Http\Controllers\Settings;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Auth\PermissionController;
use App\Fee;
class FeeController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$data['title']="Fees";
$data['fees']=Fee::all();
return view('settings.fee.index',$data);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create(Request $request)
{
$data['title']='New Fee';
return view('settings.fee.create',$data);
}
So, instead of using the routes (cos of some other reasons), I used the controller actions.
So, once a user logs in, all the controller actions he can access are loaded into session. When he tries to perform any action, the middleware, does the check to ensure he is allowed to perform that action. Otherwise, he is routed away.
So, I either add 'permission' to the routes middleware or call
$this->middleware('permission')
on the controller's construct method.
That is working for me now.
Thank you everybody for your contributions.

Laravel: How to access session value in AppServiceProvider?

Is there any way available to access Session values in AppServiceProvider? I would like to share session value globally in all views.
You can't read session directly from a service provider: in Laravel the session is handled by StartSession middleware that executes after all the service providers boot phase
If you want to share a session variable with all view, you can use a view composer from your service provider:
public function boot()
{
view()->composer('*', function ($view)
{
$view->with('your_var', \Session::get('var') );
});
}
The callback passed as the second argument to the composer will be called when the view will be rendered, so the StartSession will be already executed at that point
Add new web middleware ShareDataForView
in \app\Http\Kernel.php:
protected $middlewareGroups = [
'web' => [
// ...
\Illuminate\Session\Middleware\StartSession::class,
// I will always ShareDataForView after StartSession
\App\Http\Middleware\ShareDataForView::class,
...
and write your code in method "handle" of app\Http\Middleware\ShareDataForView.php, for example:
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Closure;
use Log, Exception, View;
class ShareDataForView
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Auth::user();
$bank = NULL;
if ( $user ){
$bank = $user->bank;
}
View::share('user', $user);
session()->put(['bank' => $bank]);
return $next($request);
}
}
The following works for me on Laravel 5.2, is it causing errors on your app?
AppServiceProvider.php
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
\Session::put('lang', 'en_US');
view()->share('lang', \Session::get('lang', 'de_DE'));
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
home.blade.php
<h1>{{$lang}}</h1>
Shows "en_US" in the browser.

Categories