Reputation: 6639
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) "[email protected]"
}
["_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": "[email protected]",
},
{
//also id
"username": "marshal1",
"email": "[email protected]",
..... 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
Upvotes: 0
Views: 1472
Reputation: 565
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'
],
])
P.S It happens because response preparing with rest serializer and it uses only one layer from model.
Upvotes: 0
Reputation: 725
All you need to do is using asArray().
Example:
$users = User::find()->with('role')->asArray()->all();
Upvotes: 0
Reputation: 14860
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();
Upvotes: 3
Reputation: 133370
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;
Upvotes: 0