I need to access to the current user in a service provider of a module. The Auth::user() returns null. I know the middleware is called after the service provider and that is why this is null. Is there any solution to this problem? it is my code
namespace Modules\User\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
use Nwidart\Modules\Facades\Module;
class ViewComposerProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = false;
/**
* Register the service provider.
*
* #return void
*/
public function boot()
{
$this->buildMenu();
$this->buildAvatar();
}
public function register()
{
dd(Auth::user());//null
}
private function buildAvatar(){
$f = Auth::user();
dd($f); // null
}
public function buildMenu()
{
view()->composer('layouts.subnavbar', function ($view) {
$t = \Nwidart\Modules\Facades\Module::getByStatus(1);
$modules = [];
foreach ($t as $item)
$modules[] = $item->name;
$view->with('modules', $modules);
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return [];
}
}
Instead of calling the user in the provider you could make 2 view composers, 1 for the menu and 1 for the avatar
AvatarComposer.php
class AvatarComposer
{
public function compose(View $view)
{
$avatar = Auth::user()->avatar//AVATAR HERE
$view->with('avatar', $avatar);
}
}
ModuleComposer.php
class ModuleComposer
{
public function compose(View $view)
{
$t = \Nwidart\Modules\Facades\Module::getByStatus(1);
$modules = [];
foreach ($t as $item)
$modules[] = $item->name;
$view->with('modules', $modules);
}
}
and then in the boot of your provider:
//make it public for all routes
View::composer('*', AvatarComposer::class);
View::composer('layouts.subnavbar', ModuleComposer::class);
Related
I'm using Http client for making outgoing HTTP requests. I've used it many places in the project.Now project has new requirement that I have to add a new header to every outgoing
requests. I can do this by adding it to every places. But I want to know , is there any kind of trigger or event which can give me ability to modify the headers just before the request send. There is an event Illuminate\Http\Client\Events\RequestSending which is only useful for inspecting the request.
This is possible to achieve without the need of a package. You can simple do something like this in a service provider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Http\Client\Factory as Http;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->extend(Http::class, function ($service, $app) {
return $service->withOptions(['foo' => 'bar']);
});
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
Yes, this is possible with a fantastic package here. After installing the package you just set the default headers like,
Http::withDefaultOptions([
'headers' => [
'X-Bar-Header' => 'bar'
],
]);
But I was unfortunate, the package was not installed with my laravel 9-dev. So I had to extract the code for me. First, create a Factory class in your app\HttpClient directory,
<?php
namespace App\HttpClient;
use Illuminate\Http\Client\Factory as BaseFactory;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Arr;
class Factory extends BaseFactory
{
protected $ignoreDefaultOptions = false;
protected $defaultOptions = [];
public function ignoreDefaultOptions()
{
$this->ignoreDefaultOptions = true;
return $this;
}
public function withoutDefaultOptions($keys = null)
{
if ($keys === null) {
return $this->ignoreDefaultOptions();
}
if (func_num_args() > 1) {
$keys = func_get_args();
}
$this->defaultOptions = with($this->defaultOptions, function ($options) use ($keys) {
foreach (Arr::wrap($keys) as $key) {
Arr::forget($options, $key);
}
return $options;
});
return $this;
}
public function withDefaultOptions(array $options)
{
$this->defaultOptions = array_merge_recursive($this->defaultOptions, $options);
return $this;
}
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}
if ($this->defaultOptions && ! $this->ignoreDefaultOptions) {
return tap(new PendingRequest($this), function ($request) {
$request->withOptions($this->defaultOptions)
->stub($this->stubCallbacks);
})->{$method}(...$parameters);
}
return parent::__call($method, $parameters);
}
}
Then, create a HttpServiceProver,
php artisan make:provider HttpServiceProvider
And put the following code there,
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Http\Client\Factory as BaseFactory;
use App\HttpClient\Factory;
class HttpServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->bind(
BaseFactory::class,
function ($app) {
return new Factory($app->make(Dispatcher::class));
}
);
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
Now, register the newly created service provider in AppServiceProvider.php
public function register()
{
//...
app()->register(HttpServiceProvider::class);
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//....
Http::withDefaultOptions([
'headers' => [
'X-Bar-Header' => 'bar'
],
]);
}
There are other options in this package. Please check it the package link for details.
In my laravel 8 iam define gate but there some problem my gate is accept only one model name is that Admin when i try to check another model name there are error show
here is my authserviceprovider
<?php
namespace App\Providers;
use App\Models\Admin\Role;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('isAdmin', function(Role $role) {
if ($role->role === 'Admin') {
return true;
} else {
return false;
}
});
}
}
here is controller
public function index(Role $role)
{
if (!Gate::allows('isAdmin', $role))
{
abort(403);
}
$users = Admin::with('roles')->get();
return view('Admin.user.index', compact('users'));
}
error message
TypeError
App\Providers\AuthServiceProvider::App\Providers{closure}(): Argument #1 ($role) must be of type App\Models\Admin\Role, App\Models\Admin given, called in D:\xampp\htdocs\education\vendor\laravel\framework\src\Illuminate\Auth\Access\Gate.php on line 477
http://127.0.0.1:8000/admin/users
Gate are mostly used to authored login user. if you need to authorise in any model specific then use policy
so in gate we get login user instance as call back automatically
so in your case code will be like this
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('isAdmin', function($user) {
return $user->role->name === 'Admin';
});
}
then in controller
public function index(Role $role)
{
abort_if(!Gate::allows('isAdmin'));
$users = Admin::with('roles')->get();
return view('Admin.user.index', compact('users'));
}
Using the nilportuguess' eloquent repository library, I made the following (with bugs) repository:
namespace App\Repositories;
use NilPortugues\Foundation\Infrastructure\Model\Repository\Eloquent\EloquentRepository;
use App\Model\Rover;
class RoverRepository extends EloquentRepository
{
/**
* {#inheritdoc}
*/
protected function modelClassName()
{
return Rover::class;
}
/**
* {#inheritdoc}
*/
public function find(Identity $id, Fields $fields = null)
{
$eloquentModel = parent::find($id, $fields);
return $eloquentModel->toArray();
}
/**
* {#inheritdoc}
*/
public function findBy(Filter $filter = null, Sort $sort = null, Fields $fields = null)
{
$eloquentModelArray = parent::findBy($filter, $sort, $fields);
return $this->fromEloquentArray($eloquentModelArray);
}
/**
* {#inheritdoc}
*/
public function findAll(Pageable $pageable = null)
{
$page = parent::findAll($pageable);
return new Page(
$this->fromEloquentArray($page->content()),
$page->totalElements(),
$page->pageNumber(),
$page->totalPages(),
$page->sortings(),
$page->filters(),
$page->fields()
);
}
/**
* #param array $eloquentModelArray
* #return array
*/
protected function fromEloquentArray(array $eloquentModelArray) :array
{
$results = [];
foreach ($eloquentModelArray as $eloquentModel) {
//This is required to handle findAll returning array, not objects.
$eloquentModel = (object) $eloquentModel;
$results[] = $eloquentModel->attributesToArray();
}
return $results;
}
}
And In order to locate them I thought to make an Integration test on an sqlite inmemory db:
namespace Test\Database\Integration\Repositories;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Repositories\RoverRepository;
use App\Model\Rover;
use App\Model\Grid;
class RoverRepositoryTest extends TestCase
{
use RefreshDatabase;
private $repository=null;
public function setUp(): void
{
parent::setUp();
$grid=factory(Grid::class)->create([
'width'=>5,
'height'=>5
]);
$rover=factory(Rover::class, 5)->create([
'grid_id' => $grid->id,
'grid_pos_x' => rand(0, $grid->width),
'grid_pos_y' => rand(0, $grid->height),
]);
//How do I run Migrations and generate the db?
$this->repository = new RoverRepository();
}
public function tearDown(): void
{
parent::tearDown();
//How I truncate and destroy Database?
}
/**
* Testing Base Search
*
* #return void
*/
public function testBasicSearch(): void
{
//Some Db test
}
}
But I have some questions:
How do I save the generated via factory Models?
How do I nuke my database in tearDown()?
I create a request in App\Http\Requests\Web in which it shows me the error.
Class 'App\Http\Requests\Web\WebRequest' not found
Here is the code of my Request CreateBucket.php:
<?php
namespace App\Http\Requests\Web;
class CreateBucket extends WebRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'bucket_name' => 'required|string|string|max:30',
'bucket_type' => 'required|string|string|max:30',
'bucket_image' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg',
];
}
}
And Here is my code of Bucket Controller:
<?php
namespace App\Http\Controllers\Web;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\Web\CreateBucket;
use App\Bucket;
class BucketController extends Controller
{
public function index(Request $request)
{
$buckets = Bucket::orderBy('id','ASC')->paginate(10);
return view('buckets.index',compact('buckets',$buckets))
->with('i',($request->input('page',1) - 1) * 10);
}
public function create()
{
return view('buckets.create');
}
public function store(CreateBucket $request)
{
if($request->hasFile('bucket_image')) {
$bucket_image = $request->file('bucket_image');
$bucket_image_name = time().'.'.$bucket_image->getClientOriginalExtension();
$path = public_path('Storage/BucketImages');
$bucket_image->move($path, $bucket_image_name);
$bucket_image = 'Storage/BucketImages/'.$bucket_image_name;
} else {
$bucket_image = NULL;
}
$category = Category::create([
'bucket_name' => $request->input('bucket_name'),
'bucket_image'=> $bucket_image,
'bucket_type' => $request->input('bucket_type'),
]);
return redirect()->route('buckets.index')
->with('success','Bucket created successfully');
}
Please Help me to resolve this error. Thanks.
My WebRequest.php is missing in Requests folder that why he gave me this Error.
Here is the WebRequest.php file I created and my issue is resolve.
<?php
namespace App\Http\Requests\Web;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
class WebRequest 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 [
//
];
}
}
I'm trying to test a model Observer for my User class and I'm experiencing the same problems as many other programmers.
The updating/updated/... events won't fire when using PHPUnit. Trying it with tinker works.
So here's the problem: I tried this solution. Unfortunately without success.
This is my TestClass:
class UserObserverTest extends TestCase {
use DatabaseTransactions;
public function setUp()
{
parent::setUp();
$this->user = factory("App\User")->create();
$this->plan = new UserSettings();
$this->difficulty1 = factory("App\Difficulty")->create();
$this->difficulty2 = factory("App\Difficulty")->create();
$this->plan->getExercisePlan()->appendAppExercise(factory("App\Exercise")->create(), false, $this->difficulty1, Constants::VORWAERTS);
$this->plan->getExercisePlan()->appendAppExercise(factory("App\Exercise")->create(), false, $this->difficulty2, Constants::VORWAERTS);
$this->user->settings = $this->plan->toJson();
$this->user->save();
$this->user = $this->user->fresh();
}
public function test_Difficulty2HasUsedCounter0AfterDeletingFromPlan()
{
$this->assertEquals(1, $this->difficulty2->fresh()->used);
$plan = new UserSettings($this->user->settings);
$exercises = $plan->getExercisePlan()->getExercisesArray();
array_pull($exercises, 1);
$this->user->settings = $plan->toJson();
$this->user->save();
$this->assertEquals(0, $this->difficulty2->fresh()->used);
}
}
UserObserver:
class UserObserver
{
/**
* Listen to the User updating event
* #param User $user
*/
public function updating(User $user)
{
$settings = new UserSettings($user->settings);
foreach($settings->getExercisePlan()->getExercisesArray() as $exercise)
{
$difficulty = Difficulty::find($exercise->getDifficultyId());
$difficulty->used--;
$difficulty->save();
}
}
/**
* Listen to the user updated event
* #param User $user
*/
public function updated(User $user)
{
$settings = new UserSettings($user->settings);
foreach($settings->getExercisePlan()->getExercisesArray() as $exercise)
{
$difficulty = Difficulty::find($exercise->getDifficultyId());
$difficulty->used++;
$difficulty->save();
}
}
/**
* Listen to the User deleting event.
*
* #param User $user
* #return void
*/
public function deleting(User $user)
{
$settings = new UserSettings($user->settings);
foreach($settings->getExercisePlan()->getExercisesArray() as $exercise)
{
$difficulty = Difficulty::find($exercise->getDifficultyId());
$difficulty->used--;
$difficulty->save();
}
}
}
I registered the Observer using User::observe(UserObserver::class); inside boot() of AppServiceProvider