hzz
- hzz 赞了回答
默认情况下,scenarios() 返回的是一个关系数组,键是模型中所有可用的场景,值是场景对应的 active attributes 列表。active attributes 有两个特点:
- 如 @koko 所说,调用 validate() 时仅会验证 active attributes
- 使用
$model->load() && $model->save()
保存数据时只保存 active attributes;
在你的例子中,把 'age' 从 update 场景中移除意味着 age 不再是 active attribute, 这就是为什么对 age 的修改没有写入数据库的原因。
默认的 scenarios() 过程(以你的例子中声明的规则为例)
scenarios() 会进行两次遍历操作。首先遍历 rules 中声明的规则,把所有可用的场景找出来,并初始化数组,以你的例子中的 rules 为例,值为:
[ 'default' => [], // 框架自带的默认场景 'add' => [], 'update' => [], ]
第二次遍历时,对每个 rule 中声明的 attributes “对号入座”,如果 rule 中不带 'on' 属性,表示该属性所属的规则适用于所有场景(例如
[['age'], 'integer']
), 会将 'age' 追加到所有场景的 active attibutes 列表中;如果指定了场景值,仅在对应的场景下的active attributes 内追加。经过这两次遍历,scenarios() 最终返回的值将是:
[ 'default' => ['age', 'name'], 'add' => ['age', 'name'], 'update' => ['age', 'name'], ]
可以看到, 'age' 在每个场景中都是 active attribute, 这就是为什么在你不重写 scenarios() 的情况下,对 age 的修改也能保存的原因。
了解了这个过程,我的理解是:在大多数情况下,是不需要重写 scenarios() 的,通过配置 rules() 来改变 scenarios() 的返回值,而不是直接手动覆盖 sceanrios(). 覆盖带来的一个明显的弊端是:你的精力被分散到了两个方法内(rules() 和 scenarios()),假设将来你的 info 表又新增了一列,在 rules() 追加新的规则的同时,你还要修改重写后的 scenarios(), 把新增加的列追加进去使其成为 active attribute,否则就会出现新增列的数据无法存入数据库。使用默认的 scenarios() 的话,只需要将精力放在 rules() 上即可。
- hzz 赞了回答
2、你在
update
场景中没有配置age
当前就不能修改了。
yii是照这个清单去一个个校验的,清单上没有的东西,不处理。 - hzz 回复了话题 Yii2 SQL 分页的问题
TableName::find()->where("coloum != 1")->offset($num * 10)->limit(10)->OrderBy("index_id")->all() 试一下,我认为可有能select出来的数据结果发生变化了。
我问下这个是分页之后页面浏览时候是不是有插入或者删除操作?比如插入2条,插入之后count(*)总条数变化了,翻页不会更新,有可能导致有一部分数据拿不到,关掉页面重新打开应该是可以扫到的?不知道是不是这个情况
- hzz 回复了 dingjj2010 的回答
用父类\Exception捕获.
@dingjj2010 确认是innodb的表,但整个db 是 MyISAM的,我怀疑是这个问题,还米有验证。我直接现在手动判断后再save。
- hzz 回复了 dingjj2010 的回答
用父类\Exception捕获.
@YiiNewer
KEYr_coustomer_id
(coustomer_id
)
) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8 ;
我实在没招了。 - hzz 回复了 dingjj2010 的回答
用父类\Exception捕获.
确实是INNODB的。 因为这个是线上的库,数据库默认配置是MyISAM,我还手动把这俩表改成了INNODB引擎。回滚确实没执行,我实在想不出来是啥问题
- hzz 回复了 dingjj2010 的回答
用父类\Exception捕获.
@YiiNewer 可是现在model1中的数据已经插入了。。回滚的话必须删除这条数据,这里的回滚确实没起作用。就是说下边的
$transcation->commit() 也没起作用的时候。 model1->save()已经保存了。 所以这次执行过后数据其实还是出错了 - hzz 回答了问题 用查询构造器查询结果为空的时候能不能不显示空数组
用查询构造器相当于是 yii执行createCommand()的生成SQL然后去数据库里边执行,没数据的时候。sql查出来的肯定是 empty-obj。赋值到$model的时候肯定是空的。
如果要想按照你说的,只能是用empty($result) 判断,然后用全 null 去setAttribute(),得到的model就是空数据 - hzz 回复了 dingjj2010 的回答
用父类\Exception捕获.
@YiiNewer
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
现在确实是innodb的。。但是第一个save()了,throw Exception之后,第一个没回滚。
我出于这样考虑的原因是: $model1->save() 之后,$model2->save()之前,如果model2的rule验证失败。$model2就是empty的。 然后$model2->save()就不会写入了。。但是这个model1和$model2是 关联的 (父-子表),必须同时写入或者同时删除,有没有什么别的思路呢?