relations access problem

Hello,

I already asked this question in the feature requests subforum without an answer.

Now i'm wondering if i'm just doing something wrong.

I have a model with an database field foo_id and a relation 'foo'. I set foo_id to a valid id which exists in the related table, but I can't access model->foo.

Any hints?

Thanks in advance,

mh

hi mh,

could you please provide the relations you've declared in your model and some example ?

8)



class z extends CActiveRecord {


    public static function model($className=__CLASS__) {


        return parent::model($className);


    }


    public function tableName() {


        return 'zertifikat';


    }


    public function relations() {


        return array(


            'teilnehmer' => array(self::BELONGS_TO, 'teilnehmer','teilnehmer_id'),


        );


    }


}




        $a = z::model();


        $teilnehmer = teilnehmer::model()->find();


        $a->teilnehmer_id = $teilnehmer->te_id;


        echo $a->teilnehmer_id; // 1


        echo $teilnehmer->te_id; // 1


        echo $a->teilnehmer->te_id; // Trying to get property of non-object


try :

<?php 


$result=z::model()->find();


echo $result->teilnehmer->te_id;


?>

8)

That's not really what I want to do, just wondering why my simple approach won't work.

I think the model has all the information it needs in order to pull in the related model.

Also, my "real" code is in the beforeSave() method, can't really switch the model there.

You should not modify data in z::model(). It is mainly served as a finder instance. Also, it is not good practice to try to bring in related objects for a new record. Why not just do a find() with the FK value?

Quote

You should not modify data in z::model().

okay, changed that to a "new z".

Quote

Also, it is not good practice to try to bring in related objects for a new record.

Why is it not good practice?

Btw, my use case: I create my model, fill it with data, then i want to generate and store a pdf in beforeSave().

Quote

Why not just do a find() with the FK value?

I feel that is unneccessary complicated.

It seems logical to me to access the models' attributes and find it awkward to get a null for a->teilnehmer.

After all, you could use find() everywhere instead of using relations (with lazy loading) - it's just inconvenient.

The fact is that you have a new record and you are expecting to bring back its related objects. This does not reflect what you have in the database.

echo $a->teilnehmer_id;

also does not reflect what is in the database, still I can access it.

I think this is a inconsistency ("->teilnehmer_id" saying there IS a related object, "->teilnehmer" saying there is NO related object) - either I should be able to access teilnehmer_id AND teilnehmer, or neither. As the latter of course is a bad idea, both should work.

I think of models as database-backed objects, not just as templates for rows in the database. For that reason I believe operations on them should work the same no matter if they are save()d or not.

$a is not in the database but the teilnehmer_id is set locally. The access of the relations is thru' DB.

The relation in your code doesn't exist in fact. You can add the relation by "addRelatedRecord"

Did you try to save "$teilnehmer" first? just before "echo $a->teilnehmer->te_id;"

Paul

Quote

Did you try to save "$teilnehmer" first?

teilnehmer is saved, else i would not have the teilnehmer id.

More confusion ensues:



        $a = z::model()->findByPK(3);


        echo $a->teilnehmer_id; // 1


        echo $a->teilnehmer->te_id; // 1


        $teilnehmer = (teilnehmer::model()->findByPK(3));


        $a->teilnehmer_id = $teilnehmer->te_id;


        echo $teilnehmer->te_id; // 3


        echo $a->teilnehmer_id; // 3


        echo $a->teilnehmer->te_id; // 1 - unexpected #1 (as discussed)


        echo $a->save(false)?"s":"f"; // s


        echo $a->teilnehmer_id; // 3


        echo $a->teilnehmer->te_id; // 1 - unexpected #2!


        $a = z::model()->findByPK(3);


        echo $a->teilnehmer_id; // 3


        echo $a->teilnehmer->te_id; // 3


results in

[pre]11331s3133[/pre]

Even after save(), the relation is not updated (note that that is indeed "what i have in the database"). I have to pull the object from the database again to see the changed relation.

I think you get a little confused here. You can either

  1. Set teilnehmer_id and save the record:
<?php


$a=z::model()->findByPk(3);


$a->teilnehmer_id=$someId;


$a->save();
  1. Fetch the record and access related teilnehmer:
<?php


$a=z::model()->findByPk(3);


echo $a->teilnehmer->te_id;


And yes, you have to fetch the record again, if you change the relation.

I understand what is currently possible and what isnt, thats what my last post should show.

I just wonder why that is needed:

Quote

And yes, you have to fetch the record again, if you change the relation.

If I unterstand corretly this only applies to belongs_to relations.

Current situation:

Problem 1: after creating new AR instance and setting foreign key -> related object cannot be accessed

Problem 2: after finding existing AR instance, accessing related object, changing foreign key and saving the record -> wrong related object is returned.

If the related object is not accessed before saving, then after saving the correct one is returned.

I think it would be a great improvement if at least problem 2 was fixed.

Fixing problem 1 would also be nice.

Qiang, can you say more to this issue?

  1. Because the record is new, it does not make sense to bring in related objects since the record is not in the database yet.

  2. This would require detection of the change to an attribute. It is better to do this manually rather than relying on some automagic implementation.

Then Yii fails to provide the expected behavior. Whenever a foreign key gets changed, the related object should be dropped and then reloaded accordingly.