Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ShadriXs's avatar

Set default value in the migration

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...

0 likes
3 replies
tisuchi's avatar

@shadrixs

The 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: The above castAttribute method will return this same JSON/data for all null JSON columns of your model. It's better to set an empty array here.

1 like
bobbybouwmann's avatar
Level 88

Yeah, this is a tough one! However, there is a workaround for this. You can disable all model events before calling the factory

User::unsetEventDispatcher();

factory(User::class)->create([
    'settings' => json_encode([
        'mail' => [
            'hasNewsletter' => false
        ],
        'time' => [
            'timezone' => ''
        ]   
    ])
]);

If you want to enable it after again, you can do something like this

$dispatcher = User::getEventDispatcher();

User::unsetEventDispatcher();

factory(User::class)->create();

User:: setEventDispatcher($dispatcher);

Let me know if this works for you ;)

1 like

Please or to participate in this conversation.