У меня есть ворота admin
, определенные в моем AuthServiceProvider
, которые используются для добавления глобальных областей запросов к некоторым моделям. Предположим, у меня есть модели A
, за которыми наблюдает Observer
(зарегистрированный в AppServiceProvider
), и B
, которые используют ворота admin
для добавления глобальных областей запроса.
// app/Providers/AuthServiceProvider.php
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::define('admin', [static::class, 'admin']);
}
public static function admin(User $user): bool
{
return $user->group->name === 'Admin';
}
}
// app/B.php
class B extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
До этого момента все работало нормально. Затем я добавил модель C
, которая имеет Observer
и использует ворота admin
. Поскольку C::observe()
срабатывает C::boot()
, а AppServiceProvider
регистрируется до AuthServiceProvider
, ворота не были определены, и я извлек регистрацию Observer
в новый ObserverServiceProvider
, зарегистрированный после AuthServiceProvider
.
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
// app/Providers/ObserverServiceProvider.php
class ObserverServiceProvider extends ServiceProvider
{
public function boot()
{
A::observe(AObserver::class);
C::observe(CObserver::class);
}
}
// config/app.php
'providers' => [
//...
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
//...
App\Providers\ObserverServiceProvider::class,
]
Моя проблема:
Наблюдатели для A
и C
все еще работают, а также admin
вентиль в B
методе boot()
, но Gate::allows('admin')
в C
всегда возвращает false
, даже не вызывая функцию вентиля.
Добавление var_dump(Gate::has('admin'))
в C::boot()
выходы true
и использование @can('admin')
позже в View
во время того же запроса также работает нормально, поэтому ворота определенно определены и в принципе работают.
Шлюз авторизации не может быть вызван, поскольку данные сеанса (и, следовательно, аутентифицированный пользователь) предоставляются промежуточным программным обеспечением StartSession
, которое запускается после поставщиков услуг.
Проблему можно решить, поместив проверку Gate::allows()
внутрь анонимной функции, чтобы она выполнялась только при построении запроса:
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
static::addGlobalScope('public', function ($query) {
if (!Gate::allows('admin')) {
$query->where('public', true);
}
});
}
}
PS: Когда я перемещаю
C::observe()
изObserverServiceProvider
вC::boot()
, все работает нормально, но я хочу, чтобы все наблюдатели были зарегистрированы в одном месте.