nimbly / 重构
为您的API响应提供简单的数据转换器
Requires
- php: >=7.3|^8.0
Requires (Dev)
- php-coveralls/php-coveralls: ^2.1
- phpunit/phpunit: ^9.0
- symfony/var-dumper: ^4.2
- vimeo/psalm: ^4.0
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"]);