dibs_ab
dibs_ab

Reputation: 723

Save and Update in a controller together in Yii

There are two tables in my db, users and profile. Profile has user_id as a primary key. Every user can have only one profile. When I upload a image file its name is stored in profile table with that user_id. When there are other fields to be updated in profile table, I first check whether there is already a record with that user_id. In my Profile model I have written

public function checkForSaveOrUpdate()
{
    return self::model()->findByAttributes(array('user_id'=>Yii::app()->user->id));
}

and my controller file looks something like this

    public function actionCreateInfo()
      {
        $profile = new Profile;
        $profile->user_id = Yii::app()->user->id;

        if(isset($_POST['Profile']))
        {
            if($profile->checkForSaveOrUpdate() === null)
            {
                $profile->attributes = $_POST['Profile'];
                if($profile->save())
                    Yii::app()->user->setFlash('success','Profile has been saved successfully');
            }
            elseif($profile = $profile->checkForSaveOrUpdate())
            {
                $profile->attributes = $_POST['Profile'];
                if($profile->update())
                    Yii::app()->user->setFlash('success','Profile has been updated successfully');
            }

            $this->redirect(array('index'));
        }

        $this->render('createInfo',array('profile'=>$profile));
}

My problem is when I already have a record in database,in profile, and I submit a new form the old data is all deleted and only the current values submitted are updated, whereas it should keep the old values and only update the new ones.

Upvotes: 1

Views: 7895

Answers (3)

clapas
clapas

Reputation: 1846

Your POST data probably includes all model attributes, including those left blank by the user set to the empty string; the empty string is an accepted value for massive assignment unless otherwise stated in the model rules; a massive assignment is what you actually do with $profile->attributes = $_POST['Profile'];.

One solution would be to unset those attributes that you don't want to update, e.g. those containing an empty string, in the controller.

But this kind of rule should be defined in the model and triggered by calling the validate() method, which you are now skipping by calling update(). You better call save() because internally calls validate() as opposed to update().

A rule for a default value is defined like this:

array(
    'attr_name',
    'default',
    'setOnEmpty' => true,
    'value' => null
)

Upvotes: 0

dInGd0nG
dInGd0nG

Reputation: 4114

Change your function to static function

 public static function checkForSaveOrUpdate()
    {
        return self::model()->findByAttributes(array('user_id'=>Yii::app()->user->id));
    }

Then modify action as

public function actionCreateInfo()
{
        $profile = Profile::checkForSaveOrUpdate();
        if($profile===null)
        {
            $profile=new Profile;
            $profile->user_id = Yii::app()->user->id;
        }
        if(isset($_POST['Profile']))
        {
            $profile->attributes = $_POST['Profile'];
            if($profile->save())
                Yii::app()->user->setFlash('success','Profile has been saved successfully');
           $this->redirect(array('index'));
        }

        $this->render('createInfo',array('profile'=>$profile));
}

Upvotes: 0

user1386320
user1386320

Reputation:

If you instaciate the model like:

$model = new YourModel;

you will have the $model->isNewRecord set to true:

var_dump($model->isNewRecord); // true, in this case you use $model->save()

When you find a record, the same property will have the opposite value:

$model = YourModel::model()->findByPk(1);
var_dump($model->isNewRecord); // false - and now you use $model->update(), instead.

Upvotes: 1

Related Questions