类 yii\behaviors\AttributeTypecastBehavior
AttributeTypecastBehavior 提供了模型属性自动类型转换的功能。
当使用 ActiveRecord 操作无模式数据库(如 MongoDB 或 Redis)时,此行为非常有用。它也适用于常规的 yii\db\ActiveRecord 甚至 yii\base\Model,允许在模型验证后保持严格的属性类型。
此行为应附加到 yii\base\Model 或 yii\db\BaseActiveRecord 的子类。
您应该通过 $attributeTypes 指定精确的属性类型。
例如
use yii\behaviors\AttributeTypecastBehavior;
class Item extends \yii\db\ActiveRecord
{
    public function behaviors()
    {
        return [
            'typecast' => [
                'class' => AttributeTypecastBehavior::class,
                'attributeTypes' => [
                    'amount' => AttributeTypecastBehavior::TYPE_INTEGER,
                    'price' => AttributeTypecastBehavior::TYPE_FLOAT,
                    'is_active' => AttributeTypecastBehavior::TYPE_BOOLEAN,
                ],
                'typecastAfterValidate' => true,
                'typecastBeforeSave' => false,
                'typecastAfterFind' => false,
            ],
        ];
    }
    // ...
}
提示:您可以将 $attributeTypes 留空 - 在这种情况下,它的值将根据所有者验证规则自动检测。以下示例将自动创建与上面配置的相同的 $attributeTypes 值
use yii\behaviors\AttributeTypecastBehavior;
class Item extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            ['amount', 'integer'],
            ['price', 'number'],
            ['is_active', 'boolean'],
        ];
    }
    public function behaviors()
    {
        return [
            'typecast' => [
                'class' => AttributeTypecastBehavior::class,
                // 'attributeTypes' will be composed automatically according to `rules()`
            ],
        ];
    }
    // ...
}
此行为允许在以下情况下进行自动属性类型转换
- 模型验证成功后
- 模型保存之前(插入或更新)
- 模型查找后(通过查询查找或刷新)
您可以使用字段 $typecastAfterValidate、$typecastBeforeSave 和 $typecastAfterFind 控制特定情况下的自动类型转换。默认情况下,类型转换仅在模型验证后执行。
注意:您可以随时手动触发属性类型转换,调用 typecastAttributes() 方法
$model = new Item();
$model->price = '38.5';
$model->is_active = 1;
$model->typecastAttributes();
公共属性
| 属性 | 类型 | 描述 | 定义于 | 
|---|---|---|---|
| $attributeTypes | array|null | 属性类型转换映射,格式为:属性名 => 类型。 | yii\behaviors\AttributeTypecastBehavior | 
| $owner | yii\base\Model|yii\db\BaseActiveRecord | 此行为的所有者。 | yii\behaviors\AttributeTypecastBehavior | 
| $skipOnNull | boolean | 是否跳过 null值的类型转换。 | yii\behaviors\AttributeTypecastBehavior | 
| $typecastAfterFind | boolean | 是否在从数据库中检索所有者模型数据后(查找或刷新后)执行类型转换。 | yii\behaviors\AttributeTypecastBehavior | 
| $typecastAfterSave | boolean | 是否在保存所有者模型(插入或更新)后执行类型转换。 | yii\behaviors\AttributeTypecastBehavior | 
| $typecastAfterValidate | boolean | 是否在所有者模型验证后执行类型转换。 | yii\behaviors\AttributeTypecastBehavior | 
| $typecastBeforeSave | boolean | 是否在保存所有者模型(插入或更新)之前执行类型转换。 | yii\behaviors\AttributeTypecastBehavior | 
公共方法
受保护的方法
| 方法 | 描述 | 定义于 | 
|---|---|---|
| detectAttributeTypes() | 根据所有者验证规则为 $attributeTypes 组成默认值。 | yii\behaviors\AttributeTypecastBehavior | 
| resetOldAttributes() | 重置命名属性的旧值。 | yii\behaviors\AttributeTypecastBehavior | 
| typecastValue() | 将给定值转换为指定类型。 | yii\behaviors\AttributeTypecastBehavior | 
常量
| 常量 | 值 | 描述 | 定义于 | 
|---|---|---|---|
| TYPE_BOOLEAN | 'boolean' | yii\behaviors\AttributeTypecastBehavior | |
| TYPE_FLOAT | 'float' | yii\behaviors\AttributeTypecastBehavior | |
| TYPE_INTEGER | 'integer' | yii\behaviors\AttributeTypecastBehavior | |
| TYPE_STRING | 'string' | yii\behaviors\AttributeTypecastBehavior | 
属性详情
属性类型转换映射,格式为:属性名 => 类型。类型可以通过 PHP 可调用函数设置,该函数接受原始值作为参数,并应返回类型转换结果。例如
[
    'amount' => 'integer',
    'price' => 'float',
    'is_active' => 'boolean',
    'date' => function ($value) {
        return ($value instanceof \DateTime) ? $value->getTimestamp(): (int) $value;
    },
]
如果未设置,则属性类型映射将根据所有者验证规则自动组成。
是否跳过对 null 值的类型转换。如果启用,则等于 null 的属性值将不会进行类型转换(例如,null 保持 null),否则它将根据 $attributeTypes 中配置的类型进行转换。
是否在从数据库中检索拥有者模型数据后(查找或刷新后)执行类型转换。可以禁用此选项以提高性能。例如,在 yii\db\ActiveRecord 使用的情况下,查找后进行类型转换在大多数情况下都不会带来好处,因此可以禁用。请注意,在此行为附加到模型后,更改此选项值将无效。
是否在保存拥有者模型(插入或更新)后执行类型转换。可以禁用此选项以提高性能。例如,在 yii\db\ActiveRecord 使用的情况下,保存后进行类型转换不会带来任何好处,因此可以禁用。请注意,在此行为附加到模型后,更改此选项值将无效。
是否在拥有者模型验证后执行类型转换。请注意,只有在验证成功的情况下才会执行类型转换,例如拥有者模型没有错误。请注意,在此行为附加到模型后,更改此选项值将无效。
是否在保存拥有者模型(插入或更新)之前执行类型转换。可以禁用此选项以提高性能。例如,在 yii\db\ActiveRecord 使用的情况下,保存前进行类型转换不会带来任何好处,因此可以禁用。请注意,在此行为附加到模型后,更改此选项值将无效。
方法详情
| public mixed __call ( $name, $params ) | ||
| $name | string | 方法名称 | 
| $params | array | 方法参数 | 
| 返回值 | mixed | 方法返回值 | 
|---|---|---|
| 抛出 | yii\base\UnknownMethodException | 调用未知方法时 | 
                public function __call($name, $params)
{
    throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
}
            
        定义于: yii\base\BaseObject::__construct()
