Ой, ничего не найдено!

К сожалению, по вашему запросу пока ничего нет (но это только пока!), зато вы можете подписаться на нашу замечательную email-рассылку, чтобы не пропустить самое интересное в будущем.

  • 10

Гайд: Кастомная страница в Filament 3 с использованием класса Page

Создание страницы через Artisan

Начнем с генерации новой страницы с помощью специальной Artisan-команды Filament. В Filament 3 доступна команда make:filament-page, которая автоматически создает класс страницы и соответствующее представление (Blade-шаблон). Например, чтобы создать страницу настроек, выполните команду:

php artisan make:filament-page Settings

После выполнения команды будут сгенерированы два файла:

  • Класс страницы – обычно помещается в каталог app/Filament/Pages. В нашем примере будет создан файл app/Filament/Pages/Settings.php. Этот класс наследует Filament\Pages\Page и будет содержать базовую заготовку страницы.
  • Blade-шаблон страницы – файл представления размещается в директории resources/views/filament/pages. Для страницы Settings будет создан шаблон resources/views/filament/pages/settings.blade.php. Этот шаблон отвечает за разметку страницы в интерфейсе Filament.

Структура класса Page и шаблона представления

Откройте сгенерированный класс страницы (например, Settings.php). Он должен наследовать базовый класс Filament Page и может содержать некоторые свойства для настройки страницы. Важные моменты структуры класса:

  • Имя класса и наследование: класс должен расширять Filament\Pages\Page. Например:

    class Settings extends Page
    {
        // ...
    }
    
  • Свойство $view: обычно в классе указывается, какой Blade-шаблон использовать для этой страницы. Статическое свойство $view содержит путь к представлению. Для страницы Settings по умолчанию будет:

    protected static string $view = 'filament.pages.settings';
    

    Это соответствует файлу resources/views/filament/pages/settings.blade.php. Filament будет рендерить этот шаблон, когда пользователь переходит на страницу.

  • Иконка и название в навигации (опционально): вы можете указать значок и метку для меню панели админки:

    protected static ?string $navigationIcon = 'heroicon-o-cog';
    protected static ?string $navigationLabel = 'Настройки';
    

    Если эти свойства не указать, Filament сформирует название автоматически на основе имени класса, а иконка по умолчанию может быть пустой. В нашем примере мы устанавливаем иконку "шестеренка" и явно задаем название пункта меню "Настройки". После настройки класса, убедитесь, что Blade-шаблон (например, filament/pages/settings.blade.php) существует. Изначально он может содержать базовую обертку страницы, например:

<x-filament-panels::page>
    <!-- Контент страницы будет здесь -->
</x-filament-panels::page>

Эта обертка <x-filament-panels::page> обеспечивает оформление страницы согласно стилям Filament.

Подключение формы ($form) на странице

Теперь перейдем к добавлению формы на нашу кастомную страницу. Filament предоставляет мощный конструктор форм (Filament Forms), который можно использовать внутри кастомных страниц. Однако, просто определив метод getFormSchema() в классе, форму вы не увидите – необходимо подключить поддержку форм к странице.

1. Подключение трейта и интерфейса HasForms: В классе страницы нужно реализовать интерфейс Filament\Forms\Contracts\HasForms и подключить трейт Filament\Forms\Concerns\InteractsWithForms. Это обеспечит класс всеми необходимыми свойствами и методами для работы с формой. Пример начала класса:

use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Pages\Page;
class Settings extends Page implements HasForms
{
    use InteractsWithForms;
    // ...
}
Начните с нами: 6 месяцев бесплатного хостинга!
Используйте промокод FREE6MONTH и раскройте потенциал своего сайта без финансовых вложений.

После этих изменений класс страницы становится Livewire-компонентом с формой, и у него появляется свойство $form для работы с формой. Если не реализовать HasForms/InteractsWithForms, методы формы (например, getFormSchema()) вызваны не будут, и форма не отобразится. Именно по этой причине часто "не работает" getFormSchema() – просто Page сам по себе не знает про форму, пока мы не подключим HasForms.

