您可以自行创建内容字段,方法是定义一个字段定义文件,然后将其注册到您的插件注册文件中。
内容字段定义类位于插件的 contentfields 目录中。内部目录名与小写形式的小部件类名匹配。内容字段可以提供资产和局部文件。一个示例目录结构如下所示。
├── contentfields
| ├── mycontentfield
| | ├── assets
| | └── partials
| | └── _column_content.php ← 分部文件
| └── MyContentField.php ← 字段类
该 create:contentfield 命令生成一个内容字段类。第一个参数指定作者和插件名称。第二个参数指定内容字段类名称。
php artisan create:contentfield Acme.Blog MyContentField内容字段类必须扩展 Backend\Classes\FormWidgetBase 类.
注册的内容字段可用于 Tailor 表单字段 和蓝图. 该类定义了字段应如何与系统其余部分交互. 例如,plugins/acme/blog/contentfields/MyContentField.php 包含以下内容.
namespace Acme\Blog\ContentFields;
use Tailor\Classes\ContentFieldBase;
use October\Contracts\Element\FormElement;
use October\Contracts\Element\ListElement;
use October\Contracts\Element\FilterElement;
class MyContentField extends ContentFieldBase
{
public function defineConfig(array $config) {}
public function defineFormField(FormElement $form, $context = null) {}
public function defineListColumn(ListElement $list, $context = null) {}
public function defineFilterScope(FilterElement $filter, $context = null) {}
public function extendModelObject($model) {}
public function extendDatabaseTable($table) {}
}插件应该通过覆盖 插件注册文件 中的 registerContentFields 方法来注册内容字段。该方法返回一个数组,其键是控件类,值是控件短代码。示例:
public function registerContentFields()
{
return [
\Acme\Blog\ContentFields\MyContentField::class => 'mycontentfield'
];
}短代码用于在蓝图模板中引用字段,它应该是一个唯一值,以避免与其他表单字段发生冲突。
假设我们想要包含一个名为 secondaryTitle 的字段配置项,它首先在类上被定义为一个属性,然后使用 defineConfig 覆盖来填充。
class MyContentField extends ContentFieldBase
{
public $secondaryTitle;
public function defineConfig(array $config)
{
if (isset($config['secondaryTitle'])) {
$this->secondaryTitle = $config['secondaryTitle'];
}
}
}这便变得可用:
my_field:
type: mycontentfield
secondaryTitle: Custom value goes here内容字段可以定义它在后端面板中作为表单字段、列表列和筛选范围的显示方式。 在每种情况下,生成的对象都是一个流畅的配置对象,它支持方法链或通过 useConfig 方法传递的数组。 请参阅 定义内容字段文章 获取更多信息。
defineFormField方法定义了内容字段在表单中应如何显示。每个字段都由接受字段名称和要向用户显示的标签的addFormField方法初始化。
public function defineFormField(FormElement $form, $context = null)
{
$form->addFormField($this->fieldName, $this->label)->useConfig($this->config);
}defineListColumn 方法定义了内容字段在列表中应如何显示。每个列都由 defineListColumn 方法初始化,该方法接受要显示给用户的字段名称和标签。
public function defineListColumn(ListElement $list, $context = null)
{
$list->defineColumn($this->fieldName, $this->label)->displayAs('switch');
}defineFilterScope 方法定义了内容字段在筛选器中应如何显示。每个作用域都由 defineScope 方法启动,该方法接收要显示给用户的字段名称和标签。
public function defineFilterScope(FilterElement $filter, $context = null)
{
$filter->defineScope($this->fieldName, $this->label)->displayAs('switch');
}extendModelObject 方法允许内容字段扩展记录模型,例如 Tailor\Models\EntryRecord 模型类。一个例子可能是使用 addJsonable 方法使该字段可 JSON 化。
public function extendModelObject($model)
{
$model->addJsonable($this->fieldName);
}另一种方法可能是指定一个 belongsTo 关系。
public function extendModelObject($model)
{
$model->belongsTo[$this->fieldName] = MyOtherModel::class;
}extendDatabaseTable 用于指定针对此字段需要哪些数据库列。它使用简化版的标准迁移结构。
public function extendDatabaseTable($table)
{
$table->mediumText($this->fieldName)->nullable();
}下面是为 October Test 插件创建内容字段的完整示例。它添加了一个 mycontentfield 类型,该类型可用于所有蓝图,如下例所示。
fields:
mycontentfield:
label: Custom Content Field
type: mycontentfield
firstColor: red
secondColor: blue该字段注册在文件 plugins/october/test/Plugin.php 中,使用的是 registerContentFields 方法。
public function registerContentFields()
{
return [
\October\Test\ContentFields\MyContentField::class => 'mycontentfield'
];
}该字段类以 PHP 类的形式创建在文件 plugins/october/test/contentfields/MyContentField.php 中。它将自身注册为一个 局部字段类型,为简单起见,不包含列表列或过滤范围。对 addJsonable 方法的调用确保字段名是一个 可 JSON 序列化属性,因此它可以存储为一个数组。数据库列存储为 mediumText 数据库 schema 类型,并带有 nullable 修饰符,允许空值。
namespace October\Test\ContentFields;
use Tailor\Classes\ContentFieldBase;
use October\Contracts\Element\FormElement;
class MyContentField extends ContentFieldBase
{
public function defineFormField(FormElement $form, $context = null)
{
$form->addFormField($this->fieldName, $this->label)
->useConfig($this->config)
->displayAs('partial')
->path('$/october/test/contentfields/mycontentfield/partials/_field.php');
}
public function extendModelObject($model)
{
$model->addJsonable($this->fieldName);
}
public function extendDatabaseTable($table)
{
$table->mediumText($this->fieldName)->nullable();
}
}文件 plugins/october/test/contentfields/mycontentfield/partials/_field.php 包含用于渲染表单字段的部分内容。这些值被检索并保存为一个数组 [first_value => 'foo', second_value => 'bar'].
<div class="row">
<div class="col">
<input
type="text"
name="<?= $field->getName() ?>[first_value]"
value="<?= e($field->value['first_value'] ?? '') ?>"
class="form-control"
style="color:<?= $field->firstColor ?: 'red' ?>"
/>
</div>
<div class="col">
<input
type="text"
name="<?= $field->getName() ?>[second_value]"
value="<?= e($field->value['second_value'] ?? '') ?>"
class="form-control"
style="color:<?= $field->secondColor ?: 'blue' ?>"
/>
</div>
</div>一个常见的问题是关于表单部件和内容字段之间的区别,以及在何种情况下哪种更好? 表单部件 是由 Backend\Widgets\Form 部件专属使用的表单字段,以及原生的 表单字段类型 (文本, 数字, 下拉列表, 局部, 等等)
内容字段是专供 Tailor 使用的表单字段的超集,并且更进一步,还包括该字段如何:
如果一个表单小部件在定义时没有指定内容字段,它默认情况下仍然可以在 Tailor 中使用,并且会解析为 Tailor\ContentFields\FallbackField 内容字段类型,这种类型是基础的,并且在数据库中注册为 TEXT 列类型。
对于健壮的解决方案,最好同时定义一个表单部件和一个内容字段。这使得该字段可以在插件中使用,并且内容可以用于Tailor 蓝图。下面链接到一个货币字段的示例,该字段可以在任何地方使用。
你可能会注意到,在内容字段内部,YAML 定义是在 PHP 中定义的。YAML 语法到 PHP 语法相当简单,其中 PHP 方法名就是 YAML 属性名,值作为第一个参数传递——默认值为 true。唯一的主要区别在于,type 属性由 displayAs 方法定义。
任何方法名都可以被调用,并可在PHP对象上进行链式调用。请参阅下表,了解一些YAML到PHP的转换示例。
| YAML | PHP |
|---|---|
autoFocus: true | ->autoFocus() |
label: my field | ->label('my field') |
type: partial | ->displayAs('partial') |
您还可以使用
->useConfig([...])将所有所需的 YAML 配置作为数组传递。