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.
Related
I have managed this by extending the Form request like this:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use App\Http\Controllers\Root\RootController;
use App\Http\Controllers\Root\ConfigRootController;
class Request extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
//
];
}
/**
* Intercept the request and make changes
*
*/
protected function getValidatorInstance()
{
$data = $this->all();
RootController::setConn($data['url']);
$Config = ConfigRootController::get_tl_config($data['url']);
if(isset($data['cookie'])){
$User = ConfigRootController::getCurrentUser($data['url'],$data['cookie']);
$GLOBALS['user']=$User;
}
$GLOBALS['CONFIG'] = json_decode($Config->getBody()->getContents());
return parent::getValidatorInstance();
}
}
However this solution has a limitation as it does not allow me to use the $request->validate() method in the controller, which is a requirement.
Given that I am using laravel as a stateless API. I need to intercept all requests made and inject the script below right before the controller so that I can access and handle the config data as needed.
$data = $this->all();
RootController::setConn($data['url']);
$Config = ConfigRootController::get_tl_config($data['url']);
if(isset($data['cookie'])){
$User = ConfigRootController::getCurrentUser($data['url'],$data['cookie']);
$GLOBALS['user']=$User;
}
$GLOBALS['CONFIG'] = json_decode($Config->getBody()->getContents());
Here is an attempt via extending the Request class and applying the script in a constructor like so :
namespace App\Http\Requests;
// use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http;
use App\Http\Controllers\Root\RootController;
use App\Http\Controllers\Root\ConfigRootController;
class Request extends Http\Request
{
public function __construct()
{
$data = $this->all();
RootController::setConn($data['url']);
$Config = ConfigRootController::get_tl_config($data['url']);
if(isset($data['cookie'])){
$User = ConfigRootController::getCurrentUser($data['url'],$data['cookie']);
$GLOBALS['user']= json_decode($User->getBody()->getContents());
}
$GLOBALS['TL_CONFIG'] = json_decode($Config->getBody()->getContents());
}
}
This however results in a 500 internal server error from postman.
As it has been pointed out, the proper way to do this is via middleware :
First :
php artisan make:middleware BeforeRequest
Then in app\Http\Middleware\BeforeRequest.php :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Http\Controllers\Root\RootController;
use App\Http\Controllers\Root\ConfigRootController;
class BeforeRequest
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json'); //force the response to be json format
$data = $request->all();
RootController::setConn($data['url']);
$Config = ConfigRootController::get_tl_config($data['url']);
if(isset($data['cookie'])){
$User = ConfigRootController::getCurrentUser($data['url'],$data['cookie']);
$GLOBALS['user']= json_decode($User->getBody()->getContents());
}
$GLOBALS['TL_CONFIG'] = json_decode($Config->getBody()->getContents());
return $next($request);
}
}
Then in app\Http\Kernel.php :
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\BeforeRequest::class, //! add your middleware
];
And that is all.
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?
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
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
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.