How CActiveRecord builds list of model attributes used in create scenario?

Following this post. I have a Users model for AUTH table. Table contains DEL column (among others, of course).

For many reasons (explained in above mentioned post) I decided to not use CActiveRecord directly. As in mentioned post, I wrote my own search() function in the model, containing pure SQL, and I use dataset returned by that function to populate my model.

It works this way in update scenario and it works fine.

For create scenario, I use following code:


$model = new Users('create');


if (isset($_POST['Users']))

{

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


    	if($model->validate())

    	{

            	$saveResult = $model->save(FALSE);


            	if($saveResult) $this->redirect(array('index'));

    	}

}

Insertion of a new record, using above code fails, halted by a trigger set on database side, which claims that DEL attribute is null.

To make myself 100% sure, I placed additional code $model->DEL = 0 just above $model->save(FALSE); and I printed out this value on screen. Everything is fine, up to line preceeding [i]save/i model DEL value is set (to zero) and gets nulled somewhere inside save(). I tested this approach with many test cases, providing different, non-zero values as good as other types (i.e. zero as string). All for nothing. Trigger still claims that DEL is null.

I’ve placed PL/SQL function for raising user errors inside trigger and printed out DEL value passed in INSERT query, as good as value of other attributes. Other attributes are set, DEL is null (empty).

Though this doesn’t seems to be related, I’ve put DEL into rules() and into search() SQL. Even though validation is fine and DEL is passed (set) until save() and even though I don’t use search() in creation of a new record (only in updated of existing one and in list of records).

All for nothing. I don’t know, what else I could check?

So, here is the question. Basing on what CActiveRecord builds a list of parameters passed (binded) to INSERT query used in create scenario? Or what else might be causing that this particular column (attribute) is not passed at all or is being nulled before passing?

Seems like you didn’t define DEL attribute into your validation rules (insert, safe or without scenario).

If you could post your model rules, it will much easier to figure out problem.

Let me quote myself:

and:

So, rules() of my model has nothing to do here. No matter, if I had DEL in them or not, I was able to read DEL value just before calling save(). I’m pretty sure that problem lies inside save() method, but I got no idea, why this function is nulling some of model attributes?

And here is my rules() array:


array('LOGN', 'required'),

array('passwordOne', 'compare', 'compareAttribute'=>'passwordTwo', 'message'=>'Hasło musi być podane dwukrotnie identycznie.'),

array('LOGN, IMIE', 'length', 'max'=>20, 'encoding'=>'UTF-8'),

array('NAZW', 'length', 'max'=>40, 'encoding'=>'UTF-8'),

array('OPIS', 'length', 'max'=>70, 'encoding'=>'UTF-8'),

array('LOGN', 'unique'),

array('DEL, IDJNIP, IDODDZ, IDPACJ, TYPA, IDPRAC, OPIS, IDGRUP, perms, permissions, passwordTwo', 'safe'),

array('LOGN', 'parse', 'on'=>'create, update')

DEL is defined in second to end array, as safe on every scenario.

Ok, here what I would check in your case:

  1. Try $model->DEL = new CDbExpression("0") (to prevent yii db typecasting)

  2. Recheck DEL type into db schema (just to be sure that it’s not enum or similar)

  3. Recheck that there are no some beforeSave/afterValidate handlers that set DEL to null somehow

  4. Recheck trigger (to prevent type casting mistakes like IF(DEL = NULL) instead of IF (DEL IS NULL)

Thank you, thank you, thank you! This solved my problem! :] Of course I have no idea, why do I have to use your way instead of simply $model->DEL = 0 and it seems to be some kind of bug in Yii, as for my. But right now, what is important, is the fact, that this is working. Thanks!

Nope. DEL column is definied as NUMBER(1,0) (Oracle).

I’m not using any events nor event-driving programming in this application.

I was not checking type/value of DEL in the trigger, as you showed. Before solving this problem, I was simply throwing DEL column (parameter) value as Oracle exception raisen, no matter, what type or value that column had.