類別 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 | 屬性類型轉換映射,格式為:attributeName => type。 | 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 |
屬性詳細資料
屬性類型轉換映射,格式為:attributeName => type。類型可以透過 PHP 可呼叫函數設定,該函數接受原始值作為參數,並應傳回類型轉換結果。例如:
[
'amount' => 'integer',
'price' => 'float',
'is_active' => 'boolean',
'date' => function ($value) {
return ($value instanceof \DateTime) ? $value->getTimestamp(): (int) $value;
},
]
如果未設定,屬性類型映射將會從擁有者的驗證規則自動組成。
是否跳過對 null
值進行類型轉換。如果啟用,屬性值等於 null
時將不會進行類型轉換(例如,null
保持為 null
),否則將根據 $attributeTypes 中設定的類型進行轉換。
是否在從資料庫檢索擁有者模型資料後(在 find 或 refresh 之後)執行類型轉換。可以停用此選項以獲得更好的效能。例如,在使用 yii\db\ActiveRecord 的情況下,find 之後的類型轉換在大多數情況下不會帶來任何好處,因此可以停用。請注意,在此行為附加到模型後,變更此選項值將不會有任何效果。
是否在儲存擁有者模型之後(插入或更新)執行類型轉換。可以停用此選項以獲得更好的效能。例如,在使用 yii\db\ActiveRecord 的情況下,save 之後的類型轉換在大多數情況下不會帶來任何好處,因此可以停用。請注意,在此行為附加到模型後,變更此選項值將不會有任何效果。
是否在擁有者模型驗證後執行類型轉換。請注意,只有在驗證成功(例如,擁有者模型沒有錯誤)時才會執行類型轉換。請注意,在此行為附加到模型後,變更此選項值將不會有任何效果。
是否在儲存擁有者模型之前(插入或更新)執行類型轉換。可以停用此選項以獲得更好的效能。例如,在使用 yii\db\ActiveRecord 的情況下,save 之前的類型轉換在大多數情況下不會帶來任何好處,因此可以停用。請注意,在此行為附加到模型後,變更此選項值將不會有任何效果。
方法詳情
public mixed __call ( $name, $params ) | ||
$name | string |
方法名稱 |
$params | array |
方法參數 |
return | mixed |
方法傳回值 |
---|---|---|
throws | 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 |
屬性名稱 |
return | mixed |
屬性值 |
---|---|---|
throws | yii\base\UnknownPropertyException |
如果屬性未定義 |
throws | 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 |
屬性名稱或事件名稱 |
return | 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 |
屬性值 |
throws | yii\base\UnknownPropertyException |
如果屬性未定義 |
---|---|---|
throws | 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 |
屬性名稱 |
throws | 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 |
是否將成員變數視為屬性 |
return | 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 |
是否將成員變數視為屬性 |
return | 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 ( ) | ||
return | 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 ( ) | ||
return | 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 的事件的事件處理常式。
子類別可以覆寫此方法,以宣告應附加到 $owner 元件事件的 PHP 回呼。
當行為附加到擁有者時,回呼將附加到 $owner 的事件;當行為從元件分離時,它們將從事件中分離。
回呼可以是以下任何一種:
- 此行為中的方法:
'handleClick'
,等效於[$this, 'handleClick']
- 物件方法:
[$object, 'handleClick']
- 靜態方法:
['Page', 'handleClick']
- 匿名函數:
function ($event) { ... }
以下範例:
[
Model::EVENT_BEFORE_VALIDATE => 'myBeforeValidate',
Model::EVENT_AFTER_VALIDATE => 'myAfterValidate',
]
public array events ( ) | ||
return | 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 boolean hasMethod ( $name ) | ||
$name | string |
方法名稱 |
return | boolean |
方法是否已定義 |
---|
public function hasMethod($name)
{
return method_exists($this, $name);
}
定義於: yii\base\BaseObject::hasProperty()
傳回一個值,指示是否已定義屬性。
屬性被定義如果
- 類別具有與指定名稱相關聯的 getter 或 setter 方法(在這種情況下,屬性名稱不區分大小寫);
- 類別具有具有指定名稱的成員變數(當
$checkVars
為 true 時);
參見
public boolean hasProperty ( $name, $checkVars = true ) | ||
$name | string |
屬性名稱 |
$checkVars | boolean |
是否將成員變數視為屬性 |
return | 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 mixed typecastValue ( $value, $type ) | ||
$value | mixed |
要進行類型轉換的值。 |
$type | string|callable |
類型名稱或類型轉換 callable。 |
return | 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);
}
註冊 或 登入 以進行評論。