news 2026/9/10 10:02:39

Filament Infolists KeyValueEntry 详解:键值对数据的表格化展示与列标题定制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Filament Infolists KeyValueEntry 详解:键值对数据的表格化展示与列标题定制

Filament Infolists KeyValueEntry 详解:键值对数据的表格化展示与列标题定制

【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps & admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filament

KeyValueEntry 是 Filament Infolists 组件库中用于展示"一维键值对数据"(如 JSON 对象或 PHP 关联数组)的专用 Entry。本文基于仓库中的官方文档 packages/infolists/docs/07-key-value-entry.md,结合 KeyValueEntry.php 源码实现与 KeyValueEntryTest.php 测试用例,系统讲解其基本用法、Eloquent 数据落库方式、keyLabel()/valueLabel()列标题定制(含闭包动态计算),以及底层渲染与空状态行为,帮助你在一站式详情页(Infolist)中专业地呈现元数据、SEO 标签、设置项等键值型数据。

什么是 KeyValueEntry

KeyValueEntry 允许你从一个一维的 JSON 对象 / PHP 数组中渲染出键值对数据。它的典型使用场景包括:文章元信息(meta)、Open Graph / SEO 标签、用户自定义设置、环境变量等"键-值"结构的数据展示。

在 07-key-value-entry.md 中,基础用法如下:

use Filament\Infolists\Components\KeyValueEntry; KeyValueEntry::make('meta')

make()接收的参数meta是状态路径(state path),即从当前 Infolist 绑定的数据中取出的字段名。例如,当绑定的记录包含如下meta数据时,Entry 会将其渲染为一张两列的表格:

[ 'description' => 'Filament is a collection of Laravel packages', 'og:type' => 'website', 'og:site_name' => 'Filament', ]

渲染结果中,数组的键(如descriptionog:type)显示在左列,对应的值显示在右列,即默认列标题为KeyValue(可自定义,见下文)。

在完整的 Infolist 上下文里,KeyValueEntry 通常作为infolist()方法中的组件使用,例如在 Resource 的ViewRecord页面中展示记录详情(参见 docs/03-resources/01-overview.md 中的 Infolist 用法):

