vkovic/laravel-custom-casts

为Laravel模型属性创建自定义转换类型

v1.4 2021-04-19 12:15 UTC

This package is auto-updated.

Last update: 2024-09-21 14:32:58 UTC


README

Build Downloads Stable License

为Laravel模型属性创建自定义转换类型

Laravel自定义转换类型与Eloquent属性转换类似,但具有自定义逻辑(在单独的类中)。这意味着我们可以跨多个模型使用相同的转换逻辑——我们可能编写图片上传逻辑并在任何地方使用它。除了转换到自定义类型外,此包还允许自定义转换监听并响应底层模型事件。

让我们回顾一些Laravel常见的转换类型及其使用示例

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'is_admin' => 'boolean',
        'login_count' => 'integer'
        'height' => 'decimal:2'
    ];
}

除了booleanintegerdecimal外,Laravel自带支持realfloatdoublestringobjectarraycollectiondatedatetimetimestamp转换。

有时使用自定义逻辑处理更复杂的类型很方便,并且转换能够监听并响应模型事件。这就是这个包派上用场的地方。

如果,例如,我们使用自定义转换存储图像,并在模型被删除时需要删除它,则直接从自定义转换处理事件非常有用。请参阅旧文档中的此示例。

📦 vkovic 包 📦

请查看我的其他包——它们都是免费的、写得很好的,其中一些很有用 😄。如果你发现有什么有趣的,请考虑为我提供包开发的支持,提出一个想法或某种改进,如果喜欢,请给仓库加星标,或者简单地查看代码——下面有很多有用的东西。

兼容性

该包与Laravel版本5.55.65.75.86兼容

以及Lumen版本5.55.65.75.8

Laravel 7+具有对自定义转换的原生支持,与该库不兼容。

最低支持的PHP版本是7.1。也支持PHP 8

安装

通过Composer安装包

composer require vkovic/laravel-custom-casts

使用方法

利用自定义转换类

要启用模型中的自定义转换,请使用HasCustomCasts特质,并使用$casts定义哪些属性将被转换——按照Laravel标准。

// File: app/User.php

namespace App;

use App\CustomCasts\NameCast;
use Illuminate\Database\Eloquent\Model;
use Vkovic\LaravelCustomCasts\HasCustomCasts;

class User extends Model
{
    use HasCustomCasts;

    protected $casts = [
        'is_admin' => 'boolean', // <-- Laravel default cast type
        'name' => NameCast::class // <-- Our custom cast class (see the section below)
    ];
}

定义自定义转换类

该类将负责我们的自定义转换逻辑。

// File: app/CustomCasts/NameCast.php

namespace App\CustomCasts;

use Vkovic\LaravelCustomCasts\CustomCastBase;

class NameCast extends CustomCastBase
{
    public function setAttribute($value)
    {
        return ucwords($value);
    }

    public function castAttribute($value)
    {
        return $this->getTitle() . ' ' . $value;
    }

    protected function getTitle()
    {
        return ['Mr.', 'Mrs.', 'Ms.', 'Miss'][rand(0, 3)];
    }
}

所需的setAttribute方法接收在模型字段上设置的$value,并应返回存储在数据库中的原始值。

可选的castAttribute方法接收从数据库中获取的原始$value,并应返回一个变异值。如果省略此方法,则返回原始数据库值。

为了本例,我们将实现一个额外的功能,该功能将为从数据库检索到的用户随机添加一个标题。

测试自定义转换类

让我们创建一个用户,看看会发生什么。

$user = new App\User;
$user->name = 'john doe';

$user->save();

这将创建我们的新用户,并将他们的名字存储在数据库中,每个单词的首字母大写。

当我们检索用户并尝试访问他们的名字时,标题将添加到它前面——就像我们在自定义NameCast类中定义的那样。

dd($user->name); // 'Mr. John Doe'

处理模型事件

假设我们希望在用户的名字更改时通知管理员。

// File: app/CustomCasts/NameCast.php

public function updated()
{
    $attribute = $this->attribute;

    if($this->model->isDirty($attribute)) {
        // Notify admin about name change
    }
}

除了updated方法外,我们还可以定义其他标准模型事件的方法:retrievedcreatingcreatedupdatingsavingsaveddeletingdeletedrestoringrestored

其他功能

如上代码所示,我们可以轻松访问转换后的属性名以及底层模型的实例。

// File: app/CustomCasts/NameCast.php

// Get the name of the model attribute being casted
dd($this->attribute); // 'name'

// Access our `User` model
dd(get_class($this->model)); // 'App/User'

我们还可以直接从模型中检索所有转换属性及其对应的类。

// File: app/User.php

dd($this->getCustomCasts()); // ['name' => 'App/CustomCasts/NameCast']

使用别名转换

您可能会发现使用别名来定义自定义转换更容易,例如。

protected $casts = [
    'avatar' => 'image' // <-- You prefer this ...
    // ---
    'avatar' => ImageCast::class // <-- ... over this
];

为了使魔法发生,首先将包的服务提供者添加到providers数组中

// File: config/app.php

'providers' => [
    // ...

    /*
     * Package Service Providers...
     */
    Vkovic\LaravelCustomCasts\CustomCastsServiceProvider::class

    // ...
]

一旦添加了提供者,发布配置文件,该文件将用于将别名与其对应的自定义转换类关联起来

php artisan vendor:publish --provider="Vkovic\LaravelCustomCasts\CustomCastsServiceProvider"

此命令应创建一个位于config/custom_casts.php的配置文件。打开它,查看配置选项的示例。

在不使用Laravel的情况下使用

此包也可以在不完整安装Laravel的情况下使用,例如使用jenssegers/model,或者如果您的项目使用illuminate/database库。

更多示例

您可以在旧版文档中找到更多示例。

贡献

如果您打算修改此Laravel包,您应该运行它附带的测试。最简单的方法是使用Dockerdocker-composephpunit

首先,我们需要初始化Docker容器(有关详细信息,请参阅docker-composer.yaml)。

docker-compose up --exit-code-from app

然后,我们可以运行测试并查看输出

docker-compose run --rm app phpunit