morrislaptop/laravel-popo-caster

使用 Symfony's Serializer 在 Laravel 中自动将 JSON 列转换为丰富的 PHP 对象

v0.12.0 2024-08-10 08:56 UTC

This package is auto-updated.

Last update: 2024-09-15 10:25:27 UTC


README

Latest Version on Packagist GitHub Tests Action Status Total Downloads

Laravel 很棒。Spatie 的 数据传输对象 包对于 PHP 来说很棒。但是它们不会将对象如日期转换为 DateTime,集合有点痛苦。普通旧 PHP 对象(POPOs)在这方面稍好一些。

你是否曾经想要将你的 JSON 列转换为值对象?

此包为你提供了 2 个 caster 类

  • Serializer,它将你的值对象序列化并存储在单个 JSON 字段中
  • Normalizer,它将你的值对象规范化并将属性存储在模型的字段上

底层实现了 Laravel 的 Castable 接口 和 Laravel 的 自定义 cast,用于在 object(或兼容数组)和你的 JSON 数据库列之间进行序列化。它使用 Symfony 的 Serializer 来实现这一点。

此包受到 Laravel Castable Data Transfer Object 的启发!

安装

您可以通过 composer 安装此包

composer require morrislaptop/laravel-popo-caster

Serializer 使用方法

1. 创建你的 POPO

namespace App\Values;

class Address
{
    public function __construct(
        public string $street,
        public string $suburb,
        public string $state,
        public Carbon $moved_at,
    ) {
    }
}

2. 配置你的 Eloquent 属性以转换为它

请注意,这应该在您的数据库模式中的 jsonbjson 列上。对象和数组都受支持。

namespace App\Models;

use App\Values\Address;
use Illuminate\Database\Eloquent\Model;
use Morrislaptop\LaravelPopoCaster\Serializer;

/**
 * @property Address $address
 */
class User extends Model
{
    protected $casts = [
        'address' => Serializer::class . ':' . Address::class,
        'prev_addresses' => Serializer::class . ':' . Address::class . '[]',
    ];
}

就这样!你现在可以传递你的 Address 类的实例,或者甚至只是一个具有兼容结构的数组。它将自动在您的类和 JSON 之间进行转换以进行存储,数据在输入和输出时将进行验证。

$user = User::create([
    // ...
    'address' => [
        'street' => '1640 Riverside Drive',
        'suburb' => 'Hill Valley',
        'state' => 'California',
        'moved_at' => now(),
    ],
    'addresses' => [
        [
            'street' => '42 Wallaby Way',
            'suburb' => 'Sydney',
            'state' => 'NSW',
            'moved_at' => '2020-01-14T00:00:00Z',
        ],
    ]
])

$residents = User::where('address->suburb', 'Hill Valley')->get();

但最好的部分是,你可以通过添加领域特定的方法来装饰你的类,将其转换为强大的值对象。

$user->address->toMapUrl();

$user->address->getCoordinates();

$user->address->getPostageCost($sender);

$user->address->calculateDistance($otherUser->address);

$user->address->moved_at->diffForHumans();

echo (string) $user->address;

Normalizer 使用方法

1. 创建你的 POPO

namespace App\Values;

class Money
{
    public function __construct(
        public int $amount,
        public string $currency,
    ) {
    }
}

2. 配置你的 Eloquent 属性以转换为它

请注意,您的值对象的属性应该是您数据库模式中的列。

namespace App\Models;

use App\Values\Money;
use Illuminate\Database\Eloquent\Model;
use Morrislaptop\LaravelPopoCaster\Normalizer;

/**
 * @property Money $money
 */
class User extends Model
{
    protected $casts = [
        'money' => Normalizer::class . ':' . Money::class,
    ];
}

就这样!你现在可以传递你的 Money 类的实例,或者在模型上设置单个属性。它将自动在您的类和属性之间进行转换以进行存储,数据在输入和输出时将进行验证。

$user = User::create([
    // ...
    'amount' => 1000,
    'curency' => 'AUD',
]);

$user = User::create([
    // ...
    'money' => new Money(1000, 'AUD'),
])

但最好的部分是,你可以通过添加领域特定的方法来装饰你的类,将其转换为强大的值对象。

$user->money->convertTo('USD');

插件

想要一个轻松模拟或为您的 POPO 创建工厂的方法?查看 morrislaptop/popo-factory

测试

composer test

更新日志

请参阅 CHANGELOG 以获取有关最近更改的更多信息。

贡献

请参阅 CONTRIBUTING 以获取详细信息。

安全漏洞

请查看我们关于如何报告安全漏洞的 安全策略

鸣谢

许可证

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