0

I got stuck on kinda very basic thing and can not move on. I have tables interpret and interpret_member like this (just important data here):

$this->createTable('interpret', [
    'name'      => $this->string(255)->notNull(),
    'PRIMARY KEY (name)'
]);

$this->createTable('interpret_member', [
    'name'      => $this->string(255)->notNull(),
    'interpret' => $this->string(255)->notNull(),
    'PRIMARY KEY (name, interpret)'
]);

$this->createIndex(
    'idx-interpret_member',
    'interpret_member',
    'interpret'
);

$this->addForeignKey('fk-interpret_member', 'interpret_member', 'interpret', 'interpret', 'name', 'CASCADE', 'CASCADE');

Then I have models for both tables generated by gii, so I also have method getInterpretMembers in Interpret model. First I tried to parse its output according to this manual, which gives me an error Trying to get property 'name' of non-object. So I searched here and found this thread. Following that I changed my foreach ($members as $member) to foreach ($members->InterpretMember as $member). That gave me error Getting unknown property: yii\db\ActiveQuery::InterpretMember. The last hope was this thread, but that ended on error Trying to get property 'name' of non-object. The code of last try was:

public function getInterpretMembers()
{
    $members = $this->hasMany(InterpretMember::className(), ['interpret' => 'name']);
    foreach ($members as $member) {
        $member = ArrayHelper::toArray($member, [
            'app\models\user\InterpretMember' => [
                'name',
                'interpret',
                'position'
            ]
        ]);
        echo "Member = {$member->name}<br/>";
    }
    die();
}

I used this code for all attempts, it was just modified according to the mentioned threads and manual.

Erik
  • 303
  • 1
  • 3
  • 12
  • $members = $this->hasMany(InterpretMember::className(), ['interpret' => 'name']); This return an activeQuery and not actualy the data Try $members = $this->hasMany(InterpretMember::className(), ['interpret' => 'name'])->all(); – ustmaestro May 15 '20 at 11:15
  • Omg thank you so much! I don't get why it isn't written like this in manual... Can you write it into the Answer section so I can mark you that as answer? – Erik May 15 '20 at 11:19

2 Answers2

1

The problem is quite simple

$members = $this->hasMany(InterpretMember::className(), ['interpret' => 'name']); 

The hasMany function returns an ActiveQuery instance and not actually the data from DB, so in order to get data you need to call one() or all() function from ActiveQuery instance

$members = $this->hasMany(InterpretMember::className(), ['interpret' => 'name'])->all();

Congratulations, now you will have the data

ustmaestro
  • 1,233
  • 12
  • 20
  • This solution will break the relation definition so you won't be able to use it where you need to work with relations. For example you won't be able to use eager loading with `ActiveQuery::with()` method or use relation to create join with `ActiveQuery::joinWith()`. – Michal Hynčica May 15 '20 at 18:46
  • @MichalHynčica You are right. I just explained the problems with getting data. – ustmaestro May 20 '20 at 12:36
1

You are misunderstanding how relations and ActiveRecord works in Yii2.

What your models should look like.

Interpret model

class Interpret extends \yii\db\ActiveRecord
{
    /**
    * Method that defines the relation. It should
    * return instance of \yii\db\ActiveQuery
    */
    public function getInterpretMembers()
    {
        return $this->hasMany(InterpretMember::class, ['interpret' => 'name']);
    }

    //... other methods
}

InterpretMember model

class InterpretMember extends \yii\db\ActiveRecord
{
    public function getInterpret()
    {
        return $this->hasOne(Interpret::class, ['name' => 'interpret'])
    }
}

This will create property interpretMembers in your Interpret class and property interpret in your InterpretMember class.

To work with it in your controller you can do for example following:

class InterpretController extends \yii\web\Controller
{
    public function actionView()
    {
        //find interpret with name InterpretName
        $interpret = Interpret::findOne('InterpretName');
        //output all members
        foreach ($interpret->interpretMembers as $member) {
            echo "Member = {$member->name}<br/>";
        }
        die();
    }
}

Or if you want to work with members inside of Interpret class:

class Interpret extends \yii\db\ActiveRecord
{
    /**
    * Method that defines the relation. It should
    * return instance of \yii\db\ActiveQuery
    */
    public function getInterpretMembers()
    {
        return $this->hasMany(InterpretMember::class, ['interpret' => 'name']);
    }

    //... other methods

    public function doSomethingWithMembers()
    {
        foreach ($this->interpretMembers as $member) {
            echo "Member = {$member->name}<br/>";
        }
        die();
    }
}
Michal Hynčica
  • 5,038
  • 1
  • 12
  • 24