十五、AR数据库操作CRUD 之update

本文详细介绍了在Yii框架中如何使用Active Record (AR) 模式进行数据更新操作,包括实例化模型、主键查找、修改字段及保存等过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们来看看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

<div class="form">
 
<?php $form=$this->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,
        ),
)); ?>
 
    <p class="note">Fields with <span class="required">*</span> are required.</p>
 
    <?php echo $form->errorSummary($model); ?>
 
    <div class="row">
        <?php echo $form->labelEx($model,'username'); ?>
        <?php echo $form->textField($model,'username',array('style'=>'height:25px;')); ?>
        <?php echo $form->error($model,'username'); ?>
    </div>
 
    <div class="row">
        <?php echo $form->labelEx($model,'city_id'); ?>
        <?php echo $form->dropDownList($model,'city_id',User::getCitys(),array('prompt'=>'请选择','style'=>'height:25px;width:100px;')); ?>
        <?php echo $form->error($model,'city_id'); ?>
    </div>
 
    <div class="row buttons">
        <?php echo CHtml::submitButton($model->isNewRecord?'添加':'修改',array('style'=>'width:60px;height:30px;')); ?>
    </div>
 
<?php $this->endWidget(); ?>
 
</div><!-- form -->

转载于:https://my.oschina.net/lonxom/blog/168250

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值