area17/twill-transformers

Twill应用的转换器

v1.2.1 2023-04-13 13:28 UTC

README

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

此包允许您为Twill应用创建转换器以生成视图数据。它包含一个基类转换器和一系列特性,允许您不仅转换模型数据,还能生成所有块,从Twill的块编辑器和预览数据。

原因

此包的主要类是从我们为一个客户工作的项目中提取出来的,我们决定使用Storybook和Twig模板来构建前端。想法是让后端开发者免于编写前端代码。为此,整个数据生成都是自动化的,从控制器view()调用开始。

安装

通过Composer

composer require area17/twill-transformers

发布配置文件

php artisan vendor:publish --provider="A17\TwillTransformers\ServiceProvider"

用法

对于使用相同方法(Storybook + Twig)的用户,要使所有这些都发生,您必须执行以下操作

创建您的基类转换器

扩展Transformer类并创建您的基本页面结构。转换器生成的所有JSON都将具有这种结构。

namespace App\Transformers;

use A17\TwillTransformers\Transformer as TwillTransformer;

abstract class Transformer extends TwillTransformer
{
    /**
     * @return array|null
     */
    public function transform()
    {
        return $this->sanitize([
            'template_name' => $this->makeTemplateName(),

            'header' => $this->transformHeader($this->data),

            $this->makePageKey() => $this->transformData($this->data),

            'seo' => $this->transformSeo($this->data),

            'footer' => $this->transformFooter($this->data),
        ]);
    }
}

使用必需的特性

在您的基控制器上添加并使用此特性

use A17\TwillTransformers\ControllerTrait;

在您的基仓库上添加并使用此特性

use A17\TwillTransformers\RepositoryTrait;

创建您的第一个转换器

请注意,要转换的数据在转换器对象内部是自包含的。因此,$this包含它负责转换的所有内容,并且由于它通常是Laravel模型的后代,它还可以访问我们通常使用模型所做的所有内容,包括访问器、修改器、关系、展示者等。

namespace App\Transformers;

class LandingPage extends Transformer
{
    public function transform()
    {
        return [
            'hero' => [
                'title' => $this->title,

                'text' => $this->text,

                'image' => $this->transformMedia(),
            ],

            'blocks' => $this->transformBlocks(),

            'related' => $this->transformRelatedArticles(),
        ];
    }
}

创建块转换器

请注意,这仅在您的块与前端数据需求不兼容时才是必需的。为了重复使用Twill块,后端和前端必须就所有块的架构和命名达成一致。但是,如果您仍然需要在块上进行数据转换,您可以创建块如下所示

namespace App\Transformers\Block;

use App\Transformers\Block;

class ArtistPortrait extends Block
{
    public function transform()
    {
        return [
            'component' => 'portrait',

            'data' => [
                'name' => $this->name,

                'text' => $this->main_info,

                'button' => [
                    'more_label' => ___('Lire plus'),
                    'less_label' => ___('Lire moins'),
                ],

                'extra_text' => $this->additional_info,

                'image' => $this->transformMedia(),
            ],
        ];
    }
}

将块作为组件重复使用

如果您有一个块转换器,并且需要将其重复用于在您的App转换器或甚至其他块转换器上生成数据,您基本上可以按这种方式调用它们

public function transformArtistPortraits($portraits)
{
    return collect($portraits)->map(function ($portrait) {
        return $this->transformBlockArtistPortrait($portrait);
    });
}

如果transform方法调用以Block开头,如transformBlockArtistPortrait(),它基本上会尝试实例化要使用的命名块转换器类。

这是调用上述块的代码

namespace App\Transformers\Block;

use App\Transformers\Block;

class ArtistPortrait extends Block
{
    public function transform()
    {
        return [
            'component' => 'portrait',

            'data' => [
                'name' => $this->name,

                'text' => $this->main_info,

                'button' => [
                    'more_label' => ___('Lire plus'),
                    'less_label' => ___('Lire moins'),
                ],

                'extra_text' => $this->additional_info,

                'image' => $this->transformMedia(),
            ],
        ];
    }
}

请注意,传递给您的转换器(块或应用转换器)的数据(模型、数组、对象)可以在块的内部使用$this访问

因此,当我们这样调用转换器时

$this->transformBlockArtistPortrait($portrait);

在转换器内部,我们可以通过这样做来渲染图像

$this->transformMedia()

或以这种方式获取肖像人的姓名

$this->name

渲染前端

您只需执行以下操作即可将JSON数据发送到您的客户端

@extends('front.layouts.app')

@section('contents')
    @include("templates.{$template_name}")
@endsection

如果您需要查看生成的数据,只需将?output=json添加到URL中。

在Twill上渲染预览

预览是包含在内的,它们基本上是这种新方法的副作用,因此您只需在twill.php文件上配置您的预览路径即可。

'views_path' => 'admin._site.front',

创建此Blade模板以渲染所有内容的预览

@extends('front.layouts.app')

@php
    $data = _transform($item);
@endphp

@section('contents')
    @include("templates.{$data['template_name']}", $data)
@endsection

Twill的块编辑器

首先,您需要为每个要渲染的块创建一个块组件,即使它只是扩展了您的应用程序中的基本组件。

然后您只需要创建这个视图,该视图将处理并渲染编辑器中的所有块

@php
    $transformed = _transform($block);

    $type = Str::kebab(Str::camel($transformed['type']));
@endphp

@include("components.block.{$type}.block-{$type}", $transformed)

Blade 变换器

您可以直接在 Blade 模板内定义变换器

@extends('layouts.app')

@transformer(\App\Transformers\Post)

...

在您的基变换器上添加一个 blade() 静态方法来处理数据变换

public static function blade($transformer, $data): array
{
    if (app()->bound(BladeTransformer::class)) {
        return app(BladeTransformer::class)->transform($transformer, $data);
    }

    return [];
}

然后在从 Blade 调用的每个变换器上,您可以定义一个 transformStorybookData() 方法,以便在没有可变换数据的情况下渲染模拟数据。例如,当通过 Blast 渲染 Storybook 故事时,可以使用此方法。

<?php

namespace App\Transformers;

class Posts extends Transformer
{
    public function transform(): array
    {
        return [
            'title' => $this->title,
        ];
    }

    public function transformStorybookData(): array
    {
        return [
            'title' => 'Fake Title to Be Displayed Inside Storybook Only',
        ];
    }
}

如果您使用 Blast 构建 Storybook 故事,则您的故事应扩展应用程序布局

@extends('layouts.app')

@transformer(\App\Transformers\Post)

@storybook([
    'layout' => 'fullscreen',
    'status' => 'dev',
    'args' => []
])

@section('content')
    <div class="container">
        ...
    </div>
@endsection

并且布局应检查是否在 Blast 中运行,并且仅渲染故事组件

@if (runningInBlast(get_defined_vars()))
    @yield('content')
@else
    <!DOCTYPE html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}" data-active-nav="@yield('active_nav')">
        <head>
            ...
        </head>
        
        <body>
            ...
        </body>
    </html>
@endif

变更日志

请参阅 CHANGELOG 以获取有关最近变更的更多信息。

测试

$ composer test

贡献

请参阅 CONTRIBUTINGCODE_OF_CONDUCT 以获取详细信息。

安全性

如果您发现任何安全相关的问题,请发送电子邮件至 antonio@area17.com 而不是使用问题跟踪器。

鸣谢

许可证

MIT 许可证 (MIT)。请参阅 许可证文件 以获取更多信息。