При попытке загрузить роли с назначенными пользователями из библиотеки laravel-permissions Spatie, как это
use Spatie\Permission\Models\Role;
Role::with('users')->get();
Эта ошибка возникает
Ошибка: имя класса должно быть допустимым объектом или строкой в файле vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php в строке 791.
Приведенный выше код отлично работает в Laravel PsySH с питанием от Repl Tinker , см. этот пост StackOverflow
Поэтому я подумал, что если это происходит только в HTTP-запросах, это должно быть связано с проблемой промежуточного программного обеспечения.
Я использую Laravel Sanctum для аутентификации API, поэтому маршрут находится под промежуточным программным обеспечением auth:sanctum
в routes/api.php
Route::middleware('auth:sanctum')->group(function () {
Route::get('/roles', [RolesController::class, 'index']);
});
Это также работает, если я перемещаю маршрут из промежуточного программного обеспечения, но я не должен этого делать, поскольку только аутентифицированные пользователи должны иметь доступ к этой конечной точке.
Я предполагаю, что это как-то связано с тем, что роли создаются с помощью guard_name as web в базе данных по умолчанию, но я не уверен, как это исправить.






в config/auth.php добавьте это в массив guards
'sanctum' => [
'driver' => 'sanctum',
'provider' => 'users'
],
Проблема в том, что поставщик услуг Sanctum устанавливает защиту аутентификации со значением null для поставщика, см. исходный код здесь
class SanctumServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
config([
'auth.guards.sanctum' => array_merge([
'driver' => 'sanctum',
'provider' => null, // <=== This is the issue
], config('auth.guards.sanctum', [])),
]);
if (! app()->configurationIsCached()) {
$this->mergeConfigFrom(__DIR__.'/../config/sanctum.php', 'sanctum');
}
}
Это вызывает вспомогательную функцию getModelForGuard() Laravel-Permission здесь
function getModelForGuard(string $guard)
{
return collect(config('auth.guards'))
->map(fn ($guard) => isset($guard['provider']) ? config("auth.providers.{$guard['provider']}.model") : null)
->get($guard);
}
ничего не возвращать, когда промежуточное ПО требует аутентификации охранника Sanctum, поэтому нетерпеливая загрузка не удалась здесь
/**
* A role belongs to some users of the model associated with its guard.
*/
public function users(): BelongsToMany
{
return $this->morphedByMany(
// Error occurs here
getModelForGuard($this->attributes['guard_name'] ?? config('auth.defaults.guard')),
'model',
config('permission.table_names.model_has_roles'),
app(PermissionRegistrar::class)->pivotRole,
config('permission.column_names.model_morph_key')
);
}
После ручной вставки защиты в auth/config.php с подходящим провайдером активная загрузка снова работает.
'guards' => [
...
'sanctum' => [
'driver' => 'sanctum',
'provider' => 'users'
]
],