Q: How to override result of hasMany relationship? Imagine I have a couple of simple objects like this:
<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{

    public function posts()
    {
        return $this->hasMany("App\Post");
    }
}

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo("App\User");
    }
}

We'll say the \App\Post object has an database column called jsondata which contains JSON-encoded data. When I want to display the user's posts in a view with that column decoded, I need to do this in the controller:
$posts = Auth::user()->posts()->get();
foreach ($posts as $post) {
    $post->jsondata = json_decode($post->jsondata);
}
return view("user.show", ["posts"=>$posts]);

Is there a way to avoid that foreach loop in my controller and do the JSON decoding at a lower level?
I'm sure I could do this in App\User::posts() but that doesn't help other places where I need to display the decoded data. I tried defining App\Post::get() to override the parent method, but it doesn't work because hasMany() doesn't seem to return an instance of the model at all.

A: It can be done in different places/ways, but I would suggest to use an append for this property in your model if you want this data is always decoded everywhere and every time you retrieve a Post model, or simply a mutator.
see https://laravel.com/docs/master/eloquent-mutators
In your model you can define:
protected $appends = [
    'name_of_property'
];

// calculated / mutated field
public function getNameOfPropertyAttribute()
{
    return jsondecode($this->jsondata);
}

You then can always access this property with:
$post->name_of_property
Note the conversion from CamelCase to snake_case and the conversion from getNameOfPropertyAttribute > name_of_property. By default you need to respect this convention to get it working automagically.
You can substitute the name_of_property and NameOfProperty with what you want accordingly.
Cheers

A: Alessandro's answer seemed like the best one; it pointed me to the Laravel documentation on accessors and mutators. But, near the bottom of the page is an even easier method: attribute casting.
In typical Laravel fashion, they don't actually list all the types you can cast to, but they do mention being able to cast a JSON-formatted database column to an array. A little poking through the source and it turns out you can do the same with an object. So my answer, added to the App\Post controller, is this:
/**
 * The attributes that should be casted to native types.
 *
 * @var array
 */
protected $casts = ["jsondata"=>"object"];

This automatically does the decode and makes the raw data available. As a bonus, it automatically does a JSON encode when saving!