构造函数。
默认实现执行两件事
- 使用给定的配置 $config初始化对象。
- 调用 init()。
如果在子类中重写此方法,建议
- 构造函数的最后一个参数是一个配置数组,如这里的 $config。
- 在构造函数的末尾调用父实现。
| public void __construct ( $config = [] ) | ||
| $config | array | 将用于初始化对象属性的名称-值对 | 
                public function __construct($config = [])
{
    if (!empty($config)) {
        Yii::configure($this, $config);
    }
    $this->init();
}
            
        定义于: yii\base\BaseObject::__get()
返回对象属性的值。
不要直接调用此方法,因为它是一个 PHP 魔术方法,在执行 $value = $object->property; 时会隐式调用。
另请参阅 __set()。
| public mixed __get ( $name ) | ||
| $name | string | 属性名称 | 
| 返回值 | mixed | 属性值 | 
|---|---|---|
| 抛出 | yii\base\UnknownPropertyException | 如果未定义属性 | 
| 抛出 | yii\base\InvalidCallException | 如果属性是只写属性 | 
                public function __get($name)
{
    $getter = 'get' . $name;
    if (method_exists($this, $getter)) {
        return $this->$getter();
    } elseif (method_exists($this, 'set' . $name)) {
        throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name);
    }
    throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
}
            
        定义于: yii\base\BaseObject::__isset()
