logaretm/transformers

简单的 Laravel Eloquent 模型转换器。

0.2.5 2016-11-13 22:59 UTC

This package is not auto-updated.

Last update: 2024-09-14 18:36:58 UTC


README

Codacy Badge Build Status

这是一个提供转换器(还原器/序列化器)类和特性用于 Laravel Eloquent 模型的包。

安装

通过 Composer

composer require logaretm/transformers
转换器

一个负责将对象从一种形式转换或减少到另一种形式然后被消费的类。

为什么你会使用它们?

转换器在 API 响应中很有用,你希望 AJAX 结果以特定的形式呈现,通过隐藏属性,公开额外的属性,或转换属性类型。

通过将转换模型的职责委托给一个单独的类,可以更容易地处理和维护。

灵感

在看过Jeffery Way 的 Laracasts 视频 并阅读书籍 Building APIs You Won't Hate 之后,我想创建一个特定于 Laravel 应用的简单包,因为我在几乎每个项目中都需要这个功能。

用法

首先你需要为你的模型创建一个转换器。转换器应该扩展 Transformer 抽象类,并提供对 getTransformation() 方法的实现。

class UserTransformer extends Transformer
{
    /**
     * @param $user
     * @return mixed
     */
    public function getTransformation($user)
    {
        return [
            'name' => $user->name,
            'email' => $user->email,
            'memberSince' => $user->created_at->timestamp
        ];
    }
}

现在你可以以多种方式使用转换器,将其注入到控制器方法中,Laravel IoC 应该会实例化它。

class UsersController extends Controller
{
    public function index(UserTransformer $transformer)
    {
        $users = User::get();

        return response()->json([
            'users' => [
                'data' => $transformer->transform($users)
            ]
        ]);
    }
}

如果你不认为 DI 是你的事情,你也可以手动实例化它。

$transformer = new UserTransformer;

动态转换

你还可以在你的模型上使用 TransformableTrait 并定义一个 $transformer 属性,以便能够使用 getTransformer() 方法。

class User extends Model implements Transform
{
    use TransformableTrait;

    /**
     * Defines the appropiate transformer for this model.
     *
     * @var
     */
    protected $transformer = UserTransformer::class;
}

然后你可以使用以下方法获取转换器实例:

$user = User::first();
$transformer = $user->getTransformer(); // returns instance of UserTransformer.

这在你想动态转换模型时很有帮助。但请注意,如果返回的实例不是 Transformer 的实例,它将抛出 TransformerException

服务提供者

你可能发现反复检索转换器并不直观,你可以使用 TransformerServiceProvider 和一个配置文件来定义一个将每个模型或任何类映射到转换器类的数组。

  • 将此行添加到 config/app.php 中的服务提供者数组。

Logaretm\Transformers\Providers\TransformerServiceProvider::class

  • 运行此 artisan 命令

php artisan vendor:publish --provider="Logaretm\Transformers\Providers\TransformerServiceProvider" --tags="config"

  • 转到 config/transformers.php 并用你的模型/转换器对填充数组。
    'transformers' => [
        User::class => UserTransformerClass
    ]
  • 现在你不需要在你的模型上提供 $transformer 属性,也不需要实现接口。

请注意,对于相关模型的转换器解析将优先考虑已注册的转换器。

此外,你现在可以使用静态方法 Transformer::makeTransformer::canMake 为模型实例化转换器,使用特性仍然很有帮助,但不再是必需的。

if(Transformer::canMake(User::class); // returns true if the transformer is registered.
$transformer = Transformer::make(User::class); // creates a transformer for the model.

关系

你还可以使用流畅方法 with() 将模型及其相关模型一起转换。

相关模型转换器在以下情况下解析:

  • 如果已注册服务提供者,则它将解析自配置数组。

  • 如果模型实现了 Transformable 协议,这是由 TransformableTrait 自动化的。它还需要定义 $transformer 属性。

否则,模型将使用简单的 toArray() 调用来转换。

$transformer = new UserTransformer();
$users = User::with('posts')->get();
$data = $transformer->with('posts')->transform($users);

你也可以使用相同的语法转换嵌套关系。

$transformer = new UserTransformer();
$users = User::with('posts.tags')->get();
$data = $transformer->with('posts.tags')->transform($users);

您可以使用 $transformer->resetRelations() 重置变压器关系,这将从转换中移除相关模型。注意,任何对 with 的调用都会自动重置变压器。

除了集合外,您还可以转换分页器或单个对象。

$users = User::get();
$transformer->transform($users); // returns an array of arrays.

$paginator = User::paginate(15);
$transformer->transform($paginator); // returns an array(15).

$user = User::first();
$transformedUser =  $transformer->transform($user); // returns a single array.

备用转换

您不必为每个变压器只使用一个转换,例如,您可能需要为同一模型在特定场景下使用特定的转换。

使用 setTransformation 方法,您可以覆盖转换方法以使用在变压器上定义的另一个方法。

class UserTransformer extends Transformer
{
    /**
     * @param $user
     * @return mixed
     */
    public function getTransformation($user)
    {
        return [
            'name' => $user->name,
            'email' => $user->email,
            'memberSince' => $user->created_at->timestamp
        ];
    }

    // Custom/Alternate transformation.
    public function adminTransformation($user)
    {
        return [
            'name' => $user->name,
            'email' => $user->email,
            'memberSince' => $user->created_at->timestamp,
            'isAdmin' => $user->isAdmin()
        ];
    }
}

要使用备用转换

$transformer->setTransformation('admin');

或者,您可以将闭包作为备用转换方法传递。

$transformer->setTransformation(function ($user) {
    return [
        'name' => $user->name,
        'email' => $user->email,
        'memberSince' => $user->created_at->timestamp,
        'isAdmin' => $user->isAdmin()
    ];
});

注意,转换方法的命名约定为 {转换名称}Transformation

后续对 transform 方法的调用将使用该转换。

请注意,如果请求的转换不存在,它将抛出 TransformerException。

要重置转换方法,请使用 resetTransformation 方法。

$transformer->resetTransformation(); //resets the transformation method.

或者,如果您想重置关系和转换方法

$transformer->reset(); //resets the transformation method and the relations.

生成变压器

您可以使用以下 artisan 命令轻松生成变压器类

php artisan make:transformer {transformer name}

这将创建一个基本的变压器类在 app/Transformers 目录中,别忘了将您的转换放在那里。

测试

使用 php unit 进行测试。

phpunit

TODO

  • 改进 API 和方法名称。
  • 可能有一个控制台命令用于为模型生成变压器。
  • 使用闭包来覆盖转换。
  • 编写更多 todo。

贡献

所有贡献将得到充分认可。

问题

如果您发现任何问题,请通过电子邮件发送至 logaretm1@gmail.com 或使用问题跟踪器。

鸣谢

许可证

MIT 许可证(MIT)。请参阅 许可证文件 了解更多信息。