Lattice: описуйте Inertia UI на PHP

Перекладено ШІ 0 Laravel News 19 червня, 2026

Lattice дозволяє створювати сучасні React-інтерфейси, описуючи структуру сторінок, форм та таблиць виключно мовою PHP. Дізнайтеся, як зробити сервер єдиним джерелом істини для всього вашого фронтенду.

Lattice — це SDUI-фреймворк (Server-driven UI) для Laravel, який дозволяє описувати інтерфейс сторінок, форм, таблиць та меню за допомогою PHP. Завдяки Inertia ці структури рендеряться як реальні React-компоненти. З Lattice сервер стає єдиним джерелом істини (single source of truth) для опису екранів, залишаючи клієнту лише одне завдання — їхнє відображення.

Кожна сторінка — це PHP-клас, що будує дерево компонентів. Lattice серіалізує це дерево у типізований payload і передає його через Inertia як звичайний візит. На фронтенді єдиний React-компонент зіставляє кожен вузол із реєстром компонентів і малює інтерфейс.

Ключові переваги такої моделі:

  • Автоматичний роутинг сторінок-класів. Атрибут #[AsPage] реєструє маршрут автоматично — Lattice сканує вказані шляхи та підключає їх без ручного внесення в routes.
  • Форми з нативною валідацією Laravel. Поля описуються в PHP, перевіряються стандартними правилами Laravel, а за потреби підтримують «живу» валідацію через Precognition.
  • Таблиці на базі Eloquent. Колонки, сортування, фільтрація та пагінація визначаються у класі таблиці, який повертає query builder.
  • Серверні дії (Actions) з ефектами. При кліку виконується PHP-код, який повертає клієнту інструкції: показати toast-сповіщення, виконати редирект або оновити компонент.

# Сторінки

Сторінка успадковує базовий клас Page, використовує атрибут #[AsPage] для роутингу та будує UI у методі render(). Замість JSX дерево компонентів збирається за допомогою ланцюжкових викликів PHP: Stack, Grid, Heading, Card тощо.

use Lattice\Lattice\Attributes\AsPage;
use Lattice\Lattice\Core\Components\Card;
use Lattice\Lattice\Core\Components\Grid;
use Lattice\Lattice\Core\Components\Heading;
use Lattice\Lattice\Core\Components\Stack;
use Lattice\Lattice\Core\Components\Text;
use Lattice\Lattice\Core\Enums\Gap;
use Lattice\Lattice\Core\PageSchema;
use Lattice\Lattice\Http\Page as BasePage;
 
#[AsPage(route: '/dashboard', middleware: ['web'])]
final class DashboardPage extends BasePage
{
    public function title(): string
    {
        return 'Dashboard';
    }
 
    public function render(PageSchema $schema): PageSchema
    {
        return $schema->schema([
            Stack::make('dashboard')
                ->gap(Gap::Large)
                ->schema([
                    Heading::make('Dashboard'),
                    Text::make('Everything below is described in PHP and rendered as React.'),
                    Grid::make('stats')
                        ->columns(2)
                        ->schema([
                            Card::make('Orders', '128 this week.'),
                            Card::make('Revenue', '$4,210 this week.'),
                        ]),
                ]),
        ]);
    }
}

Параметри маршруту передаються безпосередньо в render() через route-model binding. Також можна використовувати метод authorize() для перевірки прав доступу перед рендерингом:

#[AsPage(route: '/products/{product}/edit')]
class ProductEditPage extends Page
{
    public function authorize(Request $request): bool
    {
        return $request->user()?->can('update', Product::class) ?? false;
    }
 
    public function render(PageSchema $schema, Product $product): PageSchema
    {
        return $schema->schema([
            Heading::make("Edit {$product->name}"),
        ]);
    }
}

# Форми

Форма — це клас FormDefinition, де описуються поля та логіка обробки. Lattice рендерить React-інпути, валідує запит за правилами Laravel і виконує handle() після успішного сабміту:

use Illuminate\Http\Request;
use Lattice\Lattice\Attributes\AsForm;
use Lattice\Lattice\Forms\Components\Form as FormComponent;
use Lattice\Lattice\Forms\Components\TextInput;
use Lattice\Lattice\Forms\FormDefinition;
use Symfony\Component\HttpFoundation\Response;
 
#[AsForm('app.profile.form')]
class ProfileForm extends FormDefinition
{
    public function definition(FormComponent $form, Request $request): FormComponent
    {
        return $form->schema([
            TextInput::make('name', 'Name')->rules(['required', 'string', 'max:255']),
            TextInput::make('email', 'Email')->email()->rules(['required', 'email']),
        ]);
    }
 