检查属性是否已设置,即定义且不为 null。
不要直接调用此方法,因为它是一个 PHP 魔术方法,在执行 isset($object->property) 时会隐式调用。
请注意,如果未定义属性,则将返回 false。
| public boolean __isset ( $name ) | ||
| $name | string | 属性名称或事件名称 | 
| 返回值 | boolean | 命名的属性是否已设置(非 null)。 | 
|---|---|---|
                public function __isset($name)
{
    $getter = 'get' . $name;
    if (method_exists($this, $getter)) {
        return $this->$getter() !== null;
    }
    return false;
}
            
        定义于: yii\base\BaseObject::__set()
设置对象属性的值。
不要直接调用此方法,因为它是一个 PHP 魔术方法,在执行 $object->property = $value; 时会隐式调用。
另请参阅 __get()。
| public void __set ( $name, $value ) | ||
| $name | string | 属性名称或事件名称 | 
| $value | mixed | 属性值 | 
| 抛出 | yii\base\UnknownPropertyException | 如果未定义属性 | 
|---|---|---|
| 抛出 | yii\base\InvalidCallException | 如果属性是只读属性 | 
                public function __set($name, $value)
{
    $setter = 'set' . $name;
    if (method_exists($this, $setter)) {
        $this->$setter($value);
    } elseif (method_exists($this, 'get' . $name)) {
        throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name);
    } else {
        throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name);
    }
}
            
        定义于: yii\base\BaseObject::__unset()
将对象属性设置为 null。
不要直接调用此方法,因为它是一个 PHP 魔术方法,在执行 unset($object->property) 时会隐式调用。
请注意,如果属性未定义,则此方法不会执行任何操作。如果属性为只读,则会抛出异常。
| public void __unset ( $name ) | ||
| $name | string | 属性名称 | 
| 抛出 | yii\base\InvalidCallException | 如果属性为只读。 | 
|---|---|---|
                public function __unset($name)
{
    $setter = 'set' . $name;
    if (method_exists($this, $setter)) {
        $this->$setter(null);
    } elseif (method_exists($this, 'get' . $name)) {
        throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '::' . $name);
    }
}
            
        处理所有者的 'afterFind' 事件,确保属性类型转换。
| public void afterFind ( $event ) | ||
| $event | yii\base\Event | 事件实例。 | 
                public function afterFind($event)
{
    $this->typecastAttributes();
    $this->resetOldAttributes();
}
            
        处理所有者的 'afterInsert' 和 'afterUpdate' 事件,确保属性类型转换。
| public void afterSave ( $event ) | ||
| $event | yii\base\Event | 事件实例。 | 
                public function afterSave($event)
{
    $this->typecastAttributes();
}
            
        处理所有者的 'afterValidate' 事件,确保属性类型转换。
| public void afterValidate ( $event ) | ||
| $event | yii\base\Event | 事件实例。 | 
                public function afterValidate($event)
{
    if (!$this->owner->hasErrors()) {
        $this->typecastAttributes();
    }
}
            
        | public void attach ( $owner ) | ||
| $owner | yii\base\Component | 要将此行为附加到的组件。 | 
                public function attach($owner)
{
    parent::attach($owner);
    if ($this->attributeTypes === null) {
        $ownerClass = get_class($this->owner);
        if (!isset(self::$_autoDetectedAttributeTypes[$ownerClass])) {
            self::$_autoDetectedAttributeTypes[$ownerClass] = $this->detectAttributeTypes();
        }
        $this->attributeTypes = self::$_autoDetectedAttributeTypes[$ownerClass];
    }
}
            
        处理所有者的 'beforeInsert' 和 'beforeUpdate' 事件,确保属性类型转换。
| public void beforeSave ( $event ) | ||
| $event | yii\base\Event | 事件实例。 | 
                public function beforeSave($event)
{
    $this->typecastAttributes();
}
            
        定义于: yii\base\BaseObject::canGetProperty()
返回一个值,指示是否可以读取属性。
如果属性可读,则
- 类具有与指定名称关联的 getter 方法(在这种情况下,属性名称不区分大小写);
- 类具有与指定名称相同的成员变量(当 $checkVars为 true 时);
另请参阅 canSetProperty()。
| public boolean canGetProperty ( $name, $checkVars = true ) | ||
| $name | string | 属性名称 | 
| $checkVars | boolean | 是否将成员变量视为属性 | 
| 返回值 | boolean | 属性是否可读 | 
|---|---|---|
                public function canGetProperty($name, $checkVars = true)
{
    return method_exists($this, 'get' . $name) || $checkVars && property_exists($this, $name);
}
            
        定义于: yii\base\BaseObject::canSetProperty()
