ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Voyager BREAD Relationships 完整实战指南:在 Laravel 后台可视化创建与调优表间关系

Voyager BREAD Relationships 完整实战指南:在 Laravel 后台可视化创建与调优表间关系 后端CMS【免费下载链接】voyagerVoyager - The Missing Laravel Admin项目地址https://gitcode.com/gh_mirrors/vo/voyager点击查看免费下载Voyager 作为 Laravel 的经典后台管理扩展其 BREAD 构建器Database Manager允许开发者在不手写关联代码的情况下为数据表之间建立belongsTo、belongsToMany、hasOne、hasMany四类 Eloquent 关系并自动生成下拉框、多选框等录入控件。本篇以 docs/bread/relationships.md 为主线结合 BREAD 基础教程 与仓库内控制器、模型源码系统讲解在 BREAD 中创建关系的完整流程、belongsToMany高级参数、关系结果排序、作用域过滤以及底层存储与保存机制。读完本文你将能够独立在 Voyager 后台配置可用的表关联并理解关系配置在data_rows.details中的 JSON 结构与实际运行时的调用链。Voyager BREAD 创建关系入口Voyager BREAD 关系创建模态框前置条件先创建 BREAD再添加关系Voyager 的关系功能是附着在 BREADBrowse/Read/Edit/Add/Delete之上的。因此在使用 Create Relationship 之前必须先为两张相关的表分别完成 BREAD 构建——至少为主表建立 BREAD。如果在尚未创建 BREAD 时尝试添加关系页面会给出如下图所示的提示要求你先回到 BREAD 构建流程未创建 BREAD 时的警告提示关于 BREAD 本身的构建方式Display Names、slug、图标、Model 与 Controller 命名空间、策略名以及 Browse/Read/Edit/Add/Delete 各列的勾选、表单类型与 Optional Details 校验规则请参阅 BREAD 介绍。关系功能本质上是为 BREAD 的data_rows表追加一条type relationship的特殊行因此其生命周期完全依赖 BREAD 的存在。创建关系四个关键配置项点击 Create Relationship 按钮后会弹出关系创建模态框上图所示。需要依次配置以下内容关系类型Relationship Type在belongsTo、belongsToMany、hasOne、hasMany四者中选择其一。Voyager 官方文档明确支持这四种类型对应 Laravel Eloquent 同名方法。目标表Table与所属命名空间Namespace选择被关联的表并指定该表对应的 Model 类的完整命名空间例如App\Models\Role。命名空间对应的 Model 必须真实存在否则保存会被拒绝。关联行Relationship Column / Key指定两张表之间通过哪个字段建立关联对于belongsTo选择外键所在的列对于hasOne/hasMany选择对方表中对应的关联列与主键对于belongsToMany还需指定中间表pivot table。展示列Display Column / Label指定下拉框或多选框中每条选项显示哪个字段的值例如用name而非id。从源码看Voyager 将上述选择持久化为一条type relationship的 DataRow其details为一段 JSON。见 VoyagerBreadController.php 中addRelationship()的构造逻辑$relationshipDetails [ model $request-relationship_model, // 目标 Model 命名空间 table $request-relationship_table, // 目标表 type $request-relationship_type, // belongsTo / belongsToMany / hasOne / hasMany column $relationship_column, // 关联列 key $request-relationship_key, // 取值键如 id label $request-relationship_label, // 下拉框展示列 pivot_table $request-relationship_pivot, // 中间表仅 belongsToMany pivot ($request-relationship_type belongsToMany) ? 1 : 0, taggable $request-relationship_taggable, ];其中hasOne/hasMany的column取relationship_column对方表的外键列其余类型取relationship_column_belongs_to。这段 JSON 最终写入data_rows表的details字段DataRow.php 中的setDetailsAttribute()/getDetailsAttribute()负责在 JSON 与对象之间互转因此后续配置读取时$row-details-type、$row-details-model均可直接以对象属性方式访问。belongsToMany 高级选项自定义中间表键名对于belongsToMany关系Eloquent 默认会按惯例推断中间表的外键名主表模型名 _id、关联模型名 _id。当你的中间表字段命名不符合惯例例如是user_id/role_id而非role_user表的默认推断时需要在关系保存后于该字段的 Optional Details 中追加以下 JSON{ foreign_pivot_key: user_id, related_pivot_key: role_id, parent_key: id }三个参数的语义如下参数含义对应 EloquentbelongsToMany()形参foreign_pivot_key中间表中指向当前模型父表的外键列名第 3 个参数related_pivot_key中间表中指向关联模型的外键列名第 4 个参数parent_key当前模型用于关联的主键列名第 5 个参数它们的实际使用点在数据保存路径上当 BREAD 编辑/新增提交时Controller.php 会收集所有belongsToMany关系行读取上述键名后调用belongsToMany(...)-sync(...)完成中间表同步if ($row-type relationship $row-details-type belongsToMany) { $multi_select[] [ model $row-details-model, content $content, table $row-details-pivot_table, foreignPivotKey $row-details-foreign_pivot_key ?? null, relatedPivotKey $row-details-related_pivot_key ?? null, parentKey $row-details-parent_key ?? null, relatedKey $row-details-key, ]; } // ... $data-belongsToMany( $sync_data[model], $sync_data[table], $sync_data[foreignPivotKey], $sync_data[relatedPivotKey], $sync_data[parentKey], $sync_data[relatedKey] )-sync($sync_data[content]);由此可知未配置这三个键时 Voyager 会向 Eloquent 传null即完全依赖 Eloquent 的默认推断只有中间表命名特殊时才需要显式指定。仓库内置的Role/User/Permission模型可作为标准belongsToMany用法的参照例如 Role.php 中的user_roles关联与 VoyagerUser.php。另外如果你需要在下拉多选中同时编辑中间表上的附加字段pivot 上的业务列可以在关系的 Optional Details 中配置editablePivotFieldsSelectMultiple.php 会按pivot_字段名的请求参数重组数据后再交给sync()。这是对官方文档belongsToMany章节的补充能力可通过阅读该 ContentType 源码确认其行为。排序关系结果sort 配置对象默认情况下关系下拉框/多选框按数据库返回顺序展示。若需要固定排序可在关系字段的 Optional Details 中加入sort对象// 按 my_field 升序 { sort: { field: my_field, direction: asc } }// 按 my_field 降序 { sort: { field: my_field, direction: desc } }direction仅接受asc或desc其余取值会被当作升序处理。底层实现位于 VoyagerBaseController.php 的relation()端点中先通过$options-sort-field判断是否启用排序排序方向非空时在查询构建器上调用orderBy($options-sort-field, $options-sort-direction)对取回的结果集再执行一次sortByDesc()/sortBy()用于补偿belongsToMany等场景下集合层面的排序。从源码还可以看到排序配置还支持一个可选的flag属性对应 PHP 的SORT_REGULAR、SORT_NUMERIC等排序标志默认值为SORT_REGULAR。如果你需要按数字而非字符串顺序排序可以在此基础上扩展{ sort: { field: order, direction: asc, flag: SORT_NUMERIC } }作用域过滤scope 配置对象当目标表数据量大、需要只展示符合条件的选项时可以为关系配置局部作用域local scope。例如只显示active 1的记录先在目标 Model 中定义作用域public function scopeActive($query) { return $query-where(active, 1); }然后在关系字段的 Optional Details 中加入scope{ scope: active, }scope的值即作用域方法名去掉scope前缀后的部分方法scopeActive()→ 值active方法scopeSomeUsers()→ 值someUsers注意大小写Voyager 在运行时调用scope.ucfirst($options-scope)拼出完整方法名因此active会被解析为scopeActive。实际判断逻辑在 VoyagerBaseController.php// Apply local scope if it is defined in the relationship-options if (isset($options-scope) $options-scope ! method_exists($model, scope.ucfirst($options-scope))) { $model $model-{$options-scope}(); }method_exists()的存在意味着作用域方法未定义时该配置会被静默忽略不会报错这为多环境/多模型复用提供了容错。该过滤同时作用于下拉选项的数据源配合relation()端点中的LIKE搜索对label字段做%关键词%模糊匹配与每页 50 条的LengthAwarePaginator风格分页通过pagination.more字段驱动前端滚动加载即可获得可搜索、可筛选的关联选择器。belongsTo 的存储与显示要点官方文档在关系章节末尾特别强调了一条容易踩坑的规则在BelongsTo关系中外键字段foreign key field决定该值能否在新增add或编辑edit时被保存并承担其余一切校验规则而浏览browse、编辑edit中的可见性则由 relationship 字段本身决定。结合源码可以更清楚地理解这句话的落地方式。在 Controller.php 的保存流程中// Value is saved from $row-details-column row if ($row-type relationship $row-details-type belongsTo) { continue; } // ... if ($row-type relationship $row-details-type ! belongsToMany) { $row-field $row-details-column; }即belongsTo关系行本身不直接写入数据真正的值写入的是details-column指向的外键字段同时 BreadRelationshipParser.php 中的removeRelationshipField()会在渲染时移除与外键字段重复的裸列避免表单中出现两个同一字段。这也解释了文档提示的含义——外键列例如author_id的required、validation等设置决定了写入行为而关系列例如author负责下拉框的展示与选中回显。小结关系配置的完整数据流梳理整条链路Voyager 关系功能的工作流可归纳为配置期BREAD 构建器通过addRelationship()将关系元数据类型、模型、表、键、标签、中间表、taggable 等写入data_rows.detailsJSON增强期可在 details 中追加foreign_pivot_key/related_pivot_key/parent_key中间表键名、sort排序、scope局部作用域过滤、editablePivotFields中间表附加字段等高级配置渲染期前端下拉/多选通过relation()端点按label搜索、按sort排序、按scope过滤、按 50 条/页滚动加载返回{ results, pagination }保存期belongsTo写入details-column对应外键列belongsToMany通过belongsToMany(...)-sync(...)同步中间表。掌握以上四个环节与对应源码位置VoyagerBreadController.php、Controller.php、VoyagerBaseController.php、DataRow.php即可在 Voyager 后台从容应对从简单外键到复杂多对多关联的各类业务需求。赞分享后端CMS【免费下载链接】voyagerVoyager - The Missing Laravel Admin项目地址https://gitcode.com/gh_mirrors/vo/voyager点击查看免费下载相关推荐ComfyUI-WanVideoWrapperAI视频生成的终极解决方案轻松创作专业级动态内容ComfyUI WanVideoWrapperAI视频生成的终极解决方案轻松创作专业级动态内容 想要将静态图片变成生动的视频吗渴望用文字描述就能生成精彩短后端CMS30分钟上手Voyager零基础构建Laravel管理后台的完整指南30分钟上手Voyager零基础构建Laravel管理后台的完整指南 Voyager是Laravel框架的一款强大管理后台解决方案它提供了直观的界面和丰富的后端CMSVoyager - Laravel缺失的管理后台完全指南Voyager Laravel缺失的管理后台完全指南 Voyager是一个专为Laravel框架设计的现代化管理后台系统被誉为Laravel缺失的管理后台后端CMS上一篇终极指南如何使用C-Eval评估大语言模型的中文能力下一篇PolyglotPDF突破性AI多语言PDF翻译工具6倍速智能翻译完美保留原格式创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表