use Filament\Infolists\Infolist; use Filament\Infolists\Components\KeyValueEntry; public static function infolist(Infolist $infolist): Infolist { return $infolist ->schema([ // ... KeyValueEntry::make('meta'), ]); }

在 Eloquent 模型中保存数组数据

官方文档特别强调:如果你将键值对数据保存在 Eloquent 模型中,必须为该属性添加array类型的 Laravel 数组 / JSON 转换(cast),否则从数据库读取后拿到的是字符串而非数组,KeyValueEntry 将无法正确迭代渲染:

use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * @return array<string, string> */ protected function casts(): array { return [ 'meta' => 'array', ]; } // ... }

这样数据库中以 JSON 字符串存储的meta字段,在读取时会被自动反序列化为 PHP 关联数组,从而满足 KeyValueEntry 对一维键值数组的输入要求。

定制键列的标题:keyLabel()

默认情况下,键列(左列)的标题是翻译文件中的Key。你可以通过keyLabel()方法将其替换为更贴合业务语义的文案,例如"属性名(Property name)":

use Filament\Infolists\Components\KeyValueEntry; KeyValueEntry::make('meta') ->keyLabel('Property name')

keyLabel() 的动态计算

keyLabel()不仅支持静态字符串,还接受一个闭包(Closure)来动态计算标题。闭包中可以注入 Filament 提供的各种工具(Utility Injection),例如$record(当前记录)、$state(组件状态)、$component(组件实例)等参数:

use Filament\Infolists\Components\KeyValueEntry; KeyValueEntry::make('meta') ->keyLabel(fn ($record): string => $record->isPublished() ? 'Published property' : 'Property name')

从 KeyValueEntry.php 的源码可以看到,keyLabel()的签名是keyLabel(string | Closure | null $label),返回static(支持链式调用),底层将其存入受保护的$keyLabel属性。

定制值列的标题:valueLabel()

keyLabel()对称,valueLabel()用于定制值列(右列)的标题:

use Filament\Infolists\Components\KeyValueEntry; KeyValueEntry::make('meta') ->valueLabel('Property value')

同样地,valueLabel()也接受闭包进行动态计算,可以注入 Infolist Entry 相关的工具参数:

KeyValueEntry::make('meta') ->valueLabel(fn (): string => 'Property value')

两个方法配合使用即可完全重命名表格的两个列头,这在展示多语言界面、或需要更明确的业务术语(如"设置项 / 设置值")时非常实用。

默认标题的翻译回退机制

如果你没有调用keyLabel()/valueLabel(),组件会回退到语言包中的默认翻译。从 KeyValueEntry.php 的getKeyLabel()/getValueLabel()实现可以看到:

public function getKeyLabel(): string { return $this->evaluate($this->keyLabel) ?? __('filament-infolists::components.entries.key_value.columns.key.label'); } public function getValueLabel(): string { return $this->evaluate($this->valueLabel) ?? __('filament-infolists::components.entries.key_value.columns.value.label'); }

即:闭包计算结果(或静态值)为空时,自动使用filament-infolists::components.entries.key_value.columns.key.label...columns.value.label对应的翻译。在英文语言包 components.php 中,默认值分别为KeyValue。这意味着只要你的应用发布了 Filament 的语言资源,列标题就会自动随语言切换。

源码视角:KeyValueEntry 是如何渲染的

要深入理解 KeyValueEntry 的能力边界,需要看它的核心渲染方法。KeyValueEntry 实现了HasEmbeddedView接口,通过 toEmbeddedHtml() 直接内联输出 HTML,而不是依赖独立的 Blade 视图文件:

public function toEmbeddedHtml(): string { $state = $this->getState(); if ($state instanceof Collection) { $state = $state->all(); } $attributes = $this->getExtraAttributeBag() ->class([ 'fi-in-key-value', ]); ob_start(); ?> <table <?= $attributes->toHtml() ?>> <thead> <tr> <th scope="col"><?= e($this->getKeyLabel()) ?></th> <th scope="col"><?= e($this->getValueLabel()) ?></th> </tr> </thead> <tbody> <?php foreach (($state ?? []) as $key => $value) { ?> <tr> <th scope="row"><?= e($key) ?></th> <td><?= e($value === null || is_scalar($value) || ($value instanceof Stringable) || ($value instanceof Htmlable) ? $value : json_encode($value)) ?></td> </tr> <?php } ?> <?php if (empty($state)) { ?> <tr> <td colspan="2" class="fi-in-placeholder"> <?= e($this->getPlaceholder()) ?> </td> </tr> <?php } ?> </tbody> </table> <?php return $this->wrapEmbeddedHtml(ob_get_clean()); }

这段实现揭示了几个重要行为:

  • 支持Collection输入:如果状态是Illuminate\Support\Collection,会先通过->all()转为数组再迭代;
  • 转义输出:键和值都经过e()(HTML 实体转义)处理,防止 XSS;
  • 嵌套值的 JSON 序列化:当某个值既不是null、标量(scalar)、StringableHtmlable时(例如嵌套数组),会被json_encode成 JSON 字符串展示,而不是让渲染崩溃。这一点在测试用例renders nested array values as JSON instead of crashing(见 KeyValueEntryTest.php)中得到了验证:['theme' => ['mode' => 'dark']]会渲染出{"mode":"dark"}
  • 空状态占位:当数组为空时,渲染一行colspan="2"的占位单元格,文案来自placeholder()(默认值见下文);
  • 无障碍语义:表头使用th scope="col",每行键使用th scope="row",符合表格语义化要求。

Entry 基类提供的基础能力

KeyValueEntry 继承自 Entry.php,因此自动获得了 Entry 家族的所有通用能力:

  • 标签(Label):通过label()设置组件标签,未设置时根据字段名自动生成(如metaMeta);
  • 提示与说明hint()(右上角提示文本)、helperText()(辅助说明);
  • Tooltiptooltip()鼠标悬停提示;
  • 对齐方式alignment()控制内容对齐;
  • URL / Actionurl()action()让整个 Entry 可点击跳转或触发动作;
  • 内容插槽aboveLabel()belowLabel()beforeLabel()afterLabel()aboveContent()belowContent()beforeContent()afterContent()可在标签或内容周围注入额外组件(Action、ActionGroup 等);
  • 状态注入state()/getStateUsing()可以手动注入或计算状态,例如:
KeyValueEntry::make('meta') ->state(fn ($record) => $record->settings);

另外值得注意的是isDehydrated()返回false(Entry.php),即 Entry 组件在表单提交时不会脱水写入,它纯粹是只读展示组件。

定制空状态占位文案:placeholder() 与 emptyMessage()

当键值对数据为空数组时,表格会渲染一行占位文本。在 setUp() 中,组件默认将占位文案设置为语言包中的filament-infolists::components.entries.key_value.placeholder,英文环境下即No entries(见 components.php)。

你可以通过通用的placeholder()方法覆盖它:

use Filament\Infolists\Components\KeyValueEntry; KeyValueEntry::make('meta') ->placeholder('No metadata available')

此外,源码中保留了历史方法emptyMessage(),它目前标记为@deprecated,内部只是转发给placeholder()(KeyValueEntry.php):

/** * @deprecated Use `placeholder()` instead. */ public function emptyMessage(string | Closure | null $message): static { $this->placeholder($message); return $this; }

测试用例can use deprecated emptyMessage() as an alias for placeholder()(KeyValueEntryTest.php)也确认了该别名行为。新项目中建议统一使用placeholder()

测试验证:KeyValueEntry 的行为保障

仓库在 tests/src/Infolists/Components/KeyValueEntryTest.php 中为 KeyValueEntry 提供了完整的测试覆盖,可作为实际使用行为的权威参考:

测试场景验证点
can render传入['name' => 'John Doe', 'email' => 'john@example.com']时,页面成功渲染且能看到键和值文本
renders nested array values as JSON instead of crashing嵌套数组值被 JSON 序列化展示,不抛异常
can render with custom key and value labelskeyLabel('Setting')+valueLabel('Value')后列标题正确显示
can set and get keyLabel() / valueLabel()设置后可读取,且返回一致的字符串
getKeyLabel() / getValueLabel()未设置时返回翻译包默认值Key/Value
can set keyLabel() / valueLabel() using a Closure闭包动态计算标题生效
returns fluent $this from keyLabel()方法支持链式调用
can use deprecated emptyMessage()作为placeholder()的别名生效

测试中还通过 Livewire 测试组件(如TestComponentWithKeyValueEntry)使用Schema->state([...])->components([...])的方式注入状态并断言渲染结果,这为我们手写 Infolist 时如何组织状态与组件提供了清晰的范例。

与 KeyValue 表单字段的呼应

如果你需要在创建 / 编辑表单中编辑这类键值对数据,Filament Forms 包提供了对应的KeyValue字段(见 packages/forms/docs/16-key-value.md)。它同样以"Key / Value"两列的形式录入数据,存储结构与 KeyValueEntry 期望的一维数组格式一致。因此常见的组合方案是:编辑页用KeyValue字段录入,详情页用KeyValueEntry只读展示,两者共享同一份数组类型的数据结构,配合 Eloquent 的arraycast 即可形成完整的读写闭环。

总结

KeyValueEntry 是 Filament Infolists 中展示一维键值数据的标准方案,其要点可归纳为:

  1. 基本使用KeyValueEntry::make('meta')即可渲染键值表格,输入为关联数组或 JSON 对象,Eloquent 场景记得加arraycast;
  2. 列标题定制keyLabel()valueLabel()支持静态字符串与闭包动态计算,未设置时自动回退到语言包翻译;
  3. 健壮的渲染实现:源码内联渲染表格,自动转义输出、处理Collection、将嵌套值 JSON 序列化、并提供空状态占位;
  4. 空状态定制:通过placeholder()覆盖默认的No entriesemptyMessage()为已废弃别名;
  5. 通用 Entry 能力:继承自 Entry 基类,可自由叠加标签、提示、Tooltip、对齐、URL / Action 与内容插槽等能力。

如需深入源码,可继续阅读 KeyValueEntry.php、Entry.php 与对应的 测试文件;若想了解整个 Infolists 组件家族,可参考 packages/infolists/docs/01-overview.md。

【免费下载链接】filamentA powerful open-source UI framework for Laravel • Build and ship apps & admin panels fast with Livewire项目地址: https://gitcode.com/GitHub_Trending/fi/filament

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 10:02:35

4步本地解锁WeMod专业版功能:Wand-Enhancer开源补丁操作指南

4步本地解锁WeMod专业版功能&#xff1a;Wand-Enhancer开源补丁操作指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer WeMod&#xff08;Wand&am…

作者头像 李华