Juke Juke - 1 year ago 34
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.