azaan / laravel-scene
Laravel API 转换器
Requires
- php: >=5.5.9
- illuminate/database: *
- illuminate/support: *
Requires (Dev)
- phpunit/phpunit: ^7.4@dev
README
Laravel 库,将您的模型转换为 API 响应。
为什么需要转换库?
默认情况下,您可以使用默认实现,它根据 toArray()
将您的模型转换为 json。但是,一旦您开始为不同的端点(例如,基于用户权限、端点类型等)提供不同的模型响应,这种方法就会变得混乱。
此库还允许您将对象转换逻辑与模型分离。您的模型不需要关心它们如何在不同的端点中通过网络表示。您可以使用转换器以相同的方式转换对象或数组。它们不必是 eloquent 模型。
注意:如果您正在使用 >= 5.5,则 Laravel API Resource 是一个很好的起点。在这种情况下,您应该仔细评估您的需求以及您的复杂性如何增长,然后再选择此选项。
安装
使用 composer 安装。
composer require azaan/laravel-scene
用法
创建一个转换器类以转换您的模型。您可以使用相同的转换方法转换数组/集合中的对象或单个对象。
示例。
class PersonTransformer extends SceneTransformer { /** * Eloquent relations to preload * * Note: It will only get preloaded if it already isnt. */ protected function getPreloadRelations() { return [ // preload nested relations of posts defined in PostTransformer 'posts' => SceneTransformer::PRELOAD_RELATED, // load addresses if $this->showMin is truthy 'address' => $this->showMin, // preload createdBy relation 'createdBy', ]; } /** * Structure transformations. * * @return array structure */ protected function getStructure() { return [ 'id', 'name', 'email', 'fullname', 'actions', 'address' => [ 'name', 'street', ], 'status' => new ArrayMapTransform([ 'active' => 'Active', 'blocked' => 'Blocked', 'temp-disabled' => 'Temporarily Disabled', ]), 'posts' => PostTransformer::createMinTransformer(), // return the field 'joined_date' as 'date', 'date' => 'joined_date', 'created_at' => new DateFormatTransform('Y-m-d'), ]; } /** * Structure to use when returning multiple objects * * @return array structure */ protected function getMinStructure() { return [ 'id', 'name', 'email', // add extra key only when some condition meets 'extra' => $this->when($this->someCondition, 'extra'), ]; } protected function getFullname(Person $person) { return $person->first_name . ' ' . $person->last_name; } protected function getActions(Person $person) { // call service methods to figure out what actions the user can perform return ['can_edit', 'can_update']; } }
现在在您的控制器方法中。
public function all() { $people = $this->personService->getAllPeople(); $transformer = PersonTransformer::createMinTransformer(); return SceneResponse::respond($people, $transformer); } public function show($id) { $person = $this->personService->getPersonByIdOrFail($id); $transformer = new PersonTransformer(); return SceneResponse::respond($person, $transformer); }
您可以使用 SceneRespond::respond
方法,传递数据集合或单个对象。转换器将适当地处理它。它还可以处理 LengthAwarePaginator
。
在此示例中,假设您的模型(Person
)具有 id、name、email 和 created_at 属性。对于字段 fullname
,使用 getFullname
方法来解析值。
键的解析步骤如下
- 如果转换器中存在 getter 方法,则调用它
- 检查键是否存在于对象上
- 检查对象上是否存在键的 getter 方法
- 返回
null
嵌套转换器
您可以在另一个转换器内部嵌套转换器。例如,如果您有一个 Company
模型,其中有一个名为 owner 的关系,它解析为 Person
对象,则您的 Company
转换器可以如下所示。
class CompanyTransformer extends SceneTransformer { /** * Structure transformations. * * @return array structure */ protected function getStructure() { return [ 'id', 'name', 'owner' => new PersonTransformer() ]; } }
这样,您可以为每个模型封装转换逻辑,并轻松重用它。
钩子
定义了几个钩子方法,您可以通过覆盖它们来获得所需的行为。
从 Laravel 容器中注入
如果您需要从 laravel 容器中注入类,可以覆盖 inject
方法。所有 inject
方法的参数都将从 Laravel 容器中解析。
最小结构
当您以对象集合(例如,用于列表)响应时,您可能希望响应不同的字段。您可以通过覆盖 getMinStructure()
方法来实现此目的。在这种情况下,当您在控制器中实例化转换器时,请使用 ::createMinTransformer()
方法。
预加载 Eloquent 关系
当响应 Eloquent 对象集合并访问尚未加载的关系时,会导致 N+1 查询问题。您可以覆盖 getPreloadRelations
方法并返回要由转换器预加载的关系数组。转换器将负责仅加载尚未加载的关系,并在适当的时候加载它们。您还可以使用点表示法预加载嵌套关系。(例如:person.address
)
预处理
覆盖 preProcessSingle
和 preProcessCollection
方法以在转换器开始转换对象之前运行任何预处理逻辑。
空状态
重写方法 getNullState
以在对象为空时返回默认状态。默认实现返回 null
排序
通常在传递到转换器之前进行排序会更好。然而,在某些情况下,如果您需要根据在转换后才存在的字段进行排序,可以重写 getOrderBy
来提供排序。您应该返回一个字符串形式的字段名来按该字段排序。如果您需要指定方向,返回一个数组。(例如:['field_name', 'DESC']
)
后处理钩子。
要在所有转换之后进行任何更改,可以重写方法 transformObject
。转换后的输出数组将作为第一个参数传递,原始对象作为第二个参数。
许可证
MIT