    public function handle(Request $request): Response
    {
        $validated = $this->validate($request);
        $request->user()->update($validated);
 
        return redirect('/profile');
    }
}

Додати форму на сторінку можна одним викликом, гнучко налаштовуючи HTTP-метод, текст кнопки та початкові дані. Опція ->precognitive(500) активує «живу» перевірку помилок:

Form::use(ProfileForm::class)
    ->method(HttpMethod::Patch)
    ->submitLabel('Save changes')
    ->precognitive(500)
    ->fill([
        'name' => $user->name,
        'email' => $user->email,
    ]);

# Таблиці

Таблиці розширюють EloquentTableDefinition. Ви визначаєте колонки та повертаєте query builder, а Lattice автоматично бере на себе сортування, фільтрацію та пагінацію для полів, позначених як sortable() чи filterable():

use Illuminate\Database\Eloquent\Builder;
use Lattice\Lattice\Attributes\AsTable;
use Lattice\Lattice\Tables\Columns\BooleanColumn;
use Lattice\Lattice\Tables\Columns\NumberColumn;
use Lattice\Lattice\Tables\Columns\TextColumn;
use Lattice\Lattice\Tables\EloquentTableDefinition;
use Lattice\Lattice\Tables\TableQuery;
 
#[AsTable('app.products')]
class ProductsTable extends EloquentTableDefinition
{
    public function columns(): array
    {
        return [
            TextColumn::make('name')->sortable()->filterable(),
            NumberColumn::make('price')->sortable()->filterable(),
            BooleanColumn::make('featured'),
            TextColumn::make('updated_at')->date('Y-m-d')->sortable(),
        ];
    }
 
    public function builder(TableQuery $query): Builder
    {
        return Product::query();
    }
}

Рендеринг у компоненті використовує той самий підхід ::use(), що й у формах:

$schema->schema([
    Heading::make('Products'),
    Table::use(ProductsTable::class),
]);

# Actions та клієнтські ефекти

Actions дозволяють виконувати серверний код у відповідь на дії користувача. Клас ActionDefinition описує кнопку в definition() та виконує логіку в handle(). Замість повернення view, він повертає ActionResult з «ефектами» — командами для клієнта (наприклад, показати сповіщення або оновити частину сторінки):

use Illuminate\Http\Request;
use Lattice\Lattice\Actions\ActionDefinition;
use Lattice\Lattice\Actions\ActionResult;
use Lattice\Lattice\Actions\Components\Action;
use Lattice\Lattice\Attributes\AsAction;
use Lattice\Lattice\Core\Enums\ButtonVariant;
use Lattice\Lattice\Core\Enums\Variant;
 
#[AsAction('app.products.archive')]
class ArchiveProductAction extends ActionDefinition
{
    public function definition(Action $action): Action
    {
        return $action
            ->label('Archive')
            ->variant(ButtonVariant::Destructive)
            ->confirm('Archive product?', 'This hides it from the catalogue.');
    }
 
    public function handle(Request $request): ActionResult
    {
        $product = $this->product($request);
        $product->update(['status' => 'archived']);
 
        return ActionResult::success()
            ->toast(Variant::Success, 'Product archived.')
            ->reloadComponent('app.products');
    }
}

Прив’язана до рядка таблиці дія автоматично передає контекст на сервер, щоб handle() знав, з яким записом працювати:

Action::use(ArchiveProductAction::class)
    ->context(['product_id' => $row['id']]);

# Дізнатися більше

📕 Інструкції зі встановлення, довідник компонентів та налаштування тем доступні в документації.

💻 Вихідний код проєкту відкрито на GitHub.

Популярні

Інше, що варто прочитати

19 Оновлено 19 червня, 2026

Оптимізація запитів до бази даних за допомогою скорочених методів Laravel

Laravel пропонує зручні методи для роботи з датами, які значно спрощують запити до бази даних. Досліджуйте, як ці інтуїтивно зрозумілі функції допомагають створювати чіткі та зрозумілі умови для роботи з часовими даними!

11 Оновлено 19 червня, 2026

Локальні моделі та їх скоупи в Laravel за допомогою атрибута Scope

В Laravel 12 ми отримали можливість використовувати новий підхід для визначення локальних скоупів у моделях Eloquent. Дізнайтеся, як новий атрибут #[Scope] спрощує цей процес і зберігає ваші назви методів незмінними

56 Оновлено 19 червня, 2026

Усе, що нам відомо про Livewire 4

Нова версія Livewire 4, представленої Келебом Порзіо на Laracon US 2025, обіцяє значні покращення у швидкості та організації компонентів. Які з інноваційних функцій підкорять ваше серце? Читайте далі, щоб дізнатися більше про те, як Livewire 4 полегшить вашу роботу