Singleton created twice - laravel

In Laravel 5.4 I have registered a Service Provider that creates a singleton to my Context class which holds application context.
ContextServiceProvider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App;
class ContextServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
// Set-up application context
$context = app('context');
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->singleton('context', function ($app) {
return new App\Context();
});
}
}
Then I create a Eloquent model with a global scope.
Model Media
namespace App\Models;
use App\Scopes\SchoolScope;
use Illuminate\Database\Eloquent\Model;
class Media extends Model
{
public static function boot()
{
parent::boot();
static::addGlobalScope(new SchoolScope());
}
}
Now when I access the Context singleton in the scope SchoolScope, the singleton is created twice!
SchoolScope
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use App\Models\School;
class SchoolScope implements Scope
{
protected $school;
public function __construct()
{
$this->school = app('context')->school;
}
public function apply(Builder $builder, Model $model)
{
$builder->where('school_id', '=', $this->school->id);
}
}
Does anyone know why the singleton is created twice?

Related

Why is a observer class not working in model?

I have a Base model that I used to extend in all other Models. I created an observer for it called BaseObserver and registered it at boot method of EventServiceProvider. I have a creating event and would like to put my logic there every time I create a new other Model.
The problem is that the creating method in BaseObserver is not being called. But, when I created a closure for creating in Base model, it worked. What seems to be the problem here?
Base.php
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\SoftDeletes;
class Base extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
// This closure will work but If I commented this out, BaseObserver's creating method won't work
protected static function booted()
{
static::creating(function ($base) {
dd('hellp from base model');
});
}
}
BaseObserver.php
namespace App\Observers;
use App\Models\Base;
class BaseObserver
{
public function creating(Base $base)
{
dd('hello from base obserer');
$base->created_by = auth()->user()?->_id;
}
public function updating(Base $base)
{
dd('hello from base obserer');
$base->updated_by = auth()->user()?->_id;
}
}
EventServiceProvider.php
namespace App\Providers;
use App\Models\Base;
use App\Observers\BaseObserver;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
public function boot()
{
Base::observe(BaseObserver::class);
}
public function shouldDiscoverEvents()
{
return false;
}
}
Team.php
namespace App\Models;
use App\Models\Base;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Team extends Base
{
use HasFactory;
protected $fillable = [
'name',
'leader_id',
'member_ids',
];
}
Result
it has to work
class Base extends Model
{
protected static function booted()
{
static::observe(BaseObserver::class);
}
}

How to Get Model Dynamic in Controller Using Laravel?

I'm trying to get model name on session. Using session I'm try too get model dynamic. But it is not work
My Code
<?php
namespace App\Exports;
use App\Http\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Session;
class Export implements WithHeadings
{
/**
* #return \Illuminate\Support\Collection
*/
public $table="";
public function headings(): array
{
$model="App\Http\Models\\".Session::get('tableName');
$this->table = new $model;
}
}

Can not get Request data in custom service?

I have custom service:
<?php
namespace App\Library\Services;
use Illuminate\Http\Request;
class RegisterCustomerService
{
private $request;
public function constructor(Request $request)
{
$this->request = $request;
}
public function register($role)
{
dd($this->request);
}
}
Why I can not get dd($this->request); when I do POST request:
$customer = $registerCustomerService->register('customer');
My service provider is:
class RegisterCustomerServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register(Request $request)
{
$this->app->bind('App\Library\Services\RegisterCustomerService', function ($app) {
return new RegisterCustomerService($request);
});
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
You don't need to bind the instance in the container because Laravel can automatically resolve the namespace and the class dependencies if you resolve an object through the container.
You can the remove the binding from the service provider and use:
$customer = app('App\\Library\\Services\\RegisterCustomerService')->register('customer');
In this way the container will resolve the Register customer service and will create that with all the needed dependencies (the request object in your example).

Can an Eloquent model has multiple Observer?

Hi I want write a trait to add an observer to model but I thought write boot method is not the right way and finnaly i find that i can boot trait like boot[TraitName] but i wonder if i add an observer with code like this:
trait CreateObserver
{
public static function bootCreateObserver()
{
static::creating(function (Model $model) {
// ...
});
}
}
can I add another observer for my model like below or it will overriding my trait observer?
class MyModel extends Model
{
use CreateObserver;
public static function boot()
{
static::creating(function ($model) {
// ...
});
}
...
}
That's not the right way. I think this might help you:
https://laravel.com/docs/5.6/eloquent#observers
You bind observers to your models using a service boot:
<?php
namespace App\Providers;
use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
Inside the observer you can add all desired functionality:
<?php
namespace App\Observers;
use App\User;
class UserObserver
{
/**
* Listen to the User created event.
*
* #param \App\User $user
* #return void
*/
public function created(User $user)
{
//
}
/**
* Listen to the User deleting event.
*
* #param \App\User $user
* #return void
*/
public function deleting(User $user)
{
//
}
}
And to elaborate. Yes it can have multiple observers. Although I never seen a useful situation for that:
public function boot()
{
User::observe(UserObserver::class);
User::observe(AuthenticableModelsObserver::class);
}
This way both the UserObserver() and AuthenticableModelsObserver() are binded to the User() model on boot.

Laravel policy always return false

I made a policy for one model.the policy class as following:
namespace App\Policies;
use App\User;
use App\Models\Address;
use Illuminate\Auth\Access\HandlesAuthorization;
class AddressPolicy
{
use HandlesAuthorization;
public function delete(User $user, Address $address)
{
return $user->id === $address->user_id ;
}
}
And I register the policy in authServiceProvider
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Models\Address ;
use App\Policies\AddressPolicy;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Address::class => AddressPolicy::class,
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
//
}
I use this policy in a controller
namespace App\Http\Controllers\User;
use App\Models\Address;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Auth ;
class AddressController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function destroy(Address $address)
{
$this->authorize('delete', $address);
$address->delete();
return response()->json(['msg'=>'success'], 200);
}
when I request the destroy method in the controller, it always return a 403 status, when I remove this line "$this->authorize ('delete', $address)",the data can be deleted.I've tried several solutions and searched many same problem, none of them resolved my problem.

Resources