2. Определение схемы формы: Есть два основных способа описать поля формы в Filament:

  • Через метод getFormSchema(): Этот способ заключается в определении защищенного метода, возвращающего массив компонентов формы. Filament вызовет его внутри трейта InteractsWithForms и сформирует объект формы. Например, добавим в класс Settings метод:

    use Filament\Forms\Components\TextInput;
    class Settings extends Page implements HasForms
    {
        use InteractsWithForms;
        // ...
        protected function getFormSchema(): array
        {
            return [
                TextInput::make('site_name')->label('Название сайта')->required(),
                TextInput::make('site_email')->label('Email сайта')->email(),
            ];
        }
    }
    

    Здесь мы используем компоненты Filament Forms – два поля ввода (TextInput) для примера настроек: название сайта и email. Метод getFormSchema() возвращает массив таких полей ,TextInput%3A%3Amake('site_name')%2C ]%3B)). Filament автоматически обернет эти поля в объект формы и свяжет с Livewire-свойствами.

  • Через метод form() с объектом Form: Новый способ, появившийся в Filament 3 – определение метода public function form(Form $form): Form. Вы можете строить форму через предоставленный объект $form. Результат аналогичен getFormSchema(), но позволяет настроить дополнительные параметры формы (например, state path). Пример альтернативного определения:

  • use Filament\Forms\Form;
    use Filament\Forms\Components\TextInput;
    class Settings extends Page implements HasForms
    {
        use InteractsWithForms;
        public ?array $data = []; // массив для состояния формы (optional)
        public function form(Form $form): Form
        {
            return $form
                ->schema([
                    TextInput::make('site_name')->label('Название сайта')->required(),
                    TextInput::make('site_email')->label('Email сайта')->email(),
                ])
                ->statePath('data');
        }
    }
    

    В этом подходе мы настраиваем форму используя Fluent API: вызываем $form->schema([...])->statePath('data'). Свойство statePath указывает, куда сохранять состояние формы (в данном случае в массив $data внутри компонента). Этот метод является предпочтительным в Filament 3, и он работает так же, как в ресурсах Filament.

Оба подхода допустимы. Если вы используете getFormSchema(), Filament сам создаст форму и сохранит ее состояние во внутреннем свойстве $form. Если используете метод form(), вы более явно строите объект формы. Для простоты в нашем гайде будем считать, что используем getFormSchema(), но важно понимать, что необходимо реализовать HasForms + InteractsWithForms независимо от выбранного способа.

Рендеринг формы в шаблоне

После того, как мы описали схему формы в классе, нужно отобразить форму на странице через Blade-шаблон. Filament не рендерит форму автоматически на кастомной странице, поэтому мы вручную добавим форму в шаблон.

Откройте файл resources/views/filament/pages/settings.blade.php (созданный Artisan’ом). Внутри обертки <x-filament-panels::page>...</x-filament-panels::page> добавьте компоненты для формы. Filament предоставляет специальный Blade-компонент <x-filament-panels::form> для оформления формы.

Также можно использовать стандартный HTML-формат. Рассмотрим вариант с Blade-компонентом:

<x-filament-panels::page>
    <x-filament-panels::form wire:submit.prevent="save">
        {{ $this->form }}
        <div class="mt-4">
            <x-filament::button type="submit">
                Сохранить
            </x-filament::button>
        </div>
    </x-filament-panels::form>
</x-filament-panels::page>
Специальное предложение: бесплатный хостинг на полгода!
Введите промокод FREE6MONTH при регистрации и наслаждайтесь надежным хостингом бесплатно.

Разберем этот шаблон:

  • <x-filament-panels::form> – обертка для формы, которая автоматически применяет стили Filament. Атрибут wire:submit.prevent="save" навешивает на форму событие Livewire для обработки отправки (метод save в классе компонента).
  • {{ $this->form }} – выводит саму форму, сгенерированную Filament (согласно нашей схеме из getFormSchema() или form() метода). Переменная $this->form доступна благодаря трейту InteractsWithForms и содержит готовую форму для рендеринга.
  • Блок с кнопкой <x-filament::button type="submit">Сохранить</x-filament::button> – отображает кнопку отправки формы. Мы используем Filament Blade-компонент button для конституентного стиля (можно указать стили, размер и т.д.). Тип submit обеспечивает отправку формы по нажатию.

