#03 FilamentPHP基礎
フォームフィールドを使いこなす——入力UIの全体像
フォームフィールドの全体像
Filamentのフォームは Forms\Components 名前空間以下に多数のフィールドクラスが用意されています。すべてのフィールドは make('カラム名') で生成し、メソッドチェーンでオプションを追加していきます。
use Filament\Forms\Components\TextInput;
TextInput::make('email') // カラム名(必須)
->label('メールアドレス') // ラベル文字列
->required() // 必須バリデーション
->email(); // メール形式バリデーション
TextInput
最も基本的なフィールドです。多彩な入力タイプに対応しています。
use Filament\Forms\Components\TextInput;
// 基本的なテキスト入力
TextInput::make('name')
->label('名前')
->placeholder('山田 太郎')
->maxLength(100),
// メールアドレス
TextInput::make('email')
->label('メールアドレス')
->email() // type="email" に変更 + バリデーション
->unique(), // DBのuniqueバリデーション
// パスワード
TextInput::make('password')
->label('パスワード')
->password() // 入力を隠す
->revealable() // 表示/非表示の切り替えボタン
->minLength(8),
// 数値入力
TextInput::make('price')
->label('価格')
->numeric() // 数値のみ許可
->prefix('¥') // 先頭に単位表示
->minValue(0)
->maxValue(999999),
// 電話番号マスク
TextInput::make('phone')
->label('電話番号')
->tel()
->mask('999-9999-9999'), // 入力マスク
Select
選択肢から値を選ぶフィールドです。
use Filament\Forms\Components\Select;
// 固定の選択肢
Select::make('status')
->label('ステータス')
->options([
'draft' => '下書き',
'review' => 'レビュー中',
'published' => '公開',
'archived' => 'アーカイブ',
])
->default('draft')
->required(),
// 検索可能なセレクト
Select::make('category_id')
->label('カテゴリ')
->searchable() // 入力で絞り込み
->options(fn () => \App\Models\Category::pluck('name', 'id')->toArray()),
// リレーションから選択
Select::make('category_id')
->label('カテゴリ')
->relationship('category', 'name') // hasMany/belongsToリレーション
->searchable()
->preload(), // 初期ロード時に全件取得
// 複数選択
Select::make('tag_ids')
->label('タグ')
->multiple() // 複数選択を許可
->relationship('tags', 'name')
->searchable(),
DatePicker / DateTimePicker
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
// 日付のみ
DatePicker::make('birth_date')
->label('生年月日')
->maxDate(now()) // 今日以前のみ選択可能
->displayFormat('Y/m/d'), // 表示フォーマット
// 日時
DateTimePicker::make('published_at')
->label('公開日時')
->seconds(false) // 秒を非表示
->timezone('Asia/Tokyo')
->nullable(),
// 時刻のみ
TimePicker::make('open_time')
->label('営業開始時刻')
->seconds(false),
FileUpload
ファイルや画像のアップロードフィールドです。
use Filament\Forms\Components\FileUpload;
// 単一画像アップロード
FileUpload::make('thumbnail')
->label('サムネイル画像')
->image() // 画像のみ許可
->disk('public') // ストレージディスク
->directory('thumbnails') // 保存ディレクトリ
->visibility('public')
->imageEditor() // 画像トリミングUI
->maxSize(2048), // 最大2MB
// 複数ファイルアップロード
FileUpload::make('attachments')
->label('添付ファイル')
->multiple()
->disk('public')
->directory('attachments')
->acceptedFileTypes(['application/pdf', 'image/*'])
->maxFiles(5)
->maxSize(10240), // 最大10MB
config/filesystems.php の public ディスクを使う場合は、事前にシンボリックリンクを作成しておきます。
php artisan storage:link
RichEditor / MarkdownEditor
リッチテキストエディタです。
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Components\MarkdownEditor;
// リッチテキストエディタ(WYSIWYG)
RichEditor::make('content')
->label('本文')
->toolbarButtons([
'attachFiles',
'blockquote',
'bold',
'bulletList',
'codeBlock',
'h2',
'h3',
'italic',
'link',
'orderedList',
'redo',
'strike',
'underline',
'undo',
])
->columnSpanFull(),
// Markdownエディタ
MarkdownEditor::make('content')
->label('本文(Markdown)')
->toolbarButtons([
'attachFiles',
'blockquote',
'bold',
'bulletList',
'codeBlock',
'heading',
'italic',
'link',
'orderedList',
'redo',
'strike',
'table',
'undo',
])
->columnSpanFull(),
Repeater
同じフォームを繰り返し追加できるフィールドです。JSONカラムや別テーブルへのサブフォームとして使います。
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;
// 仕様リスト(JSONカラムに保存)
Repeater::make('specs')
->label('仕様')
->schema([
TextInput::make('key')
->label('項目名')
->required(),
TextInput::make('value')
->label('値')
->required(),
])
->columns(2) // 2カラムレイアウト
->addActionLabel('仕様を追加')
->defaultItems(1) // 初期表示の件数
->collapsible(), // アコーディオン化
// リレーション先のRepeater
Repeater::make('orderItems')
->relationship() // hasMany リレーションを使用
->schema([
Select::make('product_id')
->relationship('product', 'name')
->required(),
TextInput::make('quantity')
->numeric()
->minValue(1)
->default(1),
]),
バリデーション
Filamentのフォームフィールドには宣言的にバリデーションを追加できます。
基本のバリデーションメソッド
TextInput::make('title')
->required() // 必須
->minLength(3) // 最小3文字
->maxLength(255) // 最大255文字
->unique(table: 'posts', column: 'title'), // DB uniqueチェック
TextInput::make('price')
->numeric()
->minValue(0)
->maxValue(99999),
Select::make('status')
->options([...])
->in(['draft', 'published']), // 選択肢の値に限定
FileUpload::make('avatar')
->image()
->maxSize(1024), // 1MB以下
->rules() でLaravelルールを直接指定
TextInput::make('username')
->rules([
'required',
'alpha_num', // 英数字のみ
'min:3',
'max:20',
'unique:users,username',
]),
// クロージャでカスタムルール
TextInput::make('password_confirm')
->rules([
fn (Forms\Get $get): \Closure => function (string $attribute, $value, \Closure $fail) use ($get) {
if ($value !== $get('password')) {
$fail('パスワードが一致しません');
}
},
]),
->validationMessages() でエラーメッセージをカスタマイズ
TextInput::make('email')
->email()
->required()
->validationMessages([
'required' => 'メールアドレスは必須です',
'email' => '正しいメールアドレス形式で入力してください',
]),
フォームの完成例
実際のブログ投稿フォームの完成形です。
public static function form(Form $form): Form
{
return $form
->schema([
TextInput::make('title')
->label('タイトル')
->required()
->maxLength(255)
->columnSpanFull(),
Select::make('category_id')
->label('カテゴリ')
->relationship('category', 'name')
->searchable()
->preload()
->required(),
Select::make('tag_ids')
->label('タグ')
->multiple()
->relationship('tags', 'name')
->preload(),
FileUpload::make('thumbnail')
->label('サムネイル')
->image()
->disk('public')
->directory('posts/thumbnails')
->columnSpanFull(),
RichEditor::make('content')
->label('本文')
->required()
->columnSpanFull(),
Toggle::make('is_published')
->label('公開する'),
DateTimePicker::make('published_at')
->label('公開日時')
->seconds(false),
])
->columns(2); // デフォルトを2カラムに
}
まとめ
TextInputはemail/password/numeric/maskなど豊富なオプションを持つSelectはoptions配列・relationship・searchable・multipleに対応DatePicker/DateTimePickerでタイムゾーン対応の日時入力が可能FileUploadでdisk/directory/image/multipleを指定してアップロードRichEditor/MarkdownEditorでリッチテキスト入力Repeaterでサブフォームを繰り返し追加できる- バリデーションはメソッドチェーンまたは
->rules([])で追加
次回はテーブルカラムとフィルター機能を深掘りし、一覧画面を強化します。