Итак, что я в основном пытаюсь сделать, так это реорганизовать свой длинный фрагмент кода на что-то более простое. Я нашел этот фрагмент кода в этом Веб-сайт, и я действительно не понимаю, что происходит внутри кода. Я не думаю, что этот фрагмент кода будет работать, учитывая, что я использую другие политики и методы, чем стандартные.
Фрагмент кода с сайта:
//PermissionsServiceProvider.php
public function boot()
{
Permission::get()->map(function($permission){
Gate::define($permission->slug, function($user) use ($permission){
return $user->hasPermissionTo($permission);
});
});
}
Может кто-нибудь объяснить, что именно происходит в этом фрагменте кода?
Мой код:
// Posts Policy
Gate::define('post.view', 'App\Policies\Blog\PostsPolicy@view');
Gate::define('post.create', 'App\Policies\Blog\PostsPolicy@create');
Gate::define('post.update', 'App\Policies\Blog\PostsPolicy@update');
Gate::define('post.delete', 'App\Policies\Blog\PostsPolicy@delete');
Gate::define('post.publish', 'App\Policies\Blog\PostsPolicy@publish');
Gate::define('post.edit', 'App\Policies\Blog\PostsPolicy@edit');
Gate::define('post.global', 'App\Policies\Blog\PostsPolicy@global');
// Categories Policy
Gate::define('category.view', 'App\Policies\Blog\CategoriesPolicy@view');
Gate::define('category.create', 'App\Policies\Blog\CategoriesPolicy@create');
Gate::define('category.update', 'App\Policies\Blog\CategoriesPolicy@update');
Gate::define('category.delete', 'App\Policies\Blog\CategoriesPolicy@delete');
Gate::define('category.edit', 'App\Policies\Blog\CategoriesPolicy@edit');
Gate::define('category.global', 'App\Policies\Blog\CategoriesPolicy@global');
// Tags Policy
Gate::define('tag.view', 'App\Policies\Blog\TagsPolicy@view');
Gate::define('tag.create', 'App\Policies\Blog\TagsPolicy@create');
Gate::define('tag.update', 'App\Policies\Blog\TagsPolicy@update');
Gate::define('tag.delete', 'App\Policies\Blog\TagsPolicy@delete');
Gate::define('tag.edit', 'App\Policies\Blog\TagsPolicy@edit');
Gate::define('tag.global', 'App\Policies\Blog\TagsPolicy@global');
// Parts Section Policy
Gate::define('part.section.view', 'App\Policies\Parts\PartSectionsPolicy@view');
Gate::define('part.section.create', 'App\Policies\Parts\PartSectionsPolicy@create');
Gate::define('part.section.update', 'App\Policies\Parts\PartSectionsPolicy@update');
Gate::define('part.section.delete', 'App\Policies\Parts\PartSectionsPolicy@delete');
Gate::define('part.section.edit', 'App\Policies\Parts\PartSectionsPolicy@edit');
Gate::define('part.section.global', 'App\Policies\Parts\PartSectionsPolicy@global');
// Parts Policy
Gate::define('part.view', 'App\Policies\Parts\PartsPolicy@view');
Gate::define('part.create', 'App\Policies\Parts\PartsPolicy@create');
Gate::define('part.update', 'App\Policies\Parts\PartsPolicy@update');
Gate::define('part.delete', 'App\Policies\Parts\PartsPolicy@delete');
Gate::define('part.edit', 'App\Policies\Parts\PartsPolicy@edit');
Gate::define('part.global', 'App\Policies\Parts\PartsPolicy@global');
// Admin Management Policy
Gate::define('admin.global', 'App\Policies\AdminManagementPolicy@global');
// User Management Policy
Gate::define('user.global', 'App\Policies\UserManagementPolicy@global');
Есть ли способ сделать это с помощью цикла foreach из моей таблицы разрешений? Вот какой-то псевдокод:
foreach($permissions as $permission) {
Gate::define($permission->slug, 'App\Policies\' . $permission->category . 'Policy@' . $permission->name);
}
Вопрос: Есть ли способ сделать мой код более компактным и более удобным для чтения, как фрагмент кода с веб-сайта?






Лично ваш существующий код в порядке. Оно работает. Это читается. Хотя по мере роста вашего приложения он может становиться более подробным, этого может и не случиться. Так зачем это улучшать?
Тем не менее, вот несколько идей. Большая часть вашего кода - это соответствие между разрешением и реализацией политики. Например, 'part.view' отображается на 'App\Policies\Parts\PartsPolicy@view. «Вес» этого сопоставления не может быть удален: его можно только перемещать.
Вы можете подумать о переносе его в более простой файл конфигурации, который выглядит примерно так:
// config/permission-map.php
<?php return [
'post.view' => 'App\Policies\Blog\PostsPolicy@view',
'post.create' => 'App\Policies\Blog\PostsPolicy@create',
'post.update' => 'App\Policies\Blog\PostsPolicy@update',
'post.delete' => 'App\Policies\Blog\PostsPolicy@delete',
// etc...
];
Затем в загрузке вы читаете эту конфигурацию и повторяете:
// boot permissions
$permission_map = require_once('config/permission_map.php');
foreach ($permission_map as $permission => $policy_implementation) {
Gate::define($permission, $policy_implementation);
}
Преимущество: добавление нового сопоставления политик изменяет только самую важную информацию, и вам не нужно думать о том, как сделать это сопоставление - сегодня это Gate::define, а завтра, возможно, это Sentry::policy. Кроме того, отделив данные от кода, вы можете более свободно тестировать код.
Другим подходом могут быть аннотации: в DocBlock вашей реализации политики вы пишете собственный синтаксис аннотации, который затем анализируете и компилируете в файл конфигурации. По линиям
namespace App\Policies\Blog;
class PostsPolicy {
/**
* @permission post.view
*/
public function view() { /* ... */ }
}
Я лично не фанат этого: это добавляет слой внутренней структуры, ценность которой мне трудно измерить.
Во-первых, автор этой статьи вообще не использовал политики, он создал таблицу разрешений, а затем привязал созданные им разрешения к воротам laravel с помощью фрагмента кода.
Permission::get()->map(function($permission){
Gate::define($permission->slug, function($user) use ($permission){
return $user->hasPermissionTo($permission);
});
});
Давайте разберем это строка за строкой
Permission::get() // Query all permissions defined in permissions database table
->map(function($permission){ // Foreach permission do the following
Gate::define($permission->slug, // Create new gate with the permission slug
function($user) use ($permission){
return $user->hasPermissionTo($permission); // the user table has many to many relation with permissions table, here we only check if $user is associated with $permission
});
});
Чтобы сделать ваш код более динамичным, я предлагаю вам сделать следующее:
Создать таблицу базы данных permission
Создать таблицу базы данных roles
Создать сводную таблицу базы данных permission_role
Создать сводную таблицу базы данных role_user
Роль имеет множество разрешений (отношение "многие ко многим", определите это с помощью belongsToMany)
Разрешение принадлежит многим ролям (отношение многие ко многим, определите его с помощью belongsToMany)
У пользователя много ролей (отношение "многие ко многим", определите это с помощью belongsToMany)
globalИспользуя Gate::before, вы можете разрешить конкретному пользователю, имеющему разрешение global или root, авторизовать все определенные возможности:
Gate::before(function ($user, $ability) {
if ($user->hasPermission('root-access')) {
return true;
}
});
Если вы реализуете разрешения базы данных, вам больше не нужно создавать политики для каждой модели, и ворота будут определяться с использованием приведенного выше кода динамически.