Обратите внимание: без вывода $this->form в шаблоне форма не появится. Многие начинающие могут определить getFormSchema() и забыть, что на странице нужно явно отрисовать форму. Здесь мы это сделали – поместив {{ $this->form }} внутри формы.

Альтернативный способ рендеринга – не использовать <x-filament-panels::form>, а написать обычный <form> с нужными атрибутами. Результат будет аналогичный. Главное, чтобы внутри формы был вывод $this->form и кнопка для отправки. Использование же компонентов Filament упрощает стилизацию и делает код чище.

Кнопка "Сохранить" на кастомной странице

В ресурсах Filament (например, на странице создания/редактирования записи) кнопки сохранения появляются автоматически. Однако для кастомной Page-страницы разработчик должен сам добавить кнопку в интерфейс. В примере выше мы уже добавили кнопку "Сохранить" вручную в Blade-шаблоне. Этот подход правильный: Filament не добавит кнопку автоматически, так как он не знает, что и как вы хотите сохранить на вашей странице.

Еще один подход – использовать Filament Actions (действия) для формы. Например, можно определить метод getFormActions() в классе страницы, возвращающий массив из Filament\Actions\Action::make('save'). Но для простоты мы используем прямую кнопку в шаблоне. Это совершенно нормально для кастомной страницы.

Итого: чтобы отобразить кнопку "Сохранить", убедитесь, что в вашем Blade-шаблоне внутри формы есть кнопка с type="submit" (либо Blade-компонент x-filament::button, либо обычный <button>). Это позволит пользователю отправить данные формы.

Специальное предложение: бесплатный хостинг на полгода!
Введите промокод FREE6MONTH при регистрации и наслаждайтесь надежным хостингом бесплатно.

Обработка отправки формы: сохранение данных в базу

Теперь реализуем логику сохранения введенных данных. В нашем случае, мы хотим сохранить значения нескольких TextInput в таблицу настроек (модель Setting) и обновить конфигурацию приложения config().

Предположим, модель Setting хранит пары ключ-значение (например, key = 'site_name', value = 'My Site'). Мы будем сохранять настройки по этим ключам. В классе страницы (Settings) добавим метод, указанный в атрибуте wire:submit нашей формы – например, метод save():

use App\Models\Setting;
use Filament\Support\Exceptions\Halt;
use Filament\Notifications\Notification;
class Settings extends Page implements HasForms
{
    use InteractsWithForms;
    // ... схема формы определена выше ...
    public function save(): void
    {
        // Получаем данные формы
        $data = $this->form->getState();
        try {
            // Сохраняем каждое поле в таблицу настроек
            Setting::updateOrCreate(
                ['key' => 'site_name'],
                ['value' => $data['site_name']]
            );
            Setting::updateOrCreate(
                ['key' => 'site_email'],
                ['value' => $data['site_email']]
            );
            // Обновляем runtime-конфигурацию приложения
            config(['app.site_name' => $data['site_name']]);
            config(['app.site_email' => $data['site_email']]);
        } catch (Halt $exception) {
            // Если Filament отклоняет сохранение (например, валидация), прерываем процесс
            return;
        }
        // Отправляем уведомление об успешном сохранении
        Notification::make()
            ->title('Настройки сохранены')  
            ->success()  
            ->send();
    }
}

