首先我们来看看AR是怎么来操作更新的
我们在控制器中新建一个方法 actionUpdate,将id=7的那行数据
public function actionUpdate($id){// dump($id); $id = trim($id); //找出id符合条件的那一行(主键查找通过findByPk方法) $model = User::model()->findByPk($id);// dump($model); //实现修改操作 $model->username = '张飞'; if(!$model->save()){ dump($model->getErrors()); }else{ dump('修改成功'); } }
我们看到id为7的这行数据username已经变成 ‘张飞’
从update方法的逻辑我们可以看到,要想修改一条数据,需要先找到那条数据对应的AR对象,然后对对象的字段属性进行重新赋值,然后保存
那么这一系列的动作,yii又为我们做了些什么列
User::model()方法
实例化了一个User的单例,并绑定了User类的行为方法
public static function model($className=__CLASS__) { if(isset(self::$_models[$className])) return self::$_models[$className]; else { $model=self::$_models[$className]=new $className(null); $model->attachBehaviors($model->behaviors()); return $model; } }findByPk()方法,第二和第三个参数还可以同时制定其他的查询条件
public function findByPk($pk,$condition='',$params=array()) { Yii::trace(get_class($this).'.findByPk()','system.db.ar.CActiveRecord'); $prefix=$this->getTableAlias(true).'.'; //根据pk值 生成一个查询器对象 $criteria=$this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),$pk,$condition,$params,$prefix); return $this->query($criteria); }
//执行查询protected function query($criteria,$all=false) { $this->beforeFind(); $this->applyScopes($criteria); if(empty($criteria->with)) { if(!$all) $criteria->limit=1; $command=$this->getCommandBuilder()->createFindCommand($this->getTableSchema(),$criteria,$this->getTableAlias()); //创建一个cdbcommand对象,将查询出来的一行数据转成AR对象映射 return $all ? $this->populateRecords($command->queryAll(), true, $criteria->index) : $this->populateRecord($command->queryRow()); } else { $finder=$this->getActiveFinder($criteria->with); return $finder->query($criteria,$all); } }//将查询出来的数组转成对象public function populateRecord($attributes,$callAfterFind=true) { if($attributes!==false) { $record=$this->instantiate($attributes); //设置模型的场景为update $record->setScenario('update'); $record->init(); $md=$record->getMetaData(); foreach($attributes as $name=>$value) { if(property_exists($record,$name)) $record->$name=$value; elseif(isset($md->columns[$name])) $record->_attributes[$name]=$value; } $record->_pk=$record->getPrimaryKey(); $record->attachBehaviors($record->behaviors()); if($callAfterFind) $record->afterFind(); return $record; } else return null; }
在save方法中,通过_new判断对象不是新的记录,所以执行了Update方法
public function update($attributes=null) { if($this->getIsNewRecord()) throw new CDbException(Yii::t('yii','The active record cannot be updated because it is new.')); if($this->beforeSave()) { Yii::trace(get_class($this).'.update()','system.db.ar.CActiveRecord'); if($this->_pk===null) $this->_pk=$this->getPrimaryKey(); $this->updateByPk($this->getOldPrimaryKey(),$this->getAttributes($attributes)); $this->_pk=$this->getPrimaryKey(); $this->afterSave(); return true; } else return false; }
更新和添加用的表单基本是一样的,所以我们通常使用同样的表单视图,如
controller中
public function actionUpdate($id){// dump($id); $id = trim($id); //找出id符合条件的那一行(主键查找通过findByPk方法)// dump(User::model()); $model = User::model()->findByPk($id); $this->performAjaxValidation($model);// dump($model); if(!empty($_POST['User']) && Yii::app()->request->isPostRequest){// dump($_POST); //实现修改操作 $model->attributes = $_POST['User']; if(!$model->save()){ dump($model->getErrors()); }else{ dump('修改成功'); } } $this->render('update',array( 'model'=>$model, )); }
views/user/update.php
beginWidget('CActiveForm', array( 'id'=>'user-active_form-form', // Please note: When you enable ajax validation, make sure the corresponding // controller action is handling ajax validation correctly. // See class documentation of CActiveForm for details on this, // you need to use the performAjaxValidation()-method described there. 'enableAjaxValidation'=>true,// 'enableClientValidation'=>true, 'clientOptions'=>array( 'validateOnSubmit'=>true, 'validateOnChange'=>true, ),)); ?>Fields with * are required.
errorSummary($model); ?>labelEx($model,'username'); ?> textField($model,'username',array('style'=>'height:25px;')); ?> error($model,'username'); ?>labelEx($model,'city_id'); ?> dropDownList($model,'city_id',User::getCitys(),array('prompt'=>'请选择','style'=>'height:25px;width:100px;')); ?> error($model,'city_id'); ?>endWidget(); ?>