mmvsbg
mmvsbg

Reputation: 3588

Yii2 REST API relational data return

I've set up Yii2 REST API with custom actions and everything is working just fine. However, what I'm trying to do is return some data from the API which would include database relations set by foreign keys. The relations are there and they are actually working correctly. Here's an example query in one of the controllers:

$result = \app\models\Person::find()->joinWith('fKCountry', true)
      ->where(..some condition..)->one();

Still in the controller, I can, for example, call something like this:

$result->fKCountry->name

and it would display the appropriate name as the relation is working. So far so good, but as soon as I return the result return $result; which is received from the API clients, the fkCountry is gone and I have no way to access the name mentioned above. The only thing that remains is the value of the foreign key that points to the country table.

I can provide more code and information but I think that's enough to describe the issue. How can I encode the information from the joined data in the return so that the API clients have access to it as well?

Upvotes: 4

Views: 3381

Answers (3)

Ahmad Zahabi
Ahmad Zahabi

Reputation: 1268

use with for Eager loading

$result = \app\models\Person::find()->with('fKCountry')
      ->where(..some condition..)->all();

and then add the attribute 'fkCountry' to fields array

public function fields()
    {
        $fields= parent::fields();
        $fields[]='fkCountry';
        return $fields;
    }

So $result now will return a json array of person, and each person will have attribute fkCountry:{...}

Upvotes: 2

Mcload
Mcload

Reputation: 308

I managed to solve the above problem. Using ActiveDataProvider, I have 3 changes in my code to make it work.

This goes to the controller:

Model::find()
->leftJoin('table_to_join', 'table1.id = table_to_join.table1_id')
->select('table1.*, table_to_join.field_name as field_alias');

In the model, I introduced a new property with the same name as the above alias:

public $field_alias;

Still in the model class, I modified the fields() method:

public function fields()
{
    $fields = array_merge(parent::fields(), ['field_alias']);
    return $fields;
}

This way my API provides me the data from the joined field.

Upvotes: 3

Jap Mul
Jap Mul

Reputation: 18759

Set it up like this

public function actionYourAction() {
    return new ActiveDataProvider([
        'query' => Person::find()->with('fKCountry'), // and the where() part, etc.
    ]);
}

Make sure that in your Person model the extraFields function includes fKCountry. If you haven't implemented the extraFields function yet, add it:

public function extraFields() {
    return ['fKCountry'];
}

and then when you call the url make sure you add the expand param to tell the action you want to include the fkCountry data. So something like:

/yourcontroller/your-action?expand=fKCountry

Upvotes: 6

Related Questions