bfg/transformer

安装次数: 24,446

依赖项: 0

建议者: 0

安全性: 0

星标: 0

关注者: 2

分支: 1

开放性问题: 0

类型:bfg-app

1.4.4 2024-09-07 18:04 UTC

README

安装

composer require bfg/transformer

描述

该包旨在转换模型(例如通过API获取的数据)的数据,以及从模型(例如,在需要通过API发送数据时)的数据。

使用方法

创建新的转换器

php artisan make:transformer UserTransformer -m User

描述你将在新的类 App\Transformers\UserTransformer$toModel 变量中填写的所有字段

use Bfg\Transformer\Transformer;
...
class UserTransformer extends Transformer
{
    /**
     * If your data that you received from 
     * a third-party source have an Identifier, 
     * then you need to specify this field.
     * @var string|null 
     */
    protected ?string $remoteId = "ID";

    /**
     * An alternative source indicate the model 
     * if it is not sent to the transformer.
     * @var string|null 
     */
    protected ?string $modelClass = User::class;

    /**
     * Mapping to send data generation into the model.
     * @var string[]
     */
    protected array $toModel = [
        'FullName' => 'name',
        'Email' => 'email',
        
        // or if you identical key names:
        'name',
        'email',
        
        // for related iteration
        ContactsTransformer::class // The transformer of contacts 
            => 'contacts', // The relation name in the model
    ];
    
    /**
     * Mapping for the direction of data generation 
     * from the model, back to third-party service.
     * @var string[]
     */
    protected array $fromModel = [
        'name' => ['FirstName', 'LastName'],
        'address' => 'Address',
        'email' => 'Email',
        'phone' => 'Phone',
    ];
    
    /**
     * To implement the data unloading mechanism 
     * on third-party service.
     * @return void
     */
    public function upload()
    {

    }
}

修改器

为了完全转换,通常需要更精确地处理,为此提供了不同方向的修改器

use Bfg\Transformer\Transformer;
...
class UserTransformer extends Transformer
{
    ...
    protected array $toModel = [
        'FullName' => 'name',
        'Email' => 'email',
    ];
    
    protected array $fromModel = [
        'name' => ['FirstName', 'LastName'],
        'email' => 'Email',
    ];
    
    protected function toNameAttribute($dataValue)
    {
        $this->data; // All data is available on this property.
        $this->model; // The model is available on this property.
        
        return $dataValue;
    }
    
    protected function fromNameAttribute($modelValue)
    {    
        return $modelValue;
    }
    
    protected function forFirstNameDataAttribute($modelValue)
    {    
        return $modelValue;
    }
    
    protected function forLastNameDataAttribute($modelValue)
    {    
        return $modelValue;
    }
    
    protected function forEmailDataAttribute($modelValue)
    {    
        return $modelValue;
    }
}

转换

所有转换转换规则完全复制自 Laravel 属性的转换,其功能完全相同(除了自定义转换的 set 之外)

...
    protected $casts = [
        'views' => 'int'
    ];
...

应用于数据,而不是模型。

模型捕获

为了捕获转换器的模型定义(基于数据),可以使用 getModel 方法

use Bfg\Transformer\Transformer;
use App\Models\User;
...
class UserTransformer extends Transformer
{
    ...
    protected function getModel()
    {    
        return User::where('remote_id', $this->data['ID'])->first()
            ?: parent::getModel();
    }
}

数据捕获

对于转换器,可以直接在内部确定处理值,这种机制允许生成内置依赖项嵌套。根据规则,如果返回 Illuminate\Support\Collection 集合,则将为每个条目创建转换器实例的选择。

use Bfg\Transformer\Transformer;
use App\Models\User;
...
/**
 * @property-read ApiService $api For example some "ApiService" class
 */
class UserTransformer extends Transformer
{
    ...
    protected function getData()
    {    
        return $this->api->findUser($this->model->remote_id);
    }
}

数据到模型

use App\Transformers\UserTransformer;
...
$data = [
    'userName' => 'Thomas',
    'userEmail' => 'thomas@example.com',
]; // for example, any data

$model = UserTransformer::make()
    ->withData($data)
    ->toModel(); // Instance of User model
    
// Or from any model
$model = UserTransformer::make()
    ->withData($data)
    ->withModel(User::find(1))
    ->toModel(); // With my instance of User model

$model->save();

模型数据

use App\Models\User;
use App\Transformers\UserTransformer;
...
$model = User::find(1);

$data = UserTransformer::make()->withModel($model)->toData()->data; 
    // => ['userName' => 'Thomas','userEmail' => 'thomas@example.com']

// Or with you data filling
$fillData = (object) ['userName' => null, 'userEmail' => null, 'otherData' => 'test']
UserTransformer::make()->withModel($model)->withData($fillData)->toData()->upload();

接下来,集合将模型的全部方法感知到整个集合中

use App\Transformers\TransformerCollection;
...
/** @var TransformerCollection $collection */
$collection->save();

在事务中启动整个链

use App\Transformers\TransformerCollection;
...
/** @var TransformerCollection $collection */
$collection->transaction()->save();
// For additional updating
$collection->transaction()->save()->update([
    'api_updated_at' => now()
]);