Шлюз авторизации не вызывается во время поставщика услуг

У меня есть ворота 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 во время того же запроса также работает нормально, поэтому ворота определенно определены и в принципе работают.

PS: Когда я перемещаю C::observe() из ObserverServiceProvider в C::boot(), все работает нормально, но я хочу, чтобы все наблюдатели были зарегистрированы в одном месте.

Johannes Trümpelmann 10.04.2019 17:50
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
1
433
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Шлюз авторизации не может быть вызван, поскольку данные сеанса (и, следовательно, аутентифицированный пользователь) предоставляются промежуточным программным обеспечением 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);
      }
    });
  }
}

Другие вопросы по теме