ActiveRecord mit MANY_MANY

Nehmen wir mal an, ich habe 3 Tabellen:

User

id

username

UserAddress

userId

addressId

name

Address

id

zip

die entsprechenden Relationen

‘addresses’ => array(self::MANY_MANY, ‘Address’, ‘UserAddress(userId, addressId)’)

‘users’ => array(self::MANY_MANY, ‘User’, ‘UserAddress(userId, addressId)’)

funktionieren einwandfrei, z.B. $user->address->zip

Nur wie kann ich jetzt den namen der Relation verwenden, also ‘name’ aus ‘UserAddress’ ?

Dazu brauchst du eine weitere Relation:


'useraddress' => array(self::HAS_MANY, 'UserAddress','userId'),

 

 // Dann:

 $name=$user->useraddress->name

Da gebe ich dir Recht, aber so bekomme ich doch nur ‘irgendeinen’ namen, ich hätte aber gerne den zu einer bestimmten Relation gehörenden Namen.

Beispiel:

User: id: 1 username: mustermann

User: id: 2 username: irgendwas

UserAddress: userId: 1 addressId: 3 name: ‘bei Mutti’

UserAddress: userId: 2 addressId: 3 name: ‘bei Pappi’

Address: id: 3 zip: 12345

beide Personen wohnen also in der gleichen Adresse, nennen sie aber unterschiedlich.

ich hätte dann gerne etwas in der Art:


foreach($model->adresses as $address)

echo CHtml::encode($address->name); // wie auch immer

echo CHtml::encode($address->zip);

endforeach;



spontan würde mir dazu nur ein ‘findByPk()’ in UserAddress mit den beiden IDs einfallen, wass ich aber unschön finde.

Hmm. Da hast du recht. Glaube, dazu gibt es noch keine generelle Lösung. Ein Workaround (zwar nicht unbedingt wunderschön, aber immerhin…) könnte so aussehen:


'useraddress' => array(self::HAS_MANY, 'UserAddress','userId', array('index'=>'addressId')),



Damit werden die UserAddress-Records mit der adressId indiziert (statt 0-basiert). Das geht aber erst seit Version 1.0.7. Du könntest die Adressnamen dann so ansprechen:


// $model ist vermutlich vom Typ 'User' ...

foreach($model->adresses as $address)

echo CHtml::encode($model->useraddress[$adress->id]->name);

echo CHtml::encode($address->zip);

endforeach;



Sehr interessante Sache. So habe ich das auch nicht gewusst.

Vielen Dank, das werde ich mal in Angriff nehmen :)