返回一个值,指示是否可以设置属性。
如果属性可写,则
- 类具有与指定名称关联的 setter 方法(在这种情况下,属性名称不区分大小写);
- 类具有与指定名称相同的成员变量(当 $checkVars为 true 时);
另请参阅 canGetProperty()。
| public boolean canSetProperty ( $name, $checkVars = true ) | ||
| $name | string | 属性名称 | 
| $checkVars | boolean | 是否将成员变量视为属性 | 
| 返回值 | boolean | 属性是否可写 | 
|---|---|---|
                public function canSetProperty($name, $checkVars = true)
{
    return method_exists($this, 'set' . $name) || $checkVars && property_exists($this, $name);
}
            
        ::class。
                定义于: yii\base\BaseObject::className()
返回此类的完全限定名称。
| public static string className ( ) | ||
| 返回值 | string | 此类的完全限定名称。 | 
|---|---|---|
                public static function className()
{
    return get_called_class();
}
            
        清除所有受影响的所有者类上自动检测到的 $attributeTypes 值的内部静态缓存。
| public static void clearAutoDetectedAttributeTypes ( ) | 
                public static function clearAutoDetectedAttributeTypes()
{
    self::$_autoDetectedAttributeTypes = [];
}
            
        定义于: yii\base\Behavior::detach()
将行为对象从组件分离。
默认实现将取消设置 $owner 属性并分离在 events() 中声明的事件处理程序。如果您覆盖此方法,请确保调用父实现。
| public void detach ( ) | 
                public function detach()
{
    if ($this->owner) {
        foreach ($this->_attachedEvents as $event => $handler) {
            $this->owner->off($event, is_string($handler) ? [$this, $handler] : $handler);
        }
        $this->_attachedEvents = [];
        $this->owner = null;
    }
}
            
        根据所有者验证规则为 $attributeTypes 组成默认值。
| protected array detectAttributeTypes ( ) | ||
| 返回值 | array | 属性类型映射。 | 
|---|---|---|
                protected function detectAttributeTypes()
{
    $attributeTypes = [];
    foreach ($this->owner->getValidators() as $validator) {
        $type = null;
        if ($validator instanceof BooleanValidator) {
            $type = self::TYPE_BOOLEAN;
        } elseif ($validator instanceof NumberValidator) {
            $type = $validator->integerOnly ? self::TYPE_INTEGER : self::TYPE_FLOAT;
        } elseif ($validator instanceof StringValidator) {
            $type = self::TYPE_STRING;
        }
        if ($type !== null) {
            $attributeTypes += array_fill_keys($validator->getAttributeNames(), $type);
        }
    }
    return $attributeTypes;
}
            
        声明 $owner 事件的事件处理程序。
子类可以覆盖此方法来声明应将哪些 PHP 回调附加到 $owner 组件的事件。
当行为附加到所有者时,回调将附加到 $owner 的事件;当行为从组件分离时,它们将从事件分离。
回调可以是以下任何一种
- 此行为中的方法:'handleClick',等效于[$this, 'handleClick']
- 对象方法:[$object, 'handleClick']
- 静态方法:['Page', 'handleClick']
- 匿名函数:function ($event) { ... }
以下是一个示例
[
    Model::EVENT_BEFORE_VALIDATE => 'myBeforeValidate',
    Model::EVENT_AFTER_VALIDATE => 'myAfterValidate',
]
| public 数组 events ( ) | ||
| 返回值 | array | 事件(数组键)和对应的事件处理程序方法(数组值)。 | 
|---|---|---|
                public function events()
{
    $events = [];
    if ($this->typecastAfterValidate) {
        $events[Model::EVENT_AFTER_VALIDATE] = 'afterValidate';
    }
    if ($this->typecastBeforeSave) {
        $events[BaseActiveRecord::EVENT_BEFORE_INSERT] = 'beforeSave';
        $events[BaseActiveRecord::EVENT_BEFORE_UPDATE] = 'beforeSave';
    }
    if ($this->typecastAfterSave) {
        $events[BaseActiveRecord::EVENT_AFTER_INSERT] = 'afterSave';
        $events[BaseActiveRecord::EVENT_AFTER_UPDATE] = 'afterSave';
    }
    if ($this->typecastAfterFind) {
        $events[BaseActiveRecord::EVENT_AFTER_FIND] = 'afterFind';
    }
    return $events;
}
            
        定义于: yii\base\BaseObject::hasMethod()
