核心概念 - 插件
开发面板插件
前言
概述
此教程中,我们将开发一个简单的插件,添加一个可以在表单中使用的新表单字段。这也意味着它可以在面板中使用。
此插件的最终代码在 https://github.com/awcodes/clock-widget。
步骤 1:创建插件
首先,我们将使用开始向导中提到的步骤创建插件。
步骤 2:清理
接下来,我们将清理插件移除不需要的样板代码。这看起来很多,但由于这是一个简单的插件,我们可以删除很多样板代码。
删除下列目录和文件:
config
database
src/Commands
src/Facades
stubs
由于我们的插件没有任何设置或功能所需的其他方法,我们还可以删除 ClockWidgetPlugin.php
文件。
ClockWidgetPlugin.php
因为 Filament v3 推荐用户使用自定义的 Filament 主题来定义插件样式,我们将移除在插件中使用 CSS 所需的文件。这一操作是可选的,如果你想使用 CSS,依然可以使用,不过并不推荐。
resources/css
postcss.config.js
tailwind.config.js
然后清理 composer.json
文件移除不需要的选项。
"autoload": { "psr-4": { // We can remove the database factories "Awcodes\\ClockWidget\\Database\\Factories\\": "database/factories/" }},"extra": { "laravel": { // We can remove the facade "aliases": { "ClockWidget": "Awcodes\\ClockWidget\\Facades\\ClockWidget" } }},
最后一步是更新 package.json
文件,移除不需要的选项。使用如下内容替换 package.json
中的内容。
{ "private": true, "type": "module", "scripts": { "dev": "node bin/build.js --dev", "build": "node bin/build.js" }, "devDependencies": { "esbuild": "^0.17.19" }}
然后,我们需要安装依赖。
npm install
你可能也想删除测试目录及其文件,不过我们暂时先把它们留着,虽然我们在这个例子中我们不会使用测试,我还是强烈推荐为你的插件编写测试。
步骤 3:设置服务提供者
既然已经清理完了,我们可以开始添加代码了。src/ClockWidgetServiceProvider
文件中的样板代码中有很多内容,因此,我们删除所有内容,从头开始。
本例中,我们将注册异步 Alpine 组件。由于这些资源仅在请求时加载,因此我们可以在
packageBooted()
方法中注册它们。如果你注册的资源(比如 CSS 或 JS 文件)在每个页面上都加载,无论是否使用,我们建议在Plugin
配置对象的register()
方法中通过$panel->assets()
进行注册。否则,如果你在packageBooted()
方法中注册它们,它们将适用于每个面板,而不管插件是否已在该面板上注册。
我们需要在面板中注册 Widget 并且在使用 widget 时加载 Alpine 组件。为此,我们需要添加以下内容到服务提供者的 packageBooted
方法。这将会向 Livewire 注册 widget 组件并向 Filament 资源管理器注册 Alpine 组件。
use Filament\Support\Assets\AlpineComponent;use Filament\Support\Facades\FilamentAsset;use Livewire\Livewire;use Spatie\LaravelPackageTools\Package;use Spatie\LaravelPackageTools\PackageServiceProvider; class ClockWidgetServiceProvider extends PackageServiceProvider{ public static string $name = 'clock-widget'; public function configurePackage(Package $package): void { $package->name(static::$name) ->hasViews() ->hasTranslations(); } public function packageBooted(): void { Livewire::component('clock-widget', ClockWidget::class); // Asset Registration FilamentAsset::register( assets:[ AlpineComponent::make('clock-widget', __DIR__ . '/../resources/dist/clock-widget.js'), ], package: 'awcodes/clock-widget' ); }}
步骤 4:创建 Widget
现在我们可以创建我们的 Widget。我们需要先在 ClockWidget.php
文件中继承 Filament 的 Widget
类,并告知何处可以找到该 Widget 的视图。由于我们使用 PackageServiceProvider 去注册视图,我们可以使用 ::
语法告诉 Filament 哪里可以找到视图。
use Filament\Widgets\Widget; class ClockWidget extends Widget{ protected static string $view = 'clock-widget::widget';}
接下来,为这个 Widget 创建视图。 创建一个新文件 resources/views/widget.blade.php
并添加如下代码。我们使用 Filament 的 Blade 组件来节省编写 HTML 的时间。
我们使用异步 Alpine 来加载 Alpine 组件,因此我们需要将 x-ignore
属性添加到加载我们组件的 div。我们也需要将 ax-load
属性添加到该 div,用以告知 Alpine 加载我们的组件。你可以到本文档的核心概念章节中了解更多相关信息。
<x-filament-widgets::widget> <x-filament::card> <h2 class="font-bold text-xl mb-4 text-center"> {{ __('clock-widget::clock-widget.title') }} </h2> <div x-ignore ax-load ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('clock-widget', 'awcodes/clock-widget') }}" x-data="clockWidget()" class="text-center" > <p>{{ __('clock-widget::clock-widget.description') }}</p> <p class="text-xl" x-text="time"></p> </div> </x-filament::card></x-filament-widgets::widget>
接下来,我们需要在 src/js/index.js
中编写我们的 Alpine 组件。并使用 npm run build
编译我们的资源。
export default function clockWidget() { return { time: new Date().toLocaleTimeString(), init() { setInterval(() => { this.time = new Date().toLocaleTimeString(); }, 1000); } }}
我们也应该为插件中的文本添加翻译,这样用户翻译成他们自己的语言。我们将翻译添加到 resources/lang/en/widget.php
中。
return [ 'title' => 'Clock Widget', 'description' => 'Your current time is:',];
步骤 5:更新 README
你需要更新 README.md
文件,使之包含如何安装插件的说明以及其他你想分享给用户的信息,比如,如何在项目中使用该组件。示例:
//在 Panel 服务提供者中注册插件或 Widget: use Awcodes\ClockWidget\ClockWidgetWidget; public function panel(Panel $panel): Panel{ return $panel ->widgets([ ClockWidgetWidget::class, ]);}
就是这样,用户可以安装这个插件并在他们的项目中使用。
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion