Skip to main content

如何表格操作触发后刷新插件

· 5 min read
Martin
Full Stack Developer

本文将介绍如何使用 Filament 插件(Widget)创建统计卡片,用来展示用户统计信息。我们将展示如何使用 Livewire 生命周期 hook 和事件,在用户表修改时刷新插件。

安装

首先,安装一个名为 filament-widget-examples 的 Laravel 应用:

laravel new filament-widget-examples

然后使用命令安装 Filament:

cd filament-widget-examples
composer require filament/filament

Filament 推荐添加以下内容到 composer.jsonpost-update-cmd:

"post-update-cmd": [
// ...
"@php artisan filament:upgrade"
]

编辑用户 Migration 文件:

Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->boolean('is_admin');
$table->boolean('is_active');
$table->rememberToken();
$table->timestamps();
});

编辑用户工厂 definition 方法:

//database\factories\UserFactory.php
public function definition()
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'is_admin' => fake()->boolean(),
'is_active' => fake()->boolean(),
];
}

编辑 DatabaseSeederrun 方法:

//database\seeders\DatabaseSeeder.php
public function run()
{
\App\Models\User::factory(100)->create();
}

编辑用户模型:

//app/Models/User.php
protected $fillable = [
'name',
'email',
'password',
'is_active',
'is_admin'
];

运行 migrate 命令:

php artisan migrate --seed

用户资源 User Resource

添加 User Resource 和插件 Widget:

php artisan make:filament-resource User --simple
php artisan make:filament-widget UserOverview --resource=UserResource --stats-overview

编辑用户资源文件:

表单:

//app/Filament/Resources/UserResource.php
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->required()
->maxLength(255),
Forms\Components\TextInput::make('email')
->email()
->required()
->maxLength(255),
Forms\Components\Toggle::make('is_admin'),
Forms\Components\Toggle::make('is_active'),
]);
}

表格:

//app/Filament/Resources/UserResource.php
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('email'),
Tables\Columns\IconColumn::make('is_admin')
->boolean(),
Tables\Columns\IconColumn::make('is_active')
->boolean(),
Tables\Columns\TextColumn::make('created_at')
->date(),
Tables\Columns\TextColumn::make('updated_at')
->date(),
])
->filters([
Tables\Filters\TernaryFilter::make('is_admin'),
Tables\Filters\TernaryFilter::make('is_active'),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}

引入插件

添加 getWidgets 方法:

//app/Filament/Resources/UserResource.php
use App\Filament\Resources\UserResource\Widgets\UserOverview;
public static function getWidgets(): array
{
return [
UserOverview::class,
];
}

添加 getHeaderWidgets 方法:

//app/Filament/Resources/UserResource/Pages/ManageUsers.php
protected function getHeaderWidgets(): array
{
return [
UserOverview::class,
];
}

插件卡片

你可以使用插件卡,在一个插件内展示许多许多不同的统计。编辑用户概览插件:

//app/Filament/Resources/UserResource/Widgets/UserOverview.php
class UserOverview extends BaseWidget
{
protected static ?string $pollingInterval = null;

protected function getCards(): array
{
$usersCount = User::selectRaw('
COUNT(*) as total,
SUM(CASE WHEN is_admin THEN 1 ELSE 0 END) AS admin,
SUM(CASE WHEN is_active THEN 1 ELSE 0 END) AS active
')->first();

return [
Card::make('Total', $usersCount->total)
->color('primary')
->description('Total users'),

Card::make('Admin', $usersCount->admin)
->color('danger')
->description('Admin users'),

Card::make('Active', $usersCount->active)
->color('success')
->description('Active users'),
];
}
}

到浏览器中查看用户资源。其中有三个头部插件:Total users, Admin users 及 Active users.

你可以在用户表中删除用户,表格里的数据更新了,但是这些插件里的信息不会更新。你需要手动刷新才能更新插件。

自动刷新插件

Livewire 生命周期

每个 Livewire 组件都有生命周期。生命周期狗子让你可以在组件生命周期的任意一个地方运行代码。我们可以使用 Updated 钩子,在 Livewire 组件更新后运行。

Livewire 事件监听器

监听器是 key->value 键值对,key 是为监听的事件,值是组件上调用的方法。

我们可以使用 $refresh 魔术操作重新渲染组件。

UserOverviewWidget 文件中添加一个监听器:

//app/Filament/Resources/UserResource/Widgets/UserOverview.php
protected $listeners = ['updateUserOverview' => '$refresh'];

updated 钩子方法提供了两个属性:

  • $name: 触发的操作的名称。
  • $value: 触发的操作的值。

我们将使用 $name 属性监听两个表格事件:

  • mountedTableAction: 单个删除操作点击后执行。
  • mountedTableBulkAction: 批量删除操作点击后执行。

然后,我们可以在 updated 方法使用这些名字以及触发 updateUserOverview 事件:

//app/Filament/Resources/UserResource/Pages/ManageUsers.php
public function updated($name)
{
if (Str::of($name)->contains(['mountedTableAction', 'mountedTableBulkAction'])) {
$this->emit('updateUserOverview');
}
}

现在,每次删除操作点击后都会更新插件。

你可以检查表格事件,比如:

//text input in the top right of the table
if (Str::of($name)->contains('tableSearchQuery')) {
...
}

//the table filter form
if (Str::of($name)->contains('tableFilters')) {
...
}

使用 Laravel Filament 极速搭建美观大方的后台面板

· 4 min read

Filament 后台面板是快速创建精美的TALL技术栈的工具箱。可以创建页面、控制面板、模块、图表、插件等。

在这个教程中,我们将使用 Filament 一起搭建一个 CRUD 后台面板。

注意:本文将假定你已经创建了一个新的 Laravel 项目,并且已经配置好了数据库

  1. 安装要求
  • Laravel v8.0+
  • Livewire v2.0+
  • PHP v8.0+
  1. 安装和登录

在命令行输入:

composer require filament/filament

如果你想访问项目的登录页面,使用以下网址:

https://your-url/admin

http://your-url/admin

如果你还没创建用户,可以在命令行中使用如下命令创建:

php artisan make:filament-user

然后,你就可以在如下终端输入相关用户信息:

Name:
> admin
Email address:
> admin@laravel-filament.cn
Password:
>
Successful! admin@laravel-filament.cn may now log in at http://laravel-filament.cn/admin/login.

之后,我们就可以用这个用户名密码登录。

  1. 模型

接下来,我们将使用如下命令创建新模型及对应的迁移文件:

php artisan make:model Project -m

打开 database/migration 中的迁移文件,添加如下字段:

public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->date('start_date');
$table->date('deadline');
$table->foreignId('user_id');
$table->timestamps();
});
}