Разберем этот код:

  • $data = $this->form->getState(); – получаем все значения полей формы в виде массива. Метод getState() возвращает ассоциативный массив ['имя_поля' => значение, ...].
  • С помощью метода Eloquent updateOrCreate мы сохраняем каждую настройку. Для поля site_name ищем запись с ключом 'site_name' и обновляем ее значение. Аналогично для site_email. Вы можете использовать и другие подходы (например, если у вас модель настроек реализована иначе), главное – сохранить новые значения.
  • Обновляем конфигурацию приложения через хелпер config([...]). Здесь мы предполагаем, что в конфиге (например, config/app.php или другом) есть соответствующие параметры, которые нужно обновить. Вызов config(['app.site_name' => ...]) динамически меняет значение в текущем сеансе. Это полезно, если другие части приложения читают эти настройки через config(). Учтите: если конфигурация закеширована, такие изменения носят временный характер. В рамках работы Livewire-компонента они будут применены.
  • Блок try { ... } catch (Halt $exception) используется на случай, если Filament выбросит исключение Halt. Такое может произойти, например, если сработает валидация, и Filament решит прервать дальнейшее выполнение метода. Мы перехватываем Halt и просто return, чтобы избежать ненужных действий после прерывания. (В данном коде валидация не показана, но её можно настроить через $rules или ->required() в полях, Filament сам валидирует поля, и при ошибках метод save не выполнит содержимое до конца.)
  • После успешного сохранения вызываем отправку уведомления (рассмотрено ниже).

Таким образом, при нажатии на кнопку "Сохранить" форма отправится, вызовется метод save(), и данные запишутся в базу (таблицу settings). Если у вас другая логика (например, нужно сохранять в связанную модель или вызывать сервис), реализуйте её внутри метода.

Отображение сообщения об успехе

После сохранения настроек, хорошо бы уведомить пользователя, что операция прошла успешно. Filament имеет встроенную систему уведомлений (Notifications). В коде выше мы уже задействовали её через фасад Notification::make(). Разберем, как это работает.

Чтобы показать уведомление, достаточно добавить:

use Filament\Notifications\Notification;
// ... внутри метода save() после сохранения ...
Notification::make()
    ->title('Настройки сохранены')
    ->success()
    ->send();
Получите 6 месяцев бесплатного хостинга!
Воспользуйтесь нашим промокодом FREE6MONTH и начните свой проект без лишних затрат.

Этот fluent-вызов формирует и отображает всплывающее уведомление. Мы указываем заголовок уведомления (title), помечаем его как успешное (success() – обычно окрашивает в зеленый цвет) и вызываем send() для отправки на фронтенд.

Filament позаботился о том, чтобы в панели админки Laravel уже был подключен компонент Livewire для уведомлений (обычно @livewire('notifications') встроен в layout Filament Panel). Поэтому вызов Notification::make()->send() мгновенно покажет сообщение пользователю.

Вы можете настроить и другие свойства уведомления (текст сообщения, иконку, длительность показа и т.д.), но для нашего гайда достаточно показать простой кейс – уведомление об успешном сохранении.

Теперь, когда пользователь нажмет "Сохранить", после записи данных он увидит всплывающее сообщение "Настройки сохранены".

Расширение страницы: вкладки, повторители и прочее

Наша текущая страница настроек довольно простая – два текстовых поля. Одним из преимуществ подхода с кастомной Page и Filament Forms является легкость масштабирования формы. Вы можете добавлять новые поля, группы полей и даже сложные компоненты без изменения общей структуры страницы.

