Orchid CRUD for Laravel
建议编辑介绍
Orchid 为编写应用程序提供了独特的体验。但有时,当需要执行简单的 CRUD 操作时,可能显得有些过于复杂。因此,我们创建了一个新包,旨在帮助开发者快速为 Eloquent 模型创建用户界面,支持创建、读取、更新和删除等功能。
您可以使用一个文件描述整个过程。当您需要更多选项时,可以轻松切换到使用平台。所有字段、过滤器和特性都是兼容的。
安装
您可以使用 Composer 安装该包。在命令行中运行:
$ composer require orchid/crud
这将更新 composer.json
并将包安装到 vendor/
目录中。
定义资源
资源存储在应用程序的 app/Orchid/Resources
目录中。您可以使用 orchid:resource
Artisan 命令生成一个新资源:
php artisan orchid:resource PostResource
资源的最基本属性是其 model
属性。这个属性告诉生成器资源对应哪个 Eloquent 模型:
use App\Models\Post;
/**
* 资源对应的模型。
*
* @var string
*/
public static $model = Post::class;
这些类是完全静态的。由于其声明性质,它们没有任何状态。它们只告诉要做什么,不持有任何数据。因此,如果您添加自定义方法,请确保它们是静态的。
新创建的资源不包含任何内容。别担心,我们很快会为我们的资源添加更多字段。
注册资源
app/Orchid/Resources
目录中的所有资源默认会自动注册。您不需要手动注册它们。但如果需要,例如在创建附加包时,最佳方式是:
use App\Orchid\Resources\UserResource;
use Illuminate\Support\ServiceProvider;
use Orchid\Crud\Arbitrator;
class CrudServiceProvider extends ServiceProvider
{
/**
* 启动任何应用程序服务。
*
* @return void
*/
public function boot(Arbitrator $arbitrator)
{
$arbitrator->resources([
UserResource::class,
]);
}
}
模型扩展
Orchid 平台的许多功能依赖于模型自定义。您可以根据目标添加或移除特性。但我们假设您已为模型设置了这些特性:
use Illuminate\Database\Eloquent\Model;
use Orchid\Attachment\Attachable;
use Orchid\Filters\Filterable;
use Orchid\Screen\AsSource;
class Post extends Model
{
use AsSource, Filterable, Attachable;
}
定义字段
每个资源都包含一个 fields
方法。该方法返回一个字段数组,通常扩展自 Orchid\Screen\Field
类。要向资源添加字段,我们可以将其添加到资源的 fields
方法中。通常,字段可以使用其静态 make
方法创建。该方法接受几个参数;然而,您通常只需传递字段的名称。
use Orchid\Screen\Fields\Input;
/**
* 获取资源显示的字段。
*
* @return array
*/
public function fields(): array
{
return [
Input::make('title')
->title('Title')
->placeholder('Enter title here'),
];
}
在生成 CRUD 的包中,您可以使用 Orchid 平台的字段。查看文档站点上的所有可用字段。
定义列
每个资源都包含一个 сolumns
方法。要向资源添加列,我们可以将其添加到资源的 column
方法中。通常,列可以使用其静态 make
方法创建。
use Orchid\Screen\TD;
/**
* 获取资源显示的列。
*
* @return TD[]
*/
public function columns(): array
{
return [
TD::make('id'),
TD::make('title'),
];
}
CRUD 生成包完全基于表层。您可以在文档页面上阅读更多关于此的信息。
定义图例
每个资源都包含一个 legend
方法。它决定了模型在查看时的外观。要添加到资源中,我们可以将其添加到资源的 legend
方法中。通常,列可以使用其静态 make
方法创建。
use Orchid\Screen\Sight;
/**
* 获取资源显示的视图。
*
* @return Sight[]
*/
public function legend(): array
{
return [
Sight::make('id'),
Sight::make('title'),
];
}
CRUD 生成包完全基于图例层。您可以在文档页面上阅读更多关于此的信息。
定义规则
每个资源都包含一个 rules
方法。在提交创建或更新表单时,可以验证数据,这在 rules
方法中描述:
/**
* 获取适用于保存/更新的验证规则。
*
* @return array
*/
public function rules(Model $model): array
{
return [
'slug' => [
'required',
Rule::unique(self::$model, 'slug')->ignore($model),
],
];
}
您可以在 Laravel 的验证页面上了解更多信息。
定义过滤器
每个资源都包含一个 filters
方法。该方法期望您返回一个类名列表,这些类名应被渲染,并在必要时替换为查看的模型。
/**
* 获取资源可用的过滤器。
*
* @return array
*/
public function filters(): array
{
return [];
}
要创建新过滤器,有一个命令:
php artisan orchid:filter QueryFilter
这将在 app/Http/Filters
文件夹中创建一个类过滤器。要在您自己的资源中使用过滤器,您需要:
public function filters(): array
{
return [
QueryFilter::class
];
}
我们已经提供了一些准备好的过滤器:
Orchid\Crud\Filters\DefaultSorted
– 设置默认列排序Orchid\Crud\Filters\WithTrashed
– 显示已删除的记录
public function filters(): array
{
return [
new DefaultSorted('id', 'desc'),
];
}
您可以在 Orchid 的过滤页面上了解更多信息。
导航
如果您不希望资源出现在导航中,可以重写资源类的 displayInNavigation
方法:
/**
* 获取资源是否应显示在导航中
*
* @return bool
*/
public static function displayInNavigation(): bool
{
return false;
}
预加载
假设您经常需要在字段中访问资源的关系。在这种情况下,最好将关系添加到资源的 with
属性中。此属性指示在检索资源时始终预加载列出的关系。
/**
* 获取在执行索引查询时应预加载的关系。
*
* @return array
*/
public function with(): array
{
return ['user'];
}
分页
要定义每页应显示多少结果,请设置 perPage
方法:
/**
* 获取每页返回的模型数量
*
* @return int
*/
public static function perPage(): int
{
return 30;
}
资源事件
每个资源都有两个处理方法,onSave
和 onDelete
。每当事件执行时,您可以更改或补充逻辑:
use Orchid\Crud\ResourceRequest;
use Illuminate\Database\Eloquent\Model;
/**
* 创建和更新模型的操作
*
* @param ResourceRequest $request
* @param Model $model
*/
public function onSave(ResourceRequest $request, Model $model)
{
$model->forceFill($request->all())->save();
}
/**
* 删除模型的操作
*
* @param Model $model
*
* @throws Exception
*/
public function onDelete(Model $model)
{
$model->delete();
}
权限资源
每个资源都包含一个 permission
方法,该方法应返回用户访问此资源所需的字符串键。默认情况下,所有资源对每个用户都是可用的。
/**
* 获取资源的权限键。
*
* @return string|null
*/
public static function permission(): ?string
{
return null;
}
对于每个注册的资源,如果方法返回非空值,则会创建一个新权限。
/**
* 获取资源的权限键。
*
* @return string|null
*/
public static function permission(): ?string
{
return 'private-post-resource';
}
有必要赋予用户管理它的权限。点击左侧栏中的个人资料,进入系统页面,然后进入用户页面,您可以为他们颁发授权或分配角色。之后,它们将显示在左侧菜单中。
操作
可以使用 orchid:action
Artisan 命令生成操作:
php artisan orchid:action CustomAction
默认情况下,所有操作都放置在 app/Orchid/Actions
目录中。操作必须由两个方法组成。button
方法定义名称、图标、对话框等。而 handler
方法直接处理模型的操作。
namespace App\Orchid\Actions;
use Illuminate\Support\Collection;
use Orchid\Crud\Action;
use Orchid\Screen\Actions\Button;
use Orchid\Support\Facades\Toast;
class CustomAction extends Action
{
/**
* 操作的按钮。
*
* @return Button
*/
public function button(): Button
{
return Button::make('Run Custom Action')->icon('bs.fire');
}
/**
* 对给定模型执行操作。
*
* @param \Illuminate\Support\Collection $models
*/
public function handle(Collection $models)
{
$models->each(function () {
// action
});
Toast::message('It worked!');
}
}
在 handle
方法中,您可以执行完成操作所需的任何任务。
handle 方法始终接收一个模型的
Collection
,即使操作仅针对单个模型执行。
一旦定义了操作,您就可以将其附加到资源中。每个资源都包含一个 actions 方法。要将操作附加到资源,您应将其添加到该方法返回的操作数组中:
/**
* 获取资源可用的操作。
*
* @return array
*/
public function actions(): array
{
return [
CustomAction::class,
];
}
策略
要限制哪些用户可以查看、创建、更新或删除资源,可以利用 Laravel 的授权策略。策略是简单的 PHP 类,用于组织特定模型或资源的授权逻辑。例如,如果您的应用程序是一个博客,您可能有一个 Post
模型和一个对应的 PostPolicy
。
通常,这些策略将在应用程序的 AuthServiceProvider
中注册。如果 CRUD 检测到为模型注册了策略,它将自动在执行各自的操作之前检查该策略的相关授权方法,例如:
- viewAny
- view
- create
- update
- delete
- restore
- forceDelete
无需额外配置!因此,例如,要确定哪些用户可以更新 Post
模型,您需要在模型对应的策略类中定义一个 update
方法:
namespace App\Policies;
use App\Models\User;
use App\Models\Post;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
/**
* 确定用户是否可以更新帖子。
*
* @param User $user
* @param Post $post
* @return mixed
*/
public function update(User $user, Post $post)
{
return true;
}
}
如果策略存在但缺少特定的操作方法,则用户将不被允许执行该操作。因此,如果您定义了策略,请不要忘记定义所有相关的授权方法。
如果您不希望策略影响 CRUD 生成用户,您可能希望在给定策略中授权所有操作。为此,请在策略上定义一个 before
方法。在任何其他策略方法之前,before 方法将被执行,允许您在实际调用预期的策略方法之前授权操作。
namespace App\Policies;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
/**
* 执行预授权检查。
*
* @param User $user
* @param string $ability
* @return void|bool
*/
public function before(User $user, $ability)
{
if ($user->hasAccess('private-post-resource')) {
return true;
}
}
}
防止冲突(流量警察)
如果此选项处于活动状态,将检查模型的最后更改时间,如果在编辑表单打开后进行了更新,将抛出验证错误。默认情况下,流量警察功能是禁用的。
/**
* 指示是否应检查在查看和更新资源之间的修改。
*
* @return bool
*/
public static function trafficCop(): bool
{
return false;
}
描述
要在资源的每个页面上显示额外的描述,请使用 description
:
/**
* 获取屏幕的描述。
*
* @return null|string
*/
public static function description(): ?string
{
return null;
}
面包屑
在资源的每个页面上都有面包屑。您可以使用以下方法监控消息:
/**
* 获取列表面包屑的文本。
*
* @return string
*/
public static function listBreadcrumbsMessage(): string
{
return static::label();
}
/**
* 获取创建面包屑的文本。
*
* @return string
*/
public static function createBreadcrumbsMessage(): string
{
return __('New :resource', ['resource' => static::singularLabel()]);
}
/**
* 获取编辑面包屑的文本。
*
* @return string
*/
public static function editBreadcrumbsMessage(): string
{
return __('Edit :resource', ['resource' => static::singularLabel()]);
}
本地化
可以通过重写资源类上的 label
和 singularLabel
方法来本地化资源名称:
/**
* 获取资源的可显示标签。
*
* @return string
*/
public static function label()
{
return __('Posts');
}
/**
* 获取资源的可显示单数标签。
*
* @return string
*/
public static function singularLabel()
{
return __('Post');
}
操作按钮和通知也可以翻译,例如:
/**
* 获取创建资源按钮的文本。
*
* @return string|null
*/
public static function createButtonLabel(): string
{
return __('Create :resource', [
'resource' => static::singularLabel()
]);
}
/**
* 获取创建资源通知的文本。
*
* @return string
*/
public static function createToastMessage(): string
{
return __('The :resource was created!', [
'resource' => static::singularLabel()
]);
}
您可以在 Laravel 本地化页面上了解更多信息。