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 。