Вот несколько способов расширения функциональности:

  • Вкладки (Tabs): Если настроек много, имеет смысл разделить форму на вкладки. Filament Forms предоставляет компонент Tabs. Вы можете обернуть части схемы формы во вкладки. Например, разделим настройки на "Общие" и "Безопасность":

    use Filament\Forms\Components\Tabs;
    use Filament\Forms\Components\Tabs\Tab;
    protected function getFormSchema(): array
    {
        return [
            Tabs::make('SettingsTabs')->tabs([
                Tab::make('Общие')->schema([
                    TextInput::make('site_name')->label('Название сайта')->required(),
                    TextInput::make('site_email')->label('Email сайта')->email(),
                ]),
                Tab::make('Безопасность')->schema([
                    // здесь можно добавить поля безопасности, например пароль админа или ключи API
                    TextInput::make('admin_password')->label('Пароль администратора')->password(),
                ]),
            ]),
        ];
    }
    

    Такой подход поместит поля в две вкладки внутри единой формы. По умолчанию открыта будет первая вкладка ("Общие"), между ними можно переключаться. Это удобно для организации большого количества опций.

  • Повторители (Repeater): Если требуется вводить множественные повторяющиеся данные (например, список контактных телефонов, адресов, социальных ссылок и т.д.), можно использовать компонент Repeater. Repeater позволяет вложить набор полей, которые пользователь может добавлять или удалять динамически. Пример добавления повторителя:

    use Filament\Forms\Components\Repeater;
    use Filament\Forms\Components\TextInput;
    protected function getFormSchema(): array
    {
        return [
            // ... другие поля ...
            Repeater::make('contacts')
                ->label('Контакты')
                ->schema([
                    TextInput::make('phone')->label('Телефон'),
                    TextInput::make('email')->label('Email'),
                ])
                ->columns(2), // показывать поля повторителя в две колонки
        ];
    }
    

    В этом примере поле contacts будет представлять собой список элементов, каждый из которых содержит два подполя: телефон и email. Пользователь сможет нажать "Add" (добавить) несколько контактов. Данные contacts в итоге будут массивом, который можно сохранить (часто в JSON поле базы).

  • Другие компоненты: Filament Forms предлагает много готовых компонентов – выпадающие списки Select, переключатели Toggle, поле DatePicker для дат, FileUpload для загрузки файлов, и др. Добавлять их можно так же, как мы добавляли TextInput, изменяя схему формы. Например, можно добавить Select::make('timezone') для выбора часового пояса, или группу переключателей через CheckboxList::make('roles'), и т.д. Эти компоненты настраиваются через методы (options, multiple, reactive и пр.) согласно документации Filament.

  • Расширение логики: Класс Page не ограничивается одной формой. Можно добавить виджеты (Widgets) на страницу, дополнительные действия (Actions) в шапке, или даже несколько форм. Если в будущем вам понадобится, например, вторую форму на этой же странице (скажем, отдельный блок настроек, который сохраняется отдельно), вы можете реализовать это, хотя в Filament 3 есть ограничения на несколько форм в одном Livewire-компоненте. Часто вместо этого делают просто одну форму с разделами или вкладками. Также Page-класс можно расширять, используя Livewire хуки (mount, render и т.д.) для загрузки данных, применения фильтров и пр.

Эксклюзивно для читателей: полгода бесплатного хостинга!
Заберите свой промокод FREE6MONTH и воспользуйтесь всеми преимуществами премиум-хостинга бесплатно.

В итоге, кастомная страница на Filament 3, созданная через Page, предоставляет гибкость: вы получаете полноэкранную страницу в админ-панели, полностью контролируете какие элементы на ней находятся. В нашем гайде мы разобрали:

  • Создание страницы и ее шаблона.
  • Подключение Filament Forms и описание полей.
  • Рендеринг формы и ручное добавление кнопки сохранения.
  • Обработку сохранения: запись в базу (модель Setting) и обновление config().
  • Отображение уведомления об успехе пользователю.
  • Возможности по расширению формы (Tabs, Repeater и др.).

Следуя этим шагам, вы можете создать свою страницу настроек (или любую другую кастомную страницу) без использования Resource или SettingsPage, полностью контролируя логику. Получившаяся форма проста, и при этом ее легко масштабировать под будущие требования. Enjoy! 😉

Хостинг, на который можно положиться!
Siteko.net

Устали от медленного хостинга или дорогих тарифов? Тогда вам к нам! Siteko.net — это быстрый и простой хостинг для тех, кто ценит удобство и стабильность.

  • Без падений и нервов — наш uptime почти всегда 100%.
  • Гибкие тарифы — только нужные функции, ничего лишнего.
  • Скорость— сайты грузятся, как пуля!
  • Удобно — разобраться сможет даже новичок, всё под рукой.
  • Поддержка всегда рядом 24/7 поможем решить любой вопрос.

Заходите на Siteko.net и попробуйте нас бесплатно первый месяц! Мы делаем всё, чтобы ваш сайт работал без проблем.

Siteko.net — просто, быстро и надёжно!