azaan/laravel-scene

Laravel API 转换器

v2.0.1 2021-08-17 13:32 UTC

This package is auto-updated.

Last update: 2024-09-17 20:20:36 UTC


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 方法来解析值。

键的解析步骤如下

  1. 如果转换器中存在 getter 方法,则调用它
  2. 检查键是否存在于对象上
  3. 检查对象上是否存在键的 getter 方法
  4. 返回 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

预处理

覆盖 preProcessSinglepreProcessCollection 方法以在转换器开始转换对象之前运行任何预处理逻辑。

空状态

重写方法 getNullState 以在对象为空时返回默认状态。默认实现返回 null

排序

通常在传递到转换器之前进行排序会更好。然而,在某些情况下,如果您需要根据在转换后才存在的字段进行排序,可以重写 getOrderBy 来提供排序。您应该返回一个字符串形式的字段名来按该字段排序。如果您需要指定方向,返回一个数组。(例如:['field_name', 'DESC']

后处理钩子。

要在所有转换之后进行任何更改,可以重写方法 transformObject。转换后的输出数组将作为第一个参数传递,原始对象作为第二个参数。

许可证

MIT