yii1tech/model-typecast

允许在Yii1中对模型和ActiveRecord属性进行类型转换

1.0.0 2023-12-22 15:58 UTC

This package is auto-updated.

Last update: 2024-09-22 17:34:24 UTC


README

为Yii 1的模型属性类型转换扩展


本扩展为Yii1模型和ActiveRecord属性类型转换提供支持。

有关许可信息,请参阅LICENSE文件。

Latest Stable Version Total Downloads Build Status

安装

安装此扩展的最佳方式是通过composer

运行以下命令之一:

php composer.phar require --prefer-dist yii1tech/model-typecast

或者

"yii1tech/model-typecast": "*"

将其添加到您的composer.json文件中的"require"部分。

用法

此扩展为Yii1模型和ActiveRecord自动属性类型转换提供支持。它通过使用\yii1tech\model\typecast\TypecastBehavior行为来实现。它应该附加到\CModel\CActiveRecord派生类。例如

<?php

use yii1tech\model\typecast\TypecastBehavior;

class Item extends CActiveRecord
{
    public function behaviors()
    {
        return [
            'typecastBehavior' => [
                'class' => TypecastBehavior::class,
                'attributeTypes' => [
                    'id' => TypecastBehavior::TYPE_INTEGER,
                    'amount' => TypecastBehavior::TYPE_INTEGER,
                    'price' => TypecastBehavior::TYPE_FLOAT,
                    'is_active' => TypecastBehavior::TYPE_BOOLEAN,
                    'created_at' => TypecastBehavior::TYPE_DATETIME,
                    'json_data' => TypecastBehavior::TYPE_ARRAY_OBJECT,
                ],
                'typecastAfterValidate' => true,
                'typecastBeforeSave' => false,
                'typecastAfterSave' => true,
                'typecastAfterFind' => true,
            ],
        ];
    }

    // ...
}

提示:您可以将\yii1tech\model\typecast\TypecastBehavior::$attributeTypes留空 - 在这种情况下,其值将自动检测:对于ActiveRecord,基于所有者数据库表模式,对于常规模型,基于验证规则。

在上面的示例中,以下情况下将自动执行属性类型转换

  • 模型成功验证后
  • 模型成功保存后
  • 模型从数据库检索后

例如

<?php

$model = new Item();
$model->setAttributes([
    'name' => 'item name',
    'price' => '10.50',
    'amount' => '14',
    'is_active' => '1',
]);

if ($model->validate()) {
    var_dump($model->id); // outputs: int(123456)
    var_dump($model->price); // outputs: float(10.5)
    var_dump($model->amount); // outputs: int(14)
    var_dump($model->is_active); // outputs: bool(true)
}

$model = Item::model()->findByPk($id);
var_dump($model->id); // outputs: int(12345)
var_dump($model->amount); // outputs: int(18)
var_dump($model->is_active); // outputs: bool(true)

您可以通过调用\yii1tech\model\typecast\TypecastBehavior::typecastAttributes()方法在任何时间手动触发属性类型转换

<?php

$model = new Item();
$model->price = '38.5';
$model->is_active = 1;
$model->typecastAttributes();

var_dump($model->price); // outputs: float(38.5)
var_dump($model->is_active); // outputs: bool(true)

JSON类型转换

此行为允许在模型保存时自动将数组或可遍历对象转换为JSON字符串。例如

<?php

$model = new Item();
$model->json_data = [ // will be saved in DB as '{foo: "bar"}'
    'foo' => 'bar',
];
$model->save();

注意:即使没有直接属性类型指定,也会发生此类转换。

您可以将JSON列值类型转换为纯array\ArrayObject实例。纯数组消耗较少的内存,但无法写入其特定的内部键。\ArrayObject允许自由操作内部键,但请注意,其值总是通过引用传递。

<?php

// in case mapping in `attributeTypes` is set to `TypecastBehavior::TYPE_ARRAY`
use yii1tech\model\typecast\TypecastBehavior;

class Item extends CActiveRecord
{
    public function behaviors()
    {
        return [
            'typecastBehavior' => [
                'class' => TypecastBehavior::class,
                'attributeTypes' => [
                    'json_data' => TypecastBehavior::TYPE_ARRAY,
                ],
            ],
        ];
    }

    // ...
}

$model = Item::model()->findByPk($id);
var_dump($model->json_data); // outputs: array(1) {...}
var_dump($model->json_data['foo']); // outputs: string(bar)
$model->json_data['foo'] = 'new value'; // PHP E_NOTICE: Indirect modification of overloaded property Item::$json_data has no effect!
$model->json_data = [ // no problem
    'foo' => 'new value',
];
$model->save();

// in case mapping in `attributeTypes` is set to `TypecastBehavior::TYPE_ARRAY_OBJECT`
use yii1tech\model\typecast\TypecastBehavior;

class Item extends CActiveRecord
{
    public function behaviors()
    {
        return [
            'typecastBehavior' => [
                'class' => TypecastBehavior::class,
                'attributeTypes' => [
                    'json_data' => TypecastBehavior::TYPE_ARRAY_OBJECT,
                ],
            ],
        ];
    }

    // ...
}

$model = Item::model()->findByPk($id);
var_dump($model->json_data); // outputs: object(ArrayObject) {...}
var_dump($model->json_data['foo']); // outputs: string(bar)
$model->json_data['foo'] = 'new value'; // no problem
$jsonDataCopy = $model->json_data; // new variable holds the reference to `\ArrayObject` instance!
$jsonDataCopy['foo'] = 'value from copy'; // changes value of `$model->json_data`!
var_dump($model->json_data['foo']); // outputs: string(value from copy)
$model->save();

DateTime类型转换

此行为允许在模型保存时自动将\DateTime实例转换为ISO日期时间字符串。例如

<?php

use yii1tech\model\typecast\TypecastBehavior;

class Item extends CActiveRecord
{
    public function behaviors()
    {
        return [
            'typecastBehavior' => [
                'class' => TypecastBehavior::class,
                'attributeTypes' => [
                    'created_at' => TypecastBehavior::TYPE_DATETIME,
                ],
            ],
        ];
    }

    // ...
}

$model = new Item();
$model->created_at = new DateTime('now'); // will be saved in DB as '2023-12-22 10:14:17'
$model->save();

$model = Item::model()->findByPk($id);
var_dump($model->created_at); // outputs: object(DateTime)

如果您使用整数Unix时间戳存储日期,则可以使用\yii1tech\model\typecast\TypecastBehavior::TYPE_TIMESTAMP进行正确转换。例如

<?php

use yii1tech\model\typecast\TypecastBehavior;

class Item extends CActiveRecord
{
    public function behaviors()
    {
        return [
            'typecastBehavior' => [
                'class' => TypecastBehavior::class,
                'attributeTypes' => [
                    'created_at' => TypecastBehavior::TYPE_TIMESTAMP,
                ],
            ],
        ];
    }

    // ...
}

$model = new Item();
$model->created_at = new DateTime('now'); // will be saved in DB as '1703257478'
$model->save();

$model = Item::model()->findByPk($id);
var_dump($model->created_at); // outputs: object(DateTime)

此扩展还支持nesbot/carbon包。为了将日期转换为\Carbon\Carbon,您应使用以下类型

  • \yii1tech\model\typecast\TypecastBehavior::TYPE_DATETIME_CARBON
  • \yii1tech\model\typecast\TypecastBehavior::TYPE_TIMESTAMP_CARBON

自定义类型转换

您可以使用在\yii1tech\model\typecast\TypecastBehavior::$attributeTypes中用作类型指定的可调用来指定任何自定义属性类型转换。例如

<?php

use yii1tech\model\typecast\TypecastBehavior;

class Item extends CActiveRecord
{
    public function behaviors()
    {
        return [
            'typecastBehavior' => [
                'class' => TypecastBehavior::class,
                'attributeTypes' => [
                    'heap_data' => function ($value) {
                        if (is_object($value)) {
                            return $value;
                        }
                        
                        $heap = new \SplMaxHeap();
                        foreach (json_decode($value) as $element) {
                            $heap->insert($element);
                        }
                        
                        return $heap;
                    },
                ],
            ],
        ];
    }

    // ...
}

$model = Item::model()->findByPk($id);
var_dump($model->heap_data); // outputs: object(SplMaxHeap)