mohamedhabibwork/laravel-model-transformers

复杂模型属性的简单转换层。

dev-master 2022-08-09 12:49 UTC

This package is auto-updated.

Last update: 2024-09-09 17:18:55 UTC


README

Latest Version on Packagist Software License Total Downloads

此包帮助API开发者轻松将Eloquent模型转换为可转换为JSON的数组。

以下是如何使用它的示例,假设你有一个包含以下数据的模型

{
	"name": "iPhone",
	"type": 1
}

在这里,你使用一个数值来表示不同类型,你还在模型中有一个将数值映射到字符串的修改器。

在控制器内部,我们可以将模型转换为更友好的API结构。

<?php
class SomeController{
	function getIndex(){
		$product = Product::find(1);
		
		return response([
			"product" => ProductTransformer::transform($product)
		]);
	}
}

上面的代码将生成一个可能看起来像这样的JSON字符串

{
	"product": {
		"name": "iPhone",
		"type": {
			"key": 1,
			"name": "Mobile Phone"
		}
	}
}

安装

首先通过Composer安装包。在你的终端中运行以下命令

composer require themsaid/laravel-model-transformers

Composer完成后,将包服务提供者在config/app.php中的提供者数组中添加

Themsaid\Transformers\TransformersServiceProvider::class

最后发布配置文件

php artisan vendor:publish --provider="Themsaid\Transformers\TransformersServiceProvider"

这就完成了。

使用方法

通过扩展AbstractTransformer类创建一个模型转换器类

<?php
class CategoryTransformer extends Themsaid\Transformers\AbstractTransformer
{
    public function transformModel(Model $item)
    {
        $output = [
            'name'		=> $item->name,
            'type'		=> [
            		'key'	=> $item->type,
            		'name'	=> $item->typeName
            ],
        ];

        return $output;
    }

}

现在你可以在任何控制器中调用转换器

<?php
return response(
	CategoryTransformer::transform( Category::find(1) )
);

你还可以传递一个集合,结果将是一个转换后的模型数组

<?php
return response(
	CategoryTransformer::transform( Category::all() )
);

处理关系

此包包含两个处理关系的有用方法,第一个方法可以帮助你知道特定的关系是否是懒加载的

isRelationshipLoaded()

<?php
class ProductTransformer extends AbstractTransformer
{
    public function transformModel(Model $item)
    {
        $output = array_only($item->toArray(), ['name', 'id']);

        if ($this->isRelationshipLoaded($item, 'tags')) {
            $output['tags'] = TagTransformer::transform($item->tags);
        }

        return $output;
    }
}

现在只有当标签是懒加载的时候,它们才会出现在$output数组中,这有助于在查询具有关系的模型时记住要懒加载。

isLoadedFromPivotTable()

此方法可以帮助你知道模型是否是从多对多关系加载的,当表中存在枢纽数据并且你想展示它们时,这非常有用。

<?php
class TagTransformer extends AbstractTransformer
{
    public function transformModel(Model $item)
    {
        $output = array_only($item->toArray(), ['name', 'id']);

        if ($this->isLoadedFromPivotTable($item, 'products_tags')) {
            $output['relationship_data'] = [
                'is_active' => $item->pivot->is_active,
            ];
        }

        return $output;
    }
}

传递选项到转换器

你可能需要从控制器向转换器传递一些选项,你可以通过向transform()方法提供选项数组作为第二个参数来实现这一点

<?php

CategoryTransformer::transform($category, ['hide_admin_id' => true])

现在从CategoryTransformer内部,你可以检查选项参数

<?php
class CategoryTransformer extends AbstractTransformer
{
    public function transformModel(Model $item)
    {
    	$output = [];
    
		if (@$this->options['hide_admin_id']) {
			unset($output['admin_id']);
		}
		
		return $output;
	}
}

使用简写方法

此包附带了一个简写方法,用于应用模型或集合的转换

<?php
class SomeController{
	function getIndex(){
		$product = Product::find(1);

		return response([
			"product" => transform($product)
		]);
	}
}

使用transform()方法,该包根据作为第一个参数传递的模型或集合查找合适的转换器。

默认情况下,它假设所有转换器都位于App\Transformers命名空间下,你可以在配置文件中更改此行为。

你还可以将选项作为第二个参数传递到转换器中

<?php

transform(Model::find(1), ['use_nl2br' => true])