Juke Juke - 5 months ago 9
JSON Question

Only get String from hasOne Relation

I have two models:

a) Recipe
b) User

Each Recipe hasOne User. When (REST) requesting a Recipe, I want also get the name of the related User in my JSON answer, like this:

{
"id": 1,
"user_id": 1,
"name": "Recipe Name",
"description": "Description goes here",
"userName": "Testuser"
}


What I get instead is:

{
"id": 1,
"user_id": 1,
"name": "Recipe Name",
"description": "Description goes here",
"userName": "Testuser",
"user": {
"id": 1,
"name": "Testuser",
"email": "mail@example.com"
}
}


This is my function in the RecipeController:

public function show($id) {
$recipe = Recipe::find($id);
$recipe->userName = (string) $recipe->user->name;

return $recipe;
}


My Recipe Model has the following attribute with a getter:

protected $userName = null;

public function setUserName($userName) {
$this->userName = $userName;
}


What is interesting is the fact, that when using this code snipet, I also get the whole User Object as JSON string as part of the Recipe JSON string:

public function show($id) {
recipe = Recipe::find($id);
$recipe->user->name;

return $recipe;
}


So there is some magic happening in the call of my User Object, belonging to the Recipe.

Answer

You have to add your relationships method name to your $hidden property array inside your Recipe model to remove it from json results.

https://laravel.com/docs/5.1/eloquent-serialization#hiding-attributes-from-json

class Recipe extends Model
{
    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = ['user'];

    /**
     * The appended attributes shown in JSON results.
     *
     * @var array
     */
    protected $appends = ['username'];

    /**
     * The username attribute accessor for JSON results.
     *
     * @var string
     */
    public function getUsernameAttribute()
    {
        return $this->user->name;
    }
}

I don't believe there's a way to perform this dynamically besides forming your own set of JSON results.

You could also add the $hidden property to your User model to remove user attributes you want hidden from JSON results? This would allow you to utilize the serialized relationship model without returning sensitive information.

Comments