Q:

Migration - How to set default value for json? ( MySQL)

I have the problem that I need some values to be already set for my settings json column. 
Let us say I have this in my user migration file:
$table->json('settings');

My goal is to set let us say these values as default:
'settings' => json_encode([
    'mail' => [
        'hasNewsletter' => false
    ],
    'time' => [
        'timezone' => ''
    ]
])

How would you do this? 
My first approach was to set the values in my UserObserver in the created event after the User was created. 
This creates the problem, that my UserFactory is not working correctly.  Because a User is created but the settings values are overwritten by the UserObserver again...

A:

Following solution works with Eloquent Model. 
For default JSON data you can do something like this in your Model
<? php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{

protected $attributes = [
        'settings' => '{
            "mail": {
            "hasNewsletter" : false
            },
            "time": {
            "timezone" : ""
            }
        }'
    ];
}

Then the default value will be {"mail": {"hasNewsletter" : false},"time": {"timezone" :""} in your DB if your input is null.  However the existing values in BD will be unchanged and will have to change manually if you need. 
If you want to keep your existing DB values null (and/or when null) but want to get as the above default json by Eloquent, you can add the following method in the Model:
    protected function castAttribute($key, $value)
    {
        if ($this->getCastType($key) == 'array' && is_null($value)) {
            return '{
                    "mail":{
                        "hasNewsletter":false
                            },
                    "time":{
                         "timezone":""
                           }
                     }';
        }
        return parent::castAttribute($key, $value);
    }

Note: above castAttribute method will return this same json/data for all null json column of your model.  It's better to set empty array here. 
Tested in Laravel 5.8.  
Reference: https://laravel.com/docs/eloquent#default-attribute-values

