Laravel 包

Lattice: Describe Inertia UIs in PHP

发布
Lattice: Describe Inertia UIs in PHP image

Lattice is a server-driven UI framework for Laravel that lets you describe a screen — its pages, forms, tables, actions, and menus — in PHP and have it render as real React components over Inertia. Lattice makes the server the single source of truth for what a screen , leaving the client with one job — rendering it.

A page is a PHP class that builds a tree of component definitions. Lattice serializes that tree to a typed payload, ships it over Inertia as a normal page visit, and a single React component resolves each node against a component registry to draw it.

What you get out of that model:

  • Pages as classes, routed automatically. A #[AsPage] attribute registers the route; Lattice scans your configured paths and wires it up without a manual route entry.
  • Forms backed by Laravel validation. Fields are declared in PHP, validated with standard Laravel rules, and optionally validated live through Precognition.
  • Eloquent-backed tables. Columns, sorting, filtering, and pagination are defined on a table class that returns a query builder.
  • Server-side actions that return effects. An action runs your PHP on click and hands back instructions — a toast, a redirect, a component refresh — for the client to dispatch.

页面

A page extends the base Page class, carries an #[AsPage] attribute for its route, and builds its UI in render() . The component tree is assembled with fluent PHP — Stack , Grid , Heading , Card , and so on — rather than JSX:

使用 Lattice\Lattice\Attributes\AsPage ;
使用 Lattice\Lattice\Core\Components\Card ;
使用 Lattice\Lattice\Core\Components\Grid ;
使用 Lattice\Lattice\Core\Components\Heading ;
使用 Lattice\Lattice\Core\Components\Stack ;
使用 Lattice\Lattice\Core\Components\Text ;
使用 Lattice\Lattice\Core\Enums\Gap ;
使用 Lattice\Lattice\Core\PageSchema ;
使用 Lattice\Lattice\Http\Page 作为 BasePage ;
#[ AsPage 路线 : '/仪表板' , 中间件 :[ '网络' ])]
最终的 班级 DashboardPage 延伸 BasePage
{
民众 功能 标题 () : 细绳
{
返回 '仪表板' ;
}
民众 功能 使成为 PageSchema $schema) : PageSchema
{
返回 $schema -> 模式 ([
:: 制作 '仪表板'
-> gap Gap :: 大的
-> 模式 ([
标题 :: 制作 '仪表板' ),
文本 :: 制作 'Everything below is described in PHP and rendered as React.' ),
网格 :: 制作 统计数据
-> 2
-> 模式 ([
卡片 :: 制作 'Orders' , '128 this week.' ),
卡片 :: 制作 'Revenue' , '$4,210 this week.' ),
]),
]),
]);
}
}

Route parameters resolve straight into the render() signature with Laravel's route-model binding, and an authorize() method gates access before the page renders:

#[ AsPage 路线 : '/products/{product}/edit' )]
班级 ProductEditPage 延伸
{
民众 功能 授权 要求 $请求) : 布尔值
{
返回 $请求 -> 用户 () ?-> '更新' , 产品 ::班级 ?? 错误的 ;
}
民众 功能 使成为 PageSchema $schema, 产品 $产品) : PageSchema
{
返回 $schema -> 模式 ([
标题 :: 制作 "Edit { $产品 -> 姓名 }” ),
]);
}
}

表格

A form is a class extending FormDefinition that declares its fields and handles the submission. Lattice renders the React inputs, validates the request against your Laravel rules, and runs handle() on a successful submit:

使用 照亮\Http\请求 ;
使用 Lattice\Lattice\Attributes\AsForm ;
使用 Lattice\Lattice\Forms\Components\Form 作为 FormComponent ;
使用 Lattice\Lattice\Forms\Components\TextInput ;
使用 Lattice\Lattice\Forms\FormDefinition ;
使用 Symfony\Component\HttpFoundation\Response ;
#[ AsForm 'app.profile.form' )]
班级 ProfileForm 延伸 FormDefinition
{
民众 功能 定义 FormComponent $form, 要求 $请求) : FormComponent
{
返回 表单 -> 模式 ([
文本输入 :: 制作 '姓名' , '姓名' -> 规则 ([ '必需的' , '细绳' , '最大:255' ]),
文本输入 :: 制作 '电子邮件' , 'Email' -> 电子邮件 () -> 规则 ([ '必需的' , '电子邮件' ]),
]);
}
民众 功能 处理 要求 $请求) : 回复
{
$已验证 = $this -> 证实 (请求)
$请求 -> 用户 () -> 更新 (已验证)
返回 重定向 '/轮廓' (英文):
}
}

Dropping the form onto a page is a single call, with fluent configuration for the HTTP method, submit label, and the data it's filled with. Adding ->precognitive(500) opts into live validation through Laravel Precognition:

