yii\base\DynamicModel 專為「臨時資料驗證」設計,支援動態定義屬性與驗證規則,無需預先建立 Model 類別。本文解析其核心原始碼:屬性儲存、魔術方法、規則添加、靜態驗證入口 validateData()。
private $_attributes = []; // 動態屬性鍵值對
public function __construct(array $attributes = [], $config = []) {
foreach ($attributes as $name => $value) {
if (is_int($name)) $this->_attributes[$value] = null; // 僅名稱
else $this->_attributes[$name] = $value; // 鍵值對
}
parent::__construct($config);
}
_attributespublic function __get($name) {
return array_key_exists($name, $this->_attributes) ? $this->_attributes[$name] : parent::__get($name);
}
public function __set($name, $value) {
if (array_key_exists($name, $this->_attributes)) $this->_attributes[$name] = $value;
else parent::__set($name, $value);
}
public function __isset($name) { return array_key_exists($name, $this->_attributes) ? isset($this->_attributes[$name]) : parent::__isset($name); }
public function __unset($name) { if (array_key_exists($name, $this->_attributes)) unset($this->_attributes[$name]); else parent::__unset($name); }
public function defineAttribute($name, $value = null) { $this->_attributes[$name] = $value; }
public function undefineAttribute($name) { unset($this->_attributes[$name]); }
public function attributes() { return array_keys($this->_attributes); }
addRule()public function addRule($attributes, $validator, $options = []) {
$validators = $this->getValidators();
$validators->append(Validator::createValidator($validator, $this, (array)$attributes, $options));
return $this; // 支援鏈式呼叫
}
validateData()(最常用)public static function validateData(array $data, $rules = []) {
$model = new static($data); // 建立實例並填入屬性
if (!empty($rules)) {
$validators = $model->getValidators();
foreach ($rules as $rule) {
if ($rule instanceof Validator) $validators->append($rule);
elseif (is_array($rule) && isset($rule[0], $rule[1])) {
// 格式:[屬性陣列, 驗證器類型, 選項...]
$validator = Validator::createValidator($rule[1], $model, (array)$rule[0], array_slice($rule, 2));
$validators->append($validator);
} else {
throw new InvalidConfigException('驗證規則必須指定屬性名與驗證器類型');
}
}
}
$model->validate(); // 執行驗證
return $model; // 回傳含錯誤訊息的模型實例
}