msouto / nova-flexible-content

Laravel Nova 的灵活内容与重复字段。

0.2.11 2021-09-03 08:21 UTC

README

一个简单而完整的 Laravel Nova 灵活字段,非常适合重复和灵活的字段组。

Laravel Nova Flexible Content in action

快速开始

以下是快速入门的简要指南。请参阅完整文档:https://whitecube.github.io/nova-flexible-content

安装

composer require whitecube/nova-flexible-content

用法

灵活字段允许轻松管理可重复和可排序的字段组。与 Laravel Nova 现有的少数解决方案相比,此解决方案在这些组内允许使用的字段没有限制。这意味着您可以使用所有 Laravel Nova 字段类型,也可以使用任何社区制作的字段。

添加布局

布局代表可以在灵活字段内部重复的一组字段。您可以添加任意数量的布局。如果只定义了一个布局,字段将像简单的重复字段一样工作。通过添加更多布局,您可以获得灵活内容。这两个概念类似于 Wordpress ACF 插件中的同类

您可以使用以下方法在灵活字段中添加布局

 addLayout(string $title, string $name, array $fields)

$name 参数用于在字段的值中存储所选布局。请谨慎选择,您可能会用它来识别应用程序中的布局。

use Whitecube\NovaFlexibleContent\Flexible;

/**
 * Get the fields displayed by the resource.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
public function fields(Request $request)
{
    return [
        // ...

        Flexible::make('Content')
            ->addLayout('Simple content section', 'wysiwyg', [
                Text::make('Title'),
                Markdown::make('Content')
            ])
            ->addLayout('Video section', 'video', [
                Text::make('Title'),
                Image::make('Video Thumbnail', 'thumbnail'),
                Text::make('Video ID (YouTube)', 'video'),
                Text::make('Video Caption', 'caption')
            ])
    ];
}

Example of Flexible layouts

自定义按钮标签

您可以通过以下方式更改默认的 "添加布局" 按钮的文本

Flexible::make('Content')
    ->button('Add something amazing!');

Add something amazing

在视图中使用灵活值

如果您正在使用 Laravel 6 及以下版本,或者不想使用铸造,请使用具有 HasFlexible 特性的模型访问器 使用访问器

Laravel 7 带来了自定义铸造,灵活内容字段是它们的完美用例。字段将值存储为单个 JSON 字符串,这意味着在可以在应用程序中使用之前,需要解析此字符串。这可以通过使用此包中的 FlexibleCast 类轻松完成

namespace App;

use Illuminate\Database\Eloquent\Model;
use Whitecube\NovaFlexibleContent\Value\FlexibleCast;

class MyModel extends Model
{
    protected $casts = [
        'flexible-content' => FlexibleCast::class
    ];
}

默认情况下,FlexibleCast 类将收集基本的 Layout 实例。如果您想将布局映射到 自定义布局实例,这也是可能的。首先,通过运行 php artisan flexible:cast MyFlexibleCast 创建一个自定义灵活铸造。这将在 App\Casts 目录中创建文件。

然后轻松地将您的自定义布局类映射到适当的键

namespace App\Casts;

class MyFlexibleCast extends FlexibleCast
{
    protected $layouts = [
        'wysiwyg' => \App\Nova\Flexible\Layouts\WysiwygLayout::class,
        'video' => \App\Nova\Flexible\Layouts\VideoLayout::class,
    ]
}

如果您需要更多控制,您可以覆盖 getLayoutMappings 方法

布局集合

FlexibleCast 铸造和 HasFlexible 特性返回的集合扩展了原始的 Illuminate\Support\Collection。这些自定义布局集合公开了一个 find(string $name) 方法,该方法返回第一个具有给定布局 $name 的布局。

布局实例

布局是一种 假模型。它们使用 Laravel 的 HasAttributes 特性,这意味着您可以定义布局属性的访问器和修改器。此外,还可以使用以下方法访问布局的属性

name()

返回布局的名称。

title()

返回布局的标题(在 Nova 中显示)。

key()

返回布局的唯一键(布局的唯一标识符)。

进一步了解

当使用灵活内容字段时,你很快就会遇到一些用例,上述基本功能不足以应对。这就是我们以可扩展的方式开发此包的原因,使得为字段及其输出轻松添加自定义行为和/或功能成为可能。

自定义布局类

有时,addLayout 定义可能相当长,或者你可能希望它们与其他 Flexible 字段共享。解决这个问题的方法是将你的布局提取到它自己的类中。有关更多信息,请参阅文档

预定义预设类

除了可重用的布局类,你还可以为你的灵活字段创建 Preset 类。这些类允许你在任何需要的地方重用整个灵活字段。它们还使你的灵活字段更易于动态化,例如,如果你想要有条件地添加布局。最重要的是,如果你的灵活字段有很多 addLayout 定义,它们还有助于清理你的 Nova 资源类。有关更多信息,请参阅文档

自定义解析器类

默认情况下,字段利用模型表的 JSON 列。在某些情况下,你可能真的想使用此字段,但出于某种原因,JSON 属性并不是最佳选择。例如,你可能想将值存储在另一个表中(这意味着你将使用灵活内容字段而不是传统的 BelongsToMany 或 HasMany 字段)。别担心,我们为你考虑到了这一点!

通过创建自己的解析器类来告诉字段如何存储和检索其内容,这个类基本上只包含两个简单的方法:getset。有关更多信息,请参阅文档

与 nova-page 一起使用

你可能听说过我们的另一个包,nova-page,这是一个 Nova 工具,允许编辑静态页面,例如 “关于” 页面(或类似页面),而无需为它单独声明模型。通常情况下,灵活内容字段会非常有用。别担心,这两个包可以很好地协同工作!首先创建一个 nova 页面模板 并将一个 灵活内容 添加到模板的字段中。

如文档中所述,你可以在 blade 视图中使用 {{ Page::get('attribute') }}访问 nova-page 的静态内容。当这样请求灵活内容时,它返回一个描述灵活内容的原始 JSON 字符串,这当然不是非常有用。相反,你可以在你的页面模板上简单地实现 Whitecube\NovaFlexibleContent\Concerns\HasFlexible 特性,这将暴露 Page::flexible('attribute') 门面方法,并负责灵活内容的转换。

namespace App\Nova\Templates;

// ...
use App\Nova\Templates\Concerns\HasFlexible;

class Home extends Template
{
    use HasFlexible;

    // ...
}

💖 赞助

如果你在生产应用程序中依赖此包,请考虑赞助我们!这是帮助我们继续做我们热爱的事情的最佳方式:制作优秀的开源软件。

贡献

欢迎提出修改建议,要求新增功能或自行修复bug。我们相信还有很多可以改进的地方,我们非常乐意合并有价值的pull request。

谢谢!

用❤️为开源制作

在Whitecube,我们每天工作中使用大量的开源软件。所以当我们有机会回馈时,我们非常兴奋!

希望您会喜欢我们的小贡献,如果您在项目中发现它有用,我们非常愿意听到您的反馈。关注我们的Twitter获取更多更新!