0

Am returning data to a rest api and i would like to return both the attributes an the related attributes

This is what i have

$query = User::find()->joinWith('role');

When i perform

var_dump($query->all())

I get an array of the form (attributes and related attributes)

  [1]=>
 object(common\models\User)#119 (10) {
  ["_attributes":"yii\db\BaseActiveRecord":private]=>
array(18) {
  ["id"]=>
  int(27)
  ["username"]=>
  string(8) "marshal2"
  ["email"]=>
  string(18) "marshal2@gmail.com"
 }

["_related":"yii\db\BaseActiveRecord":private]=>
array(1) {
  ["role"]=>
  object(common\rbac\models\Role)#131 (8) {
    ["_attributes":"yii\db\BaseActiveRecord":private]=>
    array(3) {
      ["item_name"]=>
      string(23) "Tracking center officer"
      ["user_id"]=>
      int(27)

    }

  }
}

} ...

When passing the result to a json output via

return ['data' => $query->all()];

Only the attributes are passed but the related are not passed That is i get

"data": [
{
  "username": "admin",
  "email": "track.yard@gmail.com",

},
{
  //also id
  "username": "marshal1",
  "email": "marshal1@gmail.com",
  ..... and others

  //i expected to see a role name since there is a related attribute with user id
},

What do i need to add so that the related attributes are also passed as i expect the data also to show role item name

This is my user model

    public $role;

public function rules()
{
    return [
        [['username', 'email'], 'filter', 'filter' => 'trim'],
        [['username','expires_on', 'email', 'status'], 'required'],
        ['email', 'email'],
       // ['expires_on', 'integer'],
        [['username','first_name','last_name','firebase_pwd','picture'], 'string', 'min' => 2, 'max' => 255],

        // password field is required on 'create' scenario
        ['password', 'required', 'on' => 'create'],
        // use passwordStrengthRule() method to determine password strength
        $this->passwordStrengthRule(),

        ['username', 'unique', 'message' => 'This username has already been taken.'],
        ['email', 'unique', 'message' => 'This email address has already been taken.'],
    ];
}

   public function fields()
{
    $fields = parent::fields();

    // remove fields that contain sensitive information
    unset($fields['auth_key'], $fields['password_hash'],
        $fields['password_reset_token'],
        $fields['created_at'],
        $fields['firebase_pwd'],
        $fields['updated_at'],
        $fields['id'],
        $fields['authtoken'],
        $fields['account_activation_token']
    );

    $fields['role'] =function ($model){ //added this to see if it'll work
        return $model->role->name;
    };


   return $fields;
}

The relationship still in the user model

    public function getRole()
{
    // User has_one Role via Role.user_id -> id
    return $this->hasOne(Role::className(), ['user_id' => 'id']);
}

enter code here
Geoff
  • 6,277
  • 23
  • 87
  • 197

4 Answers4

2

Use eager loading on the join and use asArray() to return the data as an array:

$query = User::find()->with('role')->asArray();

or

$query = User::find()->joinWith('role', true)->asArray();
topher
  • 14,790
  • 7
  • 54
  • 70
0

You can set the response i JSON format

 \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
 $items = $query->all();
 return ['data' => $items];

or encode in php

$my_json = json_encode($items);

echo $my_json;
ScaisEdge
  • 131,976
  • 10
  • 91
  • 107
0

All you need to do is using asArray().

Example:

$users = User::find()->with('role')->asArray()->all();
Bohdan Vorona
  • 685
  • 1
  • 13
  • 26
0

You can receive result to array and return same how said @topher. Or you can wrap up toArray.

ArrayHelper::toArray(User::find()->with('role')->all(), [ //or your namespace model 'common\models\User' => ArrayHelper::merge( User::attributes(), ['role' => function($model) { return $model->role; }] ) ])

With this method you've an opportunity to setting return result.

ArrayHelper::toArray(User::find()->all(), [ //or your namespace model 'common\models\User' => [ 'id', 'username' ], ])

Converting Objects to Arrays

P.S It happens because response preparing with rest serializer and it uses only one layer from model.

gud3
  • 555
  • 3
  • 10