执行迁移:

php artisan migrate

下一步便是打开 App\Models\Project.php 并添加 fillable 字段和关联:

protected $fillable = [
'name',
'description',
'start_date',
'deadline',
'user_id'
];

public function user()
{
return $this->belongsTo(User::class);
}
  1. 项目资源 Filament 中的资源(Resource) 用于管理表格、表单、视图等。它就像是某种控制器,配置了我们所需要的,用于模型和CRUD的资源。使用以下命令创建资源:
php artisan make:filament-resource Project

这个命令会生成这么一些文件:

+-- ProjectResource.php
+-- ProjectResource
| +-- Pages
| | +-- CreateProject.php
| | +-- EditProject.php
| | +-- ListProjects.php

此时的后台面板中,你就能看到对应的菜单了。

  1. 定义表格

打开 app/Filament/Resources/ProjectResource.php 文件,你会看到有一个静态的 table() 方法,里面包含了 columns()filters()。紧接着我们就可以像这样定义表格(数据库字段):

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')->sortable()->searchable(),
Tables\Columns\TextColumn::make('description'),
Tables\Columns\TextColumn::make('start_date'),
Tables\Columns\TextColumn::make('deadline'),
Tables\Columns\TextColumn::make('user.name'),
])
->filters([]);
}

注意:只要使用像 user.name 这样的点语法就可以使用 belongsTo 关联。

  1. 创建项目表单 在 app/Filament/Resources/ProjectResource.php 文件里,我们可以在静态 form 方法中,以这样的方式创建表单控件:
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Textarea::make('description'),
DatePicker::make('start_date')->format('Y-m-d')->displayFormat('m/d/Y'),
DatePicker::make('deadline')->format('Y-m-d')->displayFormat('m/d/Y'),
BelongsToSelect::make('user_id')->relationship('user', 'name')
]);
}

别忘了引入 Textarea, DatePicker, BelongsToSelect

当使用日期时,format() 函数会将对应的格式化日期存入数据库中。

BelongsToSelect 中,我们需要在 make 中输入外键,关联接收两个参数:第一个是关联名称,第二个是你要显示的字段名。 完成后,你就可以打开 create 页面,查看表单。

接下来,你就可以使用该表单添加一些数据,然后去查看相应表格展示页。

就是这么简单!只需几分钟,我们就创建了一个后台面板,同时也完成了一个 CRUD 模块。如果你需要了解更多 Filament 的情况,可以查看 Filament 中文文档。

Welcome

· One min read
Martin
Full Stack Developer

Docusaurus blogging features are powered by the blog plugin.

Simply add Markdown files (or folders) to the blog directory.

Regular blog authors can be added to authors.yml.

The blog post date can be extracted from filenames, such as:

  • 2019-05-30-welcome.md
  • 2019-05-30-welcome/index.md

A blog post folder can be convenient to co-locate blog post images:

Docusaurus Plushie

The blog supports tags as well!

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.