类 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);
}
注册 或 登录 以发表评论。