形式 :: 使用 ProfileForm ::班级
-> 方法 HttpMethod :: 修补
-> submitLabel 'Save changes'
-> precognitive 500
-> 充满 ([
'姓名' => $用户 -> 姓名,
'电子邮件' => $用户 -> 电子邮件,
]);

表格

Tables extend EloquentTableDefinition . You declare the columns and return a query builder; sorting, filtering, and pagination are handled for you based on which columns you mark as sortable() 或者 filterable() :

使用 照亮\数据库\Eloquent\Builder ;
使用 Lattice\Lattice\Attributes\AsTable ;
使用 Lattice\Lattice\Tables\Columns\BooleanColumn ;
使用 Lattice\Lattice\Tables\Columns\NumberColumn ;
使用 Lattice\Lattice\Tables\Columns\TextColumn ;
使用 Lattice\Lattice\Tables\EloquentTableDefinition ;
使用 Lattice\Lattice\Tables\TableQuery ;
#[ AsTable 'app.products' )]
班级 ProductsTable 延伸 EloquentTableDefinition
{
民众 功能 () : 大批
{
返回 [
TextColumn :: 制作 '姓名' -> 可排序 () -> 可过滤 (),
NumberColumn :: 制作 '价格' -> 可排序 () -> 可过滤 (),
BooleanColumn :: 制作 “特色” ),
TextColumn :: 制作 'updated_at' -> 日期 'Ymd' -> 可排序 (),
];
}
民众 功能 建造者 TableQuery $query) : 建造者
{
返回 产品 :: 询问 ();
}
}

Rendering it on a page reuses the same ::use() pattern as forms, so a products page composes its heading and table from the two classes:

$schema -> 模式 ([
标题 :: 制作 'Products' ),
桌子 :: 使用 ProductsTable ::班级 ),
]);

Actions and client effects

Actions are where the round trip shows up. An action extends ActionDefinition , describes its button in definition() , and runs server-side in handle() . Rather than returning a view, it returns an ActionResult carrying effects — instructions the client dispatches, such as a toast and a component reload:

使用 照亮\Http\请求 ;
使用 Lattice\Lattice\Actions\ActionDefinition ;
使用 Lattice\Lattice\Actions\ActionResult ;
使用 Lattice\Lattice\Actions\Components\Action ;
使用 Lattice\Lattice\Attributes\AsAction ;
使用 Lattice\Lattice\Core\Enums\ButtonVariant ;
使用 Lattice\Lattice\Core\Enums\Variant ;
#[ AsAction 'app.products.archive' )]
班级 ArchiveProductAction 延伸 ActionDefinition
{
民众 功能 定义 行动 $action) : 行动
{
返回 $action
-> 标签 'Archive'
-> variant ButtonVariant :: Destructive
-> 确认 'Archive product?' , 'This hides it from the catalogue.' (英文):
}
民众 功能 处理 要求 $请求) : ActionResult
{
$产品 = $this -> 产品 (请求)
$产品 -> 更新 ([ '地位' => 已存档 ]);
返回 ActionResult :: 成功 ()
-> 吐司 Variant :: 成功 , 'Product archived.'
-> reloadComponent 'app.products' (英文):
}
}

Attached to a table row, the action carries the row's context to the server so handle() knows which record it's acting on:

行动 :: 使用 ArchiveProductAction ::班级
-> 语境 ([ 'product_id' => $row[ 'ID' ]]);

了解更多

📕 Installation, component reference, and theming options are found in the 文档

💻 The source is available on GitHub

保罗·雷德蒙德照片

Laravel News 特约撰稿人。全栈 Web 开发人员兼作家。

Filed in

赞助

laravelcloud logo
Laravel 云

轻松创建和管理服务器,并在几秒钟内部署 Laravel 应用程序。

访问 Laravel Cloud
Official Laravel Zed Extension: LSP for PHP & Blade image

Official Laravel Zed Extension: LSP for PHP & Blade

阅读文章
Laravel Head: Manage Meta Tags, Open Graph, and JSON-LD image

Laravel Head: Manage Meta Tags, Open Graph, and JSON-LD

阅读文章
PhpStorm 2026.2 Released image

PhpStorm 2026.2 Released

阅读文章
Laravel Doctor: Diagnose Your App With One Artisan Command image

Laravel Doctor: Diagnose Your App With One Artisan Command

阅读文章
CPX: The Composer Package Executor for PHP image

CPX: The Composer Package Executor for PHP

阅读文章
Laravel AI SDK Adds Human-in-the-Loop Tool Approval image

Laravel AI SDK Adds Human-in-the-Loop Tool Approval

阅读文章