Как заставить новую функцию Laravel автоматического обнаружения политики работать с моими моделями в другой папке?

#php #laravel-5.8

#php #laravel-5.8

Вопрос:

Я только что обновил свой Laravel до версии 5.8 и не могу заставить автоматическое обнаружение политик работать.

Я думаю, это потому, что все мои модели находятся в приложении / Models. В документации говорится, что я могу изменить поведение по умолчанию с помощью этого элемента управления.

 Gate::guessPolicyNamesUsing(function ($modelClass) {
    // return policy class name...
});
  

Но я не могу заставить это работать. Функция проверки «‘$user-> can()»‘ всегда возвращает false для всех моих политик и моделей.
Это действительно проблема? Папка models, или я что-то упускаю?

Кстати, все отлично работает, если я сопоставлю это вручную в массиве $ policies в AuthServiceProvider.php

Спасибо!

Ответ №1:

Если у кого-то есть эта проблема, вот как я ее исправил.

Оказалось, что проблема заключалась в App/Models структуре. Волшебство, совершаемое laravel для угадывания имени политики, учитывает местоположение модели.

Чтобы обойти это поведение, поместите приведенный ниже код внутрь app/Providers/AuthServiceProvider.php в функцию загрузки.

 Gate::guessPolicyNamesUsing(function ($modelClass) {
    return 'App\Policies\' . class_basename($modelClass) . 'Policy';
});
  

Это заставит смотреть на App/Policies вместо App/Models/Policies . (измените соответствующим образом)

И тогда я понял, что папка Policies должна быть размещена внутри App/Models , потому что именно в ней находится модель, но, эй, кто знает? Я предполагаю, что помещение моих моделей в другую папку усложнит мне жизнь.

Пока, надеюсь помочь кому-нибудь в будущем.

Ответ №2:

На всякий случай, если кто-то изменил имя папки приложения, как это сделал я, вы можете использовать следующий код:

     Gate::guessPolicyNamesUsing(function ($modelClass) {
        $classDirnameArray = explode('\', str_replace('/', '\', dirname(str_replace('\', '/', $modelClass))));
        if ($classDirnameArray[0] === app()::APP_FOLDER) {
            $classDirnameArray =  array_slice($classDirnameArray, 1);
        }
        return app()::APP_FOLDER.'\Policies\'. implode("\",$classDirnameArray) . "\" . class_basename ( $modelClass).'Policy';
    });
  

Имейте в виду, что вы, вероятно, изменили путь к имени приложения в Application.php file, итак, что я сделал, так это создал постоянную переменную, APP_FOLDER которая содержит строку имени папки приложения, и я могу просто вызывать ее везде, где я использую app()::APP_FOLDER .

Т.е. если у вас есть модель, MyAppModelsCoreUser предположительное название политики будет MyAppPoliciesModelsCoreUser .

Любые проблемы, не стесняйтесь спрашивать меня об этом, и я надеюсь, что это тоже может помочь.

PS: Я использовал PHP v7.2.9 и Laravel v5.8.37