Single field in model won't update

I have a form that updates two tables. Every field in the form except one works the way you would expect: when you change the value the new value is written to the table, replacing the old.

But one field doesn’t. No matter what I change, the POST value is returned.

I’ve checked that there is not something wrong with the database: if I change the value manually it is reflected in the form, and there is no obvious issue with datatypes I’ve set it to text and only use text. It should accept null values as well. I’ve looked through the Model and don’t see anything strange in the rules either.

Is does anybody have any suggestions?

Here’s the relevant code bits (I think this is everything):

Model:




	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('article_id, person_id', 'required'),

			array('article_id, person_id, ordinal', 'numerical', 'integerOnly'=>true),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('authorInstance_id, article_id, person_id, type, ordinal', 'safe', 'on'=>'search'),

		);

	}


	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('authorInstance_id',$this->authorInstance_id);

		$criteria->compare('article_id',$this->article_id);

		$criteria->compare('person_id',$this->person_id);

		$criteria->compare('type',$this->type,true); // removing the true has no effect on the problem AFAICS

		$criteria->compare('ordinal',$this->ordinal);


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}



context from _form




	<div class="row">

		<?php echo $form->labelEx($model,'type'); ?>

		<?php echo $form->textField($model,'type'); ?> // this one shows the table content, but doesn't update on save()

		<?php echo $form->error($model,'type'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'ordinal'); ?>

		<?php echo $form->textField($model,'ordinal'); ?> // this updates properly

		<?php echo $form->error($model,'ordinal'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($author,'lastName'); ?>

		<?php echo $form->textField($author,'lastName',array('size'=>25, 'maxlength'=>50)); ?> // this is in a different table but also updates properly

		<?php echo $form->error($author,'lastName'); ?>

	</div>




From controller




	public function actionUpdate($id)

    {

        $model = $this->loadModel($id, 'AuthorInstance');

        $author = $model->person;

        

		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['AuthorInstance'], $_POST['Person']))

		{

			$model->attributes=$_POST['AuthorInstance'];

			$author->attributes=$_POST['Person'];

						

			//$valid=$model->validate();

            //$valid=$author->validate() && $valid;

            $valid=$author->validate();

            $valid=$model->validate() && $valid;

 

            if($valid)  

            {  

                $author->save(false);  

                if ($model->save(false)) //;  // doesn't matter if false is on or off

                //$this->redirect(array('article/view','id'=>$model->article_id));

                {echo $model->type;} // this echoes the unchanged value

            }

        }


        $this->render('create',array(

            'model'=>$model,

            'author'=>$author,

        ));






As I say, the issue is not in the database: I can update the field manually.

Securing Attribute Assignments

Thanks, I never would have thought of that!

To help anybody else with the issue: the problem is that the attribute in question does not appear in the rule() method in the controller that is applicable to the update scenario (or in my case any other scenario other than search). So it is the inverse of the usual problem with gii generated rules: I have a attribute that is supposed to receive user input but which is not found in rules() (when it is autogenerated by gii, rules() includes every attribute in the relevant dbase table and you are supposed to remove the ones that are not going to receive user input; I removed this one (except from search) even though it is supposed to receive user input).

The reason for this is for security.

Lets say that you had a profile form where your users could update fields you choose to display. Email, Address, etc. There is also a field called is_admin in this table.

If this wasn’t built into Yii as part of validation you might have a malicious person craft their own POST response and elevate their authority to admin.