
正文
Yii2的save()方法容易出错的地方
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
如果save()返回true, 但是数据没有保存成功,则应该是开启了事务且已经回滚
如果save()返回false, 则使用$model->errors查看错误原因
可以设置$model的场景,对具体的场景进行验证; 没有指定场景的验证规则会在所有的场景通用
save()方法有两个参数,第一个参数为是否开启验证,第二个字段为验证的字段,但是会调用beforeBValidate()
源码如下所示:
public function save($runValidation = true, $attributeNames = null)
{
if ($this->getIsNewRecord()) {
return $this->insert($runValidation, $attributeNames);
} else {
return $this->update($runValidation, $attributeNames) !== false;
}
}
public function update($runValidation = true, $attributeNames = null)
{
if ($runValidation && !$this->validate($attributeNames)) {
return false;
}
return $this->updateInternal($attributeNames);
}
public function validate($attributeNames = null, $clearErrors = true)
{
if ($clearErrors) {
$this->clearErrors();
}
if (!$this->beforeValidate()) {
return false;
}
$scenarios = $this->scenarios();
$scenario = $this->getScenario();
if (!isset($scenarios[$scenario])) {
throw new InvalidParamException("Unknown scenario: $scenario");
}
if ($attributeNames === null) {
$attributeNames = $this->activeAttributes();
}
foreach ($this->getActiveValidators() as $validator) {
$validator->validateAttributes($this, $attributeNames);
}
$this->afterValidate();
return !$this->hasErrors();
}
protected function updateInternal($attributes = null)
{
if (!$this->beforeSave(false)) {
return false;
}
$values = $this->getDirtyAttributes($attributes);
if (empty($values)) {
$this->afterSave(false, $values);
return 0;
}
$condition = $this->getOldPrimaryKey(true);
$lock = $this->optimisticLock();
if ($lock !== null) {
$values[$lock] = $this->$lock + 1;
$condition[$lock] = $this->$lock;
}
// We do not check the return value of updateAll() because it's possible
// that the UPDATE statement doesn't change anything and thus returns 0.
$rows = static::updateAll($values, $condition);
if ($lock !== null && !$rows) {
throw new StaleObjectException('The object being updated is outdated.');
}
if (isset($values[$lock])) {
$this->$lock = $values[$lock];
}
$changedAttributes = [];
foreach ($values as $name => $value) {
$changedAttributes[$name] = isset($this->_oldAttributes[$name]) ? $this->_oldAttributes[$name] : null;
$this->_oldAttributes[$name] = $value;
}
$this->afterSave(false, $changedAttributes);
return $rows;
}







