Languages

Version

Theme

资源

单体资源

概述

资源并非在 Filament 面板中与 Eloquent 记录交互的唯一方式。尽管资源可以解决你的许多需求,但资源的 “index”页面包含一个表,其中包含该资源中的记录列表。

有时不需要一个表来列出资源中的记录。用户只与一条记录交互。如果用户访问页面时该记录尚不存在,则会在用户首次提交表单以保存该记录时创建该记录。如果该记录已存在,则会在页面首次加载时将其加载到表单中,并在提交表单时更新。

例如,CMS 可能有一个 Page Eloquent 模型和一个 PageResource,但您可能还希望在 PageResource 之外创建一个单独的页面来编辑网站的“主页”。这允许用户直接编辑主页,而无需导航到 PageResource并在表中查找主页记录。

其他示例包括“设置”页面或当前登录用户的“个人资料”页面。不过,对于这些用例,我们建议你使用 Filament 的 Spatie 设置插件个人资料 功能,他们需要的代码较少。

创建单体资源

虽然 Filament 中没有专门的“单体资源”功能,但它是一项用户呼声很高的功能,可以通过使用自定义页面和 、表单轻松实现。本指南将讲解如何操作。

首先,创建一个自定义页面

php artisan make:filament-page ManageHomepage

该命令将创建两个文件 - 一个资源目录的 /Filament/Pages 中的页面类,以及资源视图目录的 /filament/pages 目录中的 Blade 视图。

页面类应包含以下元素:

  • $data 属性,用于保存表单的当前状态。
  • mount() 方法,用于从数据库加载当前记录并用其数据填充表单。如果记录不存在,则 null 将被传递给表单的 fill() 方法,该方法将为表单字段分配默认值。
  • form() 方法,用于定义表单 Schema。表单包含 components() 方法中的字段。record() 方法用于指定表单应从哪个记录加载关联数据。statePath() 方法用于指定应存储表单状态的属性($data)的名称。
  • save() 方法,用于将表单数据保存到数据库。getState() 方法运行表单验证并返回有效的表单数据。此方法应检查记录是否已存在,如果不存在,则创建新记录。模型的 wasRecentlyCreated 属性可用于判断记录是否刚刚创建,如果是,则所有关联也应保存。系统会向用户发送通知,确认记录已保存。
  • getRecord() 方法虽然并非必需,但最好添加。此方法将返回表单正在编辑的 Eloquent 记录。它可以与其他方法一起使用,以避免代码重复。
namespace App\Filament\Pages;

use App\Models\WebsitePage;
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Schema;

/**
 * @property-read Schema $form
 */
class ManageHomepage extends Page
{
    /**
     * @var array<string, mixed> | null
     */
    public ?array $data = [];

    public function mount(): void
    {
        $this->form->fill($this->getRecord()?->attributesToArray());
    }

    public function form(Schema $schema): Schema
    {
        return $schema
            ->components([
                TextInput::make('title')
                    ->required()
                    ->maxLength(255),
                RichEditor::make('content'),
                // ...
            ])
            ->record($this->getRecord())
            ->statePath('data');
    }

    public function save(): void
    {
        $data = $this->form->getState();
        
        $record = $this->getRecord();
        
        if (! $record) {
            $record = new WebsitePage();
            $record->is_homepage = true;
        }
        
        $record->fill($data);
        $record->save();
        
        if ($record->wasRecentlyCreated) {
            $this->form->record($record)->saveRelationships();
        }

        Notification::make()
            ->success()
            ->title('Saved')
            ->send();
    }
    
    public function getRecord(): ?WebsitePage
    {
        return WebsitePage::query()
            ->where('is_homepage', true)
            ->first();
    }
}

其页面 Blade 视图应该渲染表单和保存按钮。wire:submit 指令用来在表单提交时调用 save() 命令:

<x-filament::page>
    <form wire:submit="save">
        {{ $this->form }}
    
        <div>
            <x-filament::button type="submit">
                Save
            </x-filament::button>
        </div>
    </form>
</x-filament::page>
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

Previous
嵌套资源