logo

重复器字段

测试版

此字段目前处于测试版阶段。API 虽然稳定,但在测试版期间可能会发生更改。

概述

Repeater 字段允许你创建和编辑可重复的结构化数据,并将该数据存储在 JSON 列或 HasMany 关系中

php
<?php

namespace App\Nova;

use App\Nova\Repeater\LineItem;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Repeater;
use Laravel\Nova\Http\Requests\NovaRequest;
 
class Invoice extends Resource
{
	/**  
	 * Get the fields displayed by the resource. 
	 * 
	 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request  
	 * @return array  
	 */
	public function fields(NovaRequest $request)
	{
		return [
			ID::make(),
			Repeater::make('Line Items')
				->repeatables([
					LineItem::make(),
				]),
		];
	}
}

在定义 Repeater 字段后,你的资源将拥有一个优雅的界面,用于在字段中添加和编辑可重复的项目

Repeater Field

可重复项

Repeatable 对象表示 Repeater 字段的可重复数据。它定义了可重复项使用的字段集。当 Repeater 使用 HasMany 预设时,它还可选地定义一个 Eloquent Model 类。

Repeater 字段不限于单一类型可重复项。它还支持多个“可重复”类型,这些类型可能包含它们自己独特的字段集和模型。这些可重复项可用于创建编辑灵活内容区域的界面,类似于内容管理系统提供的界面。

生成可重复项

要生成新的 Repeatable,调用 nova:repeatable Artisan 命令

sh
php artisan nova:repeatable LineItem

在调用上述命令后,Nova 会在 app/Nova/Repeater/LineItem.php 中生成一个新文件。此文件包含一个 fields 方法,你可以在其中列出任何受支持的 Nova 字段。例如,下面我们将定义一个 Repeatable,表示发票的项目

php
<?php

namespace App\Nova\Repeater;

use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Fields\Currency;
use Laravel\Nova\Fields\Number;
use Laravel\Nova\Fields\Repeater\Repeatable;
use Laravel\Nova\Fields\Textarea;

class LineItem extends Repeatable
{
	/**
	 * Get the fields displayed by the repeatable.
	 *
	 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
	 * @return array
	 */
	public function fields(NovaRequest $request)
	{
		return [
			Number::make('Quantity')->rules('required', 'numeric'),
			Textarea::make('Description')->rules('required', 'max:255'),
			Currency::make('Price')->rules('required', 'numeric'),
		];
	}
}

确认可重复项删除

你可以指示 Nova 在删除可重复项之前显示确认模态框,方法是在定义可重复项时调用 confirmRemoval 方法

php
Repeater::make('Attachments')->repeatables([
	\App\Nova\Repeater\File::make()->confirmRemoval(),
	\App\Nova\Repeater\Note::make(),
	\App\Nova\Repeater\Video::make()->confirmRemoval(),
]),

重复器预设

Repeater 字段开箱即用地包含两个存储“预设”:JsonHasMany。每个预设都定义了如何从你的数据库存储和检索可重复数据。

例如,Invoice 资源可以使用 Repeater 字段编辑发票的项目。使用 Laravel\Nova\Fields\Repeater\JSON 预设,这些项目将存储在 line_items JSON 列中。但是,使用 HasMany 预设时,项目将存储在单独的“line_items”数据库表中,其中字段对应于每个数据库列。

JSON 预设

JSON 预设将可重复项存储在数据库的 JSON 列中。例如,发票的项目可以存储在 line_items 列中。当使用 JSON 预设的 Repeater 字段的资源被保存时,可重复项将被序列化并保存到该列中。

要使用 JSON 预设,只需在 Repeater 字段定义中调用 asJson 方法即可

php
Repeater::make('Line Items', 'line_items')
	->repeatables([
		\App\Nova\Repeater\LineItem::make(),
	])
	->asJson()

在使用此预设之前,您应该确保资源的可重复项列的底层 Eloquent 属性配置为在 Eloquent 模型类中转换为 array(或等效项)

php
protected $casts = [
    'line_items' => 'array'
];

HasMany 预设

HasMany 预设使用 HasMany 关系通过 Eloquent 存储可重复项。例如,与其以 JSON 格式存储发票的项目,不如将数据保存在单独的 line_items 数据库表中,其中包含映射到可重复项中每个字段的专用列。Repeater 字段将在编辑资源时自动管理这些关系。

要使用 HasMany 预设,只需在 Repeater 字段定义中调用 asHasMany 方法即可

php
Repeater::make('Line Items', 'lineItems')
	->repeatables([
		\App\Nova\Repeater\LineItem::make(),
	])
	->asHasMany()

HasMany 预设要求每个可重复项通过在 Repeatable 上设置 model 属性来指定它表示的底层模型。例如,LineItem 可重复项需要指定它表示的底层 \App\Models\LineItem 模型

php
class LineItem extends Repeatable
{
	/**  
	 * The underlying model the repeatable represents. 
	 * 
	 * @var class-string
	 */
	public static $model = \App\Models\LineItem::class;
}

使用唯一字段更新可重复项

默认情况下,在使用 HasMany 预设配置可重复项时,Nova 将删除所有相关项并在每次保存资源时重新创建它们。要指示 Nova “更新”可重复项数据,您应该确保相关模型上有一个唯一标识符列。通常,这将是一个自动递增列或 UUID。然后,您可以使用 uniqueField 方法指定哪个列包含数据库表的唯一键

php
/**  
 * Get the fields displayed by the resource. 
 * 
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request  
 * @return array  
 */
public function fields(NovaRequest $request)
{
	return [
		ID::make(),
		
		Repeater::make('Line Items')
			->asHasMany()
			->uniqueField('uuid')
			->repeatables([
				\App\Nova\Repeater\LineItem::make()
			])
	];
}

此外,Repeatablefields 方法必须包含与 uniqueField 匹配的字段

php
use Laravel\Nova\Fields\ID;

/**  
 * Get the fields displayed by the repeatable. 
 * 
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request  
 * @return array  
 */
public function fields()
{
	return [
		ID::hidden('uuid'), // The unique ID field

		// Other fields...
	];
}

在此示例中,我们使用了 ID::hidden 方法,该方法可防止 Nova 向用户显示 ID 字段,但在保存或更新资源时仍会将其值传递给 Nova。

Repeater 字段功能

虽然 Repeatable 可以使用与典型 Nova 资源和操作相同的大部分字段,但它们的行为并不相同。例如,不支持 creationRulesupdateRules 等方法,因为创建和编辑模式的验证规则相同。此外,Repeatable 中的字段不支持相关字段 (dependsOn) 功能。

支持的字段

Repeater 字段允许使用 Nova 支持的每个字段,但以下字段除外

  • HasOne
  • MorphOne
  • HasMany
  • MorphMany
  • BelongsTo
  • MorphTo
  • BelongsToMany
  • MorphToMany

部分支持的字段

以下字段部分支持

  • 文件字段
  • Vapor 文件字段
  • Markdown 字段
  • Trix 字段

MarkdownTrix 字段支持用于文本,但目前不支持附件。