themsaid/laravel-model-transformers

此包已废弃,不再维护。未建议替代包。

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

v1.1.0 2017-08-16 16:06 UTC

This package is auto-updated.

Last update: 2020-02-05 23:02:45 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中的 providers 数组中添加包服务提供者

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])