oza75 / laravel-hubble
立即创建一个漂亮的laravel仪表盘
Requires
- php: ^7.1|^8.0
- ext-json: *
- maatwebsite/excel: ^3.1
Requires (Dev)
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.0
- victorjonsson/markdowndocs: ^1.3
This package is auto-updated.
Last update: 2024-09-26 02:05:58 UTC
README
立即使用laravel构建一个漂亮的仪表盘。
要求
- php : ^7.1
- Laravel : ^6.0
安装
您可以通过composer安装此包
composer require oza75/laravel-hubble
然后安装laravel-hubble
php artisan hubble:install
# Now Add App\Providers\HubbleServiceProvider into providers array in your config/app.php
现在转到: http://yourapp.tld/hubble (如果您使用 artisan serve
,则为 https://:8000/hubble)
身份验证
Hubble 使用默认的 Laravel 授权网关来检查用户是否有权访问仪表盘。默认情况下,所有人都可以访问 Hubble 仪表盘。您可以使用 App\Providers\HubbleServiceProvider
中的 authorizesAccess
方法来限制访问。
// file: app/Providers/HubbleServiceProvider.php /** * Determines if a given user can access to hubble dashboard. * By default every user can access to hubble * * @param User $user * @return bool */ public function authorizesAccess(User $user): bool { return $user->isAdmin(); }
使用方法
资源
Hubble 资源是一个简单的 PHP 类,旨在表示您想要添加的资源,即它具有的不同字段、操作、过滤器等。
创建资源
您可以通过运行 hubble:resource
命令来创建一个新的资源
php artisan hubble:resource UserResource
这将在 app/Hubble
文件夹下自动创建一个新的资源
<?php namespace App\Hubble; use Illuminate\Database\Eloquent\Builder; use Oza75\LaravelHubble\Action; use Oza75\LaravelHubble\Field; use Oza75\LaravelHubble\Filter; use Oza75\LaravelHubble\Actions\DeleteAction; use App\Hubble\Resource; class UserResource extends Resource { /** * @var string The title will be used as your resource name in the ui */ protected $title = "Users"; /** * @var string[] */ protected $searchColumns = ['id']; /** * @var string used to show resource value in relationship */ protected $displayColumn = 'id'; /** * Get the fields displayed that the user resource * * @return Field[] array of fields */ public function fields() { return [ Field::make('id', 'ID'), Field::make('name', 'Name') ]; } /** * Register all actions that the user resource have * * @return Action[] array of actions */ public function actions() { return [ DeleteAction::make(), ]; } /** * Register all filters that the user resource have * * @return Filter[] array of filters */ public function filters() { return []; } /** * @return Builder */ public function baseQuery(): Builder { return \App\User::query(); } /** * Return this resource icon * * @return string|null */ public function icon() { return null; } }
在您的资源生成后,您需要设置 Hubble 应该使用的 eloquent builder
来获取您的数据。在生成此资源时,我们将尝试根据通过 php artisan hubble:resource
命令传入的资源名称获取 eloquent builder。您可以修改此查询构建器以添加一些计算字段。
/** * @return Builder */ public function baseQuery(): Builder { return \App\User::query()->select('*')->selectRaw('age > 18 as is_adult'); }
fields
方法用于返回您想要显示的所有字段。默认情况下,Hubble 带有一些字段,如 TextField
、TextareaField
、ImageField
等。但您也可以创建自己的自定义字段。
/** * Get the fields displayed that the user resource * * @return Field[] array of fields */ public function fields() { return [ Field::make('id', 'ID'), TextField::make('name', 'Name')->sortable(), TextareaField::make('bio', 'Bio')->onlyOnDetails(), TextField::make('email', 'Email')->displayOnIndexUsing(function ($value) { return "<a href='mailto:$value'>$value</a>"; })->type('email')->sortable(), ]; }
配置您的资源
您可以通过在您的资源类上设置一些属性来配置您的资源。
/** * @var string The title will be used as your resource name in the ui */ protected $title = "Users"; /** * @var string[] */ protected $searchColumns = ['id', 'name']; /** * @var string used to show resource value in relationship */ protected $displayColumn = 'name'; /** @var int Number of records per page */ protected $perPage = 38; /** @var bool Determines if a resource should be shown in sidebar */ protected $displayInSidebar = true; /** * @var bool Determines if a resource can be exported in excel format. */ protected $exportable = true;
如果您想自定义每个不同屏幕(索引页面、编辑页面、详情页面等)应显示的标题,您可以在您的资源中定义 configure
方法。例如
// use Oza75\LaravelHubble\Configuration\Configuration; // use Oza75\LaravelHubble\Configuration\ScreenConfiguration; public function configure(Configuration $configuration) { $configuration->details(function (ScreenConfiguration $configuration, User $user) { $configuration->setTitle("User #". $user->id); }); }
注册您的资源
默认情况下,Hubble 将自动注册您在 app/Hubble
文件夹下的所有资源。
只需转到 http://yourapp.tld/hubble
,您将看到我们添加的新用户资源。
您可以在配置文件中自定义 Hubble 必须在哪个文件夹中查找您的资源。自动注册在开发仪表板时非常有用,但在生产中您可能禁用它以提高性能。
在您的 app/Providers/HubbleServiceProvider.php
<?php namespace App\Providers; use Illuminate\Foundation\Auth\User; use Oza75\LaravelHubble\HubbleServiceProvider as BaseProvider; class HubbleServiceProvider extends BaseProvider { /** * Determines if hubble should detects automatically * resources under Hubble resource folder. This is useful when you are * developing but should be disable in production * * @var bool */ protected $autoRegistration = false; // set to false to disable auto registration /** * List of resource Hubble should register. Should be used * when you set autoRegistration = false. Optionally you can * define a resource method in this class to bypass this property. * * @var array */ protected $resources = [ // add your resources manually here UserResource::class, ]; /** * Determines if a given user can access to hubble dashboard. * By default every user can access to hubble * * @param User $user * @return bool */ public function authorizesAccess(User $user): bool { return parent::authorizesAccess($user); } }
操作
操作用于对一个或多个 Eloquent 模型执行自定义任务。您可以使用以下命令生成操作:
php artisan hubble:action ActiveUsers
此命令将在 app/Hubble/Actions
下生成一个新的 ActiveUsers
类
<?php namespace App\Hubble\Actions; use App\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\LazyCollection; use Oza75\LaravelHubble\Action; class ActiveUsers extends Action { /** * @var string the title of this action */ protected $title = 'ActiveUsers'; /** * @var string the confirmation message to warn user before running this action. Set to null to disable it */ protected $confirmationMessage = 'Do you really want to perform this action ?'; /** * Handle your action * * @param LazyCollection $collection * @param Builder $query * @return string */ public function handle(LazyCollection $collection, Builder $query) { $query = $query->newQuery(); $collection->each(function (User $user) use ($query) { $query->orWhere('id', $user->id); }); $query->update(['is_active' => true]); return "Utilisateurs activé avec succès !"; } /** * @param \Illuminate\Foundation\Auth\User $user * @param Model|null $model * @return bool */ public function can(\Illuminate\Foundation\Auth\User $user, ?Model $model = null): bool { return true; } protected function icon() { return asset('images/lock.svg'); } }
title
属性包含将在用户界面中显示的操作名称
在 handle
方法中,您可以执行您的操作。在我们的例子中,假设我们的用户表有一个 active 列,它确定用户是否活跃。
/** * Handle your action * * @param $ids * @return void */ public function handle($ids) { User::query()->whereIn('id', $ids)->update(['active' => true]); }
当您创建操作时,您可以在资源中添加它。
/** * Register all actions that the user resource have * * @return Action[] array of actions */ public function actions() { return [ DeleteAction::make(), new ActiveUsers(), ]; }
过滤器
如名称所示,过滤器用于过滤您的数据,并仅显示满足某些条件的数据。向资源中添加过滤器的有许多方法
- 第一种方式(最简单的方式)
/** * Register all filters that the user resource have * * @return Filter[] array of filters */ public function filters() { return [ Filter::make('is_active', 'Only Active Users', ['Yes' => 1, 'No' => 0]), ]; }
Filter::make
的第一个参数是数据库中的列。第二个参数是标题,然后是第三个选项数组。
选项参数是一个关联数组,键是标签,值是选项的值。您还可以传递一个URL,其中应该获取选项,或一个自定义数组。在这些情况下,您可以使用setValueKey(string $key)
和setTextKey(string $key)
来设置valueKey和textKey。
例如
/** * Register all filters that the user resource have * * @return Filter[] array of filters */ public function filters() { return [ Filter::make('is_active', 'Users Status', [ ['name' => 'All', 'value' => null], ['name' => 'Active', 'value' => 1], ['name' => 'Non active', 'value' => 0] ])->setValueKey('value')->setTextKey('name'), ]; }
另一个示例
/** * Register all filters that the user resource have * * @return Filter[] array of filters */ public function filters() { return [ Filter::make('state', 'Users State', "https://restcountries.eu/rest/v2/all") ->setValueKey('alpha3Code') ->setTextKey('name') ->searchable('Start typing a state...'), ]; }
- 定义过滤器(更强大)的另一种方式
/** * Register all filters that the user resource have * * @return Filter[] array of filters */ public function filters() { return [ Filter::make('state', 'Users State', "https://restcountries.eu/rest/v2/all") ->setValueKey('alpha3Code') ->setTextKey('name') ->setHandler(function (Builder $builder, $value) { $builder->whereHas('state', function ($query) use ($value) { $query->where('code', $value); }); }), ]; }
使用这种方法,您可以使用setHandler
方法传递一个可调用的函数,该函数将查询构建器
作为第一个参数,并将过滤器值作为参数,您可以添加任何想要的where子句
。
- 最后一种方式是生成一个新的过滤器类。
php artisan hubble:filter MyCustomFilter
此命令将在app/Hubble/Filters
下生成一个新的过滤器类。
<?php namespace App\Hubble\Filters; use Illuminate\Database\Eloquent\Builder; use Oza75\LaravelHubble\Filter; class MyCustomFilter extends Filter { /** * @var string the title of your filter that will be shown on the ui. */ protected $title = 'My custom filter'; /** * @var string the VueJs component that will be used to display this filter */ protected $component = 'hubble-checkbox-filter'; /** * Apply your filter * * @param Builder $query * @param $value * @return void */ public function handle(Builder $query, $value) { // apply your filter here. return null; } /** * Return all options for this filter * * @return array */ public function options() { // first way return ['Option 1' => 1, 'Option 2' => 2]; // the key is the label and the value is the option value // second way return [ ['name' => 'Option 1', 'value' => 1], ['name' => 'Option 2', 'value' => 2], ]; // third way return "https://restcountries.eu/rest/v2/all"; // do not forget to use `setValueKey(string $key)` and `setTextKey(string $key)` in the constructor of this class // or when instantiating this class to set the value key and the text key } }
您还可以使用自定义VueJs
组件生成过滤器。
php artisan hubble:filter MyCustomFilter --custom
这将在resources/hubble/components/filters/my-custom-filter.vue
下生成一个VueJs
组件。
字段
字段用于显示您的数据。基本Field
类可以用于创建字段。任何类型的字段都扩展了这个类。
\Oza75\LaravelHubble\Field::make('column', 'title');
- 可排序
\Oza75\LaravelHubble\Field::make('column', 'title')->sortable(); // now this field can be used to sort your data
您还可以告诉Hubble
默认情况下使用某个字段来对数据进行排序。
\Oza75\LaravelHubble\Field::make('column', 'title')->sortable(true, 'desc');
自定义显示
有一些方法可以用来自定义您想要在仪表板的不同部分中显示的字段值。
- displayUsing
- displayOnIndexUsing
- displayOnDetailsUsing
- displayOnFormsUsing
- displayWhenEditingUsing
- displayWhenCreatingUsing
displayUsing
方法自定义了仪表板所有部分的显示。
所有这些方法都有相同的签名。
\Oza75\LaravelHubble\Field::make('fullname', 'Full Name')->displayUsing(function ($value, $resource) { return $resource->first_name . ' '. $resource->last_name; // in this case resource is a User model }); \Oza75\LaravelHubble\Field::make('email', 'Email')->displayOnIndexUsing(function ($value) { return "<a href='mailto:$value'>$value</a>"; });
可见性
Field
提供了一些方法,您可以使用它们来指定何时显示
- hide : 将在所有屏幕上隐藏字段
- hideOnIndex
- hideOnForms
- hideOnDetails
- hideWhenCreating
- hideWhenEditing
- hideOnExport
- showOnIndex
- showOnDetails
- showOnForm
- showWhenCreating
- showWhenEditing
- showOnExport
- onlyOnIndex
- onlyOnDetails
- onlyOnForms
- onlyOnCreating
- onlyOnEditing
- onlyOnExport
\Oza75\LaravelHubble\TextField::make('email', 'Email')->hideOnIndex();
所有这些方法都可以传递一个闭包,该闭包将被用来在特定屏幕上隐藏或显示字段。
\Oza75\LaravelHubble\PasswordField::make('password', 'Change the password')->onlyOnForms(function (User $user, ?\Illuminate\Database\Eloquent\Model $model = null) { return $user->isAdmin() || ($model && $model->id === $user->id); });
Hubble
提供了许多类型的字段,但您也可以创建自己的。
- TextField
- BooleanField
- NumberField
- TextareaField
- DateTimeField
- SelectField
- ColorField
- FileField
- ImageField
- BelongsToField (关系字段)
- HasManyField (关系字段)
TextField
用于显示文本字段。
\Oza75\LaravelHubble\Fields\TextField::make('email', 'Email');
- text类型
\Oza75\LaravelHubble\Fields\TextField::make('email', 'Email')->type('email');
此类型将用于在表单中显示正确的输入类型。
- limit
\Oza75\LaravelHubble\Fields\TextField::make('bio', 'Bio')->limit(100);
限制表格中应显示的字符数。
BooleanField
\Oza75\LaravelHubble\Fields\BooleanField::make('active', 'Active ?')->text('Yes', 'No');
当此字段具有true
或false
值时,text
方法将设置要显示的文本。
NumberField
用于显示数字值
\Oza75\LaravelHubble\Fields\NumberField::make('articles_count', 'Articles');
TextareaField
用于显示长文本值
\Oza75\LaravelHubble\Fields\TextareaField::make('bio', 'Bio');
DateTimeField
用于显示日期值
\Oza75\LaravelHubble\Fields\DateTimeField::make('created_at', 'Created at');
- 日期格式
\Oza75\LaravelHubble\Fields\DateTimeField::make('created_at', 'Created at')->format('Y-m-d at h:i');
- 日期区域
\Oza75\LaravelHubble\Fields\DateTimeField::make('created_at', 'Created at')->setLocale('fr')->format('Y-m-d at h:i');
SelectField
\Oza75\LaravelHubble\Fields\SelectField::make('user_type', 'Type')->options(['Pro' => 'pro', 'Normal' => 'normal']);
- 使用标签显示
\Oza75\LaravelHubble\Fields\SelectField::make('user_type', 'Type') ->options(['Pro' => 'pro', 'Normal' => 'normal']) ->displayUsingLabel();
ColorField
用于显示颜色
\Oza75\LaravelHubble\Fields\ColorField::make('primary_color', 'Color');
- 使用十六进制值显示
\Oza75\LaravelHubble\Fields\ColorField::make('primary_color', 'Color')->displayUsingHex();
FileField
用于显示和上传文件
\Oza75\LaravelHubble\Fields\FileField::make('avatar', 'Avatar'),
- multiple
\Oza75\LaravelHubble\Fields\FileField::make('avatar', 'Avatar')->multiple(),
- max
限制文件数量
\Oza75\LaravelHubble\Fields\FileField::make('avatar', 'Avatar')->multiple()->max(5),
ImageField
用于显示图像和上传图像。
ImageField
扩展自FileField
,因此它具有FileField
的所有方法,例如multiple
或max
。
\Oza75\LaravelHubble\Fields\ImageField::make('avatar', 'Avatar'),
或
\Oza75\LaravelHubble\Fields\ImageField::make('avatar', 'Avatar')->multiple()->max(5),
BelongsToField
用于显示相关资源
- 签名
\Oza75\LaravelHubble\Fields\BelongsToField::make('method_name', 'related_class', 'Title');
第一个参数是名称关系方法。假设在我们的 User
模型中有一个指向 City
模型的 belongsTo
方法。
/** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function city() { return $this->belongsTo(City::class); }
然后在我们的资源中添加这个关系
\Oza75\LaravelHubble\Fields\BelongsToField::make('city', CityResource::class);
HasManyField
用于显示相关资源
- 签名
\Oza75\LaravelHubble\Fields\BelongsToField::make('method_name', 'related_class', 'Title');
与 BelongsToField
类似,HasManyField
将关系方法名称作为其第一个参数。
\Oza75\LaravelHubble\Fields\HasManyField::make('roles', RoleResource::class, 'User Roles');
创建自定义字段
您可以通过此命令创建自定义字段
php artisan hubble:field ColorField
您也可以使用此命令生成具有自定义组件的新字段
php artisan hubble:field ColorField --custom
这将在 resources/hubble/components/fields/color
下为您的字段创建新的 VueJs
组件
使用此命令构建新组件
npm run hubble:watch
或
npm run hubble:prod
php artisan hubble:field
将在 app/Hubble/Fields
下生成新的字段类
<?php namespace App\Hubble\Fields; use Oza75\LaravelHubble\Field; use Oza75\LaravelHubble\HubbleResource; class ColorField extends Field { /** * Register your vuejs components */ protected function registerComponents() { parent::registerComponents(); $this->components = [ 'index' => 'index-text-field', 'editing' => 'edit-text-field', 'creating' => 'edit-text-field', 'details' => 'show-text-field' ]; } /** * This hook is called when the field is ready to work. * Basically it will just set the resource within your field is added. * So if you have some attributes to add or actions that depends on the resource * this is where you should do it. * * @param HubbleResource $resource */ public function prepare(HubbleResource $resource) { parent::boot($resource); // do action that depends on the resource within this field is added } }
规则
您可以通过在每个字段上设置规则来自动验证表单数据。
\Oza75\LaravelHubble\Fields\TextField::make('email', 'Email')->rules('required|email|max:255');
还有每个 creation
和 editing
屏幕的 rules
方法
rulesWhenUpdating
将仅定义更新时的规则rulesWhenCreating
将仅定义创建时的规则
警告:规则方法还不能接受验证对象(如规则类)或闭包,但任何
Pull Request
都是受欢迎的。
对于前端交互,您可以在 resources/hubble/rules.js
中设置一个处理程序,以自动验证字段值。如果没有,当用户填写表单时,将发送一个 ajax
请求到后端以检查值是否有效。
// this method must return a boolean, a string or a promise (for validations that need to make ajax requests) export const string = function (value, fieldName) { if (typeof value !== "string") { // For localization purposes your laravel validation language file is injected into the javascript window, // then you can use the `window.trans` method to return a translated string return window.trans('validation.string', {attribute: fieldName}) } return true; }
授权
授权用于限制对仪表板某些屏幕的访问。内部,它主要使用 Laravel Authorization Gate
。
您只需要为您的资源创建一个 Laravel Policy,这将控制哪个用户可以访问或无法访问特定屏幕。
例如,假设我有一个 Post
模型
php artisan make:policy PostPolicy --model=Post
这将在 app/Policies
下生成一个新的 Laravel Policy
<?php namespace App\Policies; use App\Post; use Illuminate\Auth\Access\HandlesAuthorization; class PostPolicy { use HandlesAuthorization; public function before(User $user) { // bypass all authorization check when user is admin if ($user->isAdmin()) { return true; } } /** * Determine whether the user can view any models. * * @param \App\User $user * @return mixed */ public function viewAny(User $user) { return true; // Anyone can see `the index table`. You can also return false to remove the hubble' PostResource in sidebar. } /** * Determine whether the user can view the model. * * @param \App\User $user * @param \App\Post $model * @return mixed */ public function view(User $user, Post $model) { return true; // anyone can see the details screen. } /** * Determine whether the user can create models. * * @param \App\User $user * @return mixed */ public function create(User $user) { return true; // anyone can create a new user } /** * Determine whether the user can update the model. * * @param \App\User $user * @param \App\Post $model * @return mixed */ public function update(User $user, Post $model) { return $user->id === $model->user_id; // only the owner of the post can edit this post } /** * Determine whether the user can delete the model. * * @param \App\User $user * @param \App\Post $model * @return mixed */ public function delete(User $user, Post $model) { return $user->id === $model->user_id; // only the owner of the post can delete this post } /** * Determine whether the user can restore the model. * * @param \App\User $user * @param \App\User $model * @return mixed */ public function restore(User $user, User $model) { return false; } /** * Determine whether the user can permanently delete the model. * * @param \App\User $user * @param \App\User $model * @return mixed */ public function forceDelete(User $user, User $model) { return false; } /** * Determines if the current user can attach users to post * when using a HasManyField */ public function attachUser(User $user) { return false; } /** * Determines if the current user can detach users to post * when using a HasManyField */ public function detachUser(User $user, Post $model) { return false; } }
测试
composer test
变更日志
有关最近更改的更多信息,请参阅 CHANGELOG
贡献
有关详细信息,请参阅 CONTRIBUTING
安全
如果您发现任何安全相关的问题,请通过电子邮件 abouba181@gmail.com 而不是使用问题跟踪器。
鸣谢
许可
MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件
Laravel 包模板
此包是使用 Laravel 包模板 生成的。