1

I have this schema:

enter image description here

and this relation in model zwz:

public function getAuftrs() {
    return $this->hasMany(\app\models\Auftr::className(), ['id' => 'auftr_id'])
        ->viaTable('znw', ['zwzx_id' => 'id'])
        ->viaTable('zwz_expl', ['zwz_id' => 'id'])
;}

in the view of zwz:

<?= count($model->getAuftrs()->asArray()->all())

I'm getting:

PHP Notice – yii\base\ErrorException

Undefined index: auftr_id

  1. in C:...\vendor\yiisoft\yii2\db\ActiveRelationTrait.php

And now if I change the two viaTable()s to:

->via('znws')

and of course define this relation before:

public function getZnws() {
    return $this->hasMany(\app\models\Znw::className(), ['zwzx_id' => 'id'])
        ->viaTable('zwz_expl', ['zwz_id' => 'id'])
;}

then it works. The problem is, that this latter via() way is incompatible with yii2-giiant, so I would like to know what is the difference actually between the two, and how could I keep the original viaTable() way.

github.com/yiisoft/yii2/.../docs/guide/db-active-record.md#chaining-relation-definitions-via-multiple-tables

for me it seems quite clear that we always have to pick the last ID of the chain and define all other IDs backwards. (however in these docs there is via() and not viaTable() and maybe it makes also a difference)

Thanks in advance!

Community
  • 1
  • 1
user2511599
  • 796
  • 1
  • 13
  • 38
  • Can you show us the model of zwz – mrateb Oct 24 '17 at 14:15
  • Actually I think I found the problem. It has nothing to do with via and viaTable. The problem is you are using an index that does not exist in the model. As you are showing, the table that zwz does not have auftr_id. – mrateb Oct 24 '17 at 14:26
  • Can you please tell me how could I define `viaTable()` through multiple tables? What if I don't even have to use multiple `viaTable()`s...? – user2511599 Oct 24 '17 at 14:38
  • I mean as soon as I define the first table via `viaTable()`, I have to define the next in that model and so on...? – user2511599 Oct 24 '17 at 14:45
  • 1
    Can you just try swapping 'auftr_id' and 'id' – mrateb Oct 24 '17 at 14:55
  • I think this will work. – mrateb Oct 24 '17 at 14:56
  • please have a look at this: [github.com/yiisoft/yii2/.../docs/guide/db-active-record.md#chaining-relation-definitions-via-multiple-tables](https://github.com/yiisoft/yii2/blob/c4b3e102dbc35b0db5164ecc104a675f794b4a5b/docs/guide/db-active-record.md#chaining-relation-definitions-via-multiple-tables-) for me it seems quite clear that you always have to pick the last ID of the chain and define all other IDs backwards. (however in these docs there is `via()` and not `viaTable()` and maybe it makes also a difference) – user2511599 Oct 25 '17 at 06:05

1 Answers1

1
  1. You can not use viaTable() twice on the same relation. The second call will overwrite the first one. If you want to go over more than a junction table you need via(). You can however define multiple relations, one of them using via() and the other using viaTable().

  2. I have no idea how giiant works, but it may detect a Many-Many relation through the fact that viaTable() is used. viaTable() in contrast to via() skips one table so you do not need an ActiveRecord for the junction table. With via() you always define direct relations.

  3. About the order of keys in relation definitions, please check the docs at

    http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#declaring-relations

    [...] the link between the two types of data: specifies the column(s) through which the two types of data are related. The array values are the columns of the primary data (represented by the Active Record class that you are declaring relations), while the array keys are the columns of the related data.

    An easy rule to remember this is, as you see in the example above, you write the column that belongs to the related Active Record directly next to it. You see there that customer_id is a property of Order and id is a property of Customer.

cebe
  • 3,610
  • 1
  • 23
  • 37
  • I was having the same idea, that maybe `viaTable()` can be used only once in a relation, but I couldn't figure it out myself. Can it be in the docs included? Or is there a chance to make yii work with multiple `viaTable()`s (when it makes sense)? – user2511599 Oct 25 '17 at 07:39
  • I do not see how you would define a relation with two time viaTable. It would be easier to help you if you'd describe the problem on a higher level. Which entities do you have an how should they be related on a high level from the user view. Your schema looks a bit weird also as there is no Many-Many table that would justify `viaTable()` use, there is no combined primary key. – cebe Oct 25 '17 at 07:44
  • I would define it like in my example above: `zwz` hasMany `Auftr` viaTable('znw'...) viaTable('zwz_expl'...) Is `znw` not a M:M table? I would like only, that giiant generates related data for me. So when I have a look at a `zwz` (view), I would like to be able to see all the related `Auftr`s. Is there something wrong with the idea? – user2511599 Oct 25 '17 at 07:53
  • The M:M table should have the primary key as composite key over the two foreign key columns. As I said, I have no idea how giiant works but the relation definition in Yii must be done using via() if you want to go over more than one table. If you want giiant to understand that, that would probably be a feature request for it. – cebe Oct 25 '17 at 08:03
  • Why is it better (or is it a must?) to have a composite key instead of a single one for yii2? – user2511599 Oct 25 '17 at 08:16
  • There are many other fields also in this table, so it not only two IDs. – user2511599 Oct 25 '17 at 08:28
  • having a composite key will 1. ensure no duplicate relation entries exist, 2. help automatic generation software like giiant to detect a Many-Many relation. (I have no idea whether it does that, but without such a PK it looks like a normal table). – cebe Oct 25 '17 at 08:48