nimbly/重构

为您的API响应提供简单的数据转换器

2.1 2021-01-14 19:53 UTC

This package is auto-updated.

Last update: 2024-09-15 04:01:25 UTC


README

为您的API响应提供简单的数据转换器。

安装

composer require nimbly/remodel

基本用法

创建一个扩展 Nimbly\Remodel\Transformer 抽象类的转换器。必须实现 transform 方法,并接受一个要转换的单个 对象。这个 对象 可以是模型对象或简单的关联数组,或者其他任何东西 - 真的没关系。

在这个方法中,您将定义并返回转换后的数据作为关联数组。

use Nimbly\Remodel\Transformer;

class UserTransform extends Transformer
{
    public function transform(User $user): array
    {
        return [
            "id" => (int) $user->id,
            "name" => $user->name,
            "email" => $user->email,
            "created_at" => \date("c", $user->created_at)
        ];
    }
}

现在我们已经定义了 UserTransformer,让我们从数据库中检索一个用户并将其转换。为了转换用户数据,我们必须将需要转换的数据映射到特定的转换器。

为此,我们创建一个新的 Item 主题,因为我们正在转换单个项目。如果这是一组用户,我们将使用 Collection 主题。

// Grab the user from the database
$user = App\Models\User::find($id);

// Create a new Item subject using the UserTransformer
$subject = new Nimbly\Remodel\Subjects\Item($user, new UserTransformer);

自动包含相关数据

如果转换器只能转换你给出的对象,那么转换器还有什么用?真实用例要复杂得多。如果你需要转换一个作者存储在单独的模型实例中的书籍,并且需要对其进行自己的转换,那怎么办?如果我们需要关于这本书的最新用户评论呢?

在转换器上添加受保护的 $defaultIncludes 数组属性,包含所有你想要默认包含的项目。然后 Remodel 将在转换器上查找名为 "{include}Include" 的方法。例如

class BookTransformer extends Transformer
{
    protected $defaultIncludes = ["author", "reviews"];

    public function transform(Book $book): array
    {
        return [
            "id" => (int) $book->id,
            "title" => $book->title,
            "genre" => $book->genre,
            "isbn" => $book->isbn,
            "published_at" => date("c", $book->published_at)
        ];
    }

    /**
     *
     * Remodel will call this method automatically for you since it's in the list of
     * $defaultIncludes above.
     *
     */
    public function authorInclude(Book $book): Subject
    {
        return new Item($book->author, new AuthorTransformer);
    }

    /**
     *
     * Return an array of reviews.
     *
     */
    public function reviewsInclude(Book $book): Subject
    {
        return new Collection($book->reviews, new ReviewTransformer);
    }
}

现在让我们创建我们的 Author 对象的转换器。

class AuthorTransformer extends Transformer
{
    public function transform(Author $author)
    {
        return [
            "id" => (int) $author->id,
            "name" => $author->name
        ];
    }
}

嵌套包含

如果你需要在另一个包含中包含可选的包含项,那怎么办?例如,如果作者还有一个默认不包含的 Address 对象呢?

你可以使用点符号来嵌套包含。

protected $defaultIncludes = ["author.address"];

这将包含一个作者及其 Address 对象。

你可以嵌套尽可能多的包含,并且可以无限深入。

protected $defaultIncludes = ["comments.user.profile"];

转换主题集合

你可以以类似的方式转换主题集合或数组。

$collection = new Nimbly\Remodel\Subjects\Collection($books, new BookTransformer);

运行时添加包含项

如果你不总是需要在每个转换中包含相关主题,那怎么办?也许它是一种仅在请求客户端需要时提供资源?

你可以使用 setIncludes 方法将运行时用户提供的包含项传递给转换器实例。

$transformer = new BookTransformer;
$transformer->setIncludes(["author", "publisher"]);

运行时覆盖默认包含项

你可以通过调用 setDefaultIncludes 方法在运行时覆盖默认包含项。

$transformer = new BookTransformer;
$transformer->setDefaultIncludes(["comments"]);