返回一个值,指示方法是否已定义。
默认实现是调用 php 函数 method_exists()。当您实现了 php 魔术方法 __call() 时,您可以覆盖此方法。
| public 布尔值 hasMethod ( $name ) | ||
| $name | string | 方法名称 | 
| 返回值 | boolean | 方法是否已定义 | 
|---|---|---|
                public function hasMethod($name)
{
    return method_exists($this, $name);
}
            
        定义于: yii\base\BaseObject::hasProperty()
返回一个值,指示属性是否已定义。
如果满足以下条件,则属性被定义为
- 类具有与指定名称关联的 getter 或 setter 方法(在这种情况下,属性名称不区分大小写);
- 类具有与指定名称相同的成员变量(当 $checkVars为 true 时);
另请参阅
| public 布尔值 hasProperty ( $name, $checkVars = true ) | ||
| $name | string | 属性名称 | 
| $checkVars | boolean | 是否将成员变量视为属性 | 
| 返回值 | boolean | 属性是否已定义 | 
|---|---|---|
                public function hasProperty($name, $checkVars = true)
{
    return $this->canGetProperty($name, $checkVars) || $this->canSetProperty($name, false);
}
            
        | public void init ( ) | 
                public function init()
{
}
            
        重置命名属性的旧值。
| protected void resetOldAttributes ( ) | 
                protected function resetOldAttributes()
{
    if ($this->attributeTypes === null) {
        return;
    }
    $attributes = array_keys($this->attributeTypes);
    foreach ($attributes as $attribute) {
        if ($this->owner->canSetOldAttribute($attribute)) {
            $this->owner->setOldAttribute($attribute, $this->owner->{$attribute});
        }
    }
}
            
        根据 $attributeTypes 对所有者属性进行类型转换。
| public void typecastAttributes ( $attributeNames = null ) | ||
| $attributeNames | array|null | 应该进行类型转换的属性名称列表。如果此参数为空,则表示应转换 $attributeTypes 中列出的任何属性。 | 
                public function typecastAttributes($attributeNames = null)
{
    $attributeTypes = [];
    if ($attributeNames === null) {
        $attributeTypes = $this->attributeTypes;
    } else {
        foreach ($attributeNames as $attribute) {
            if (!isset($this->attributeTypes[$attribute])) {
                throw new InvalidArgumentException("There is no type mapping for '{$attribute}'.");
            }
            $attributeTypes[$attribute] = $this->attributeTypes[$attribute];
        }
    }
    foreach ($attributeTypes as $attribute => $type) {
        $value = $this->owner->{$attribute};
        if ($this->skipOnNull && $value === null) {
            continue;
        }
        $this->owner->{$attribute} = $this->typecastValue($value, $type);
    }
}
            
        将给定值转换为指定类型。
| protected 混合 typecastValue ( $value, $type ) | ||
| $value | mixed | 要进行类型转换的值。 | 
| $type | 字符串|可调用 | 类型名称或类型转换可调用。 | 
| 返回值 | mixed | 类型转换结果。 | 
|---|---|---|
                protected function typecastValue($value, $type)
{
    if (is_scalar($type)) {
        if (is_object($value) && method_exists($value, '__toString')) {
            $value = $value->__toString();
        }
        switch ($type) {
            case self::TYPE_INTEGER:
                return (int) $value;
            case self::TYPE_FLOAT:
                return (float) $value;
            case self::TYPE_BOOLEAN:
                return (bool) $value;
            case self::TYPE_STRING:
                if (is_float($value)) {
                    return StringHelper::floatToString($value);
                }
                return (string) $value;
            default:
                throw new InvalidArgumentException("Unsupported type '{$type}'");
        }
    }
    return call_user_func($type, $value);
}
            
        
注册 或 登录 以发表评论。