@Snapey Yes, avoiding a bunch of migrations each time I need a new setting was precisely the impetus for going down the json column rabbit hole to begin with! I realize simply adding columns per setting is extremely straight forward either on the users table or a related settings table. But I'm actively building this out and not sure if I need 2 or 25 settings!
I wanted to experiment and see what it would look like to create, update and search where in that json column as that could potentially make using designated columns more attractive.
Note: I'm using Laravel 8
It turns out that it's not all too bad. You have to:
- create
accessors in the model that also handle missing data. (The ?? syntax makes that easy.)
- add nested attributes to $fillable
- cast the json column as an array
User Model:
protected $fillable = [
'name',
'email',
'password',
'settings->background',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'settings' => 'array',
];
public function getBackgroundAttribute()
{
return json_decode($this->attributes['settings'])->background ?? null;
}
Here is how to read and write to the settings JSON column:
//Creating or Updating
$user = Auth::user();
$user->update(['settings->background' => 'dark']);
//Return Settings->background
$background = Auth::user()->background;
//Query Where (Eloquent)
$darkBackgroundUsers = User::whereJsonContains('settings', ['background' => 'dark'])->get();
//Query Where (Query Builder)
$darkBackgroundUsers = DB::table('users')->where('settings->background', 'dark')->get();
I couldn't find much information on using Eloquent with whereJsonContains (for Laravel 8)
Taking a look at the raw queries in telescope I can see this:
Eloquent resolves to:
select * from `users` where json_contains(`settings`, '{\"background\":\"dark\"}')
Query Builder resolves to:
select * from `users` where json_unquote(json_extract(`settings`, '$."background"')) = 'dark'
Hopefully this helps someone else and of course I'm open to ideas here.