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

shoxton's avatar

[MIGRATION] Update nullable column to default value

I have a migration that creates a table with the following collumn:

Schema::create('products', function (Blueprint $table) {
	 ...
	$table->boolean('active')->nullable();
	...
});

Now i need this column value to be false by default. So i created another migration to update this column. I tried something like this:

if (Schema::hasColumn('products', 'active')) {
	Schema::table('products', function (Blueprint $table) {
		$table->boolean('active')->default(false)->change();
	});
}

But it doesnt seems to work.

Is it possible to acomplish this?

0 likes
9 replies
sirch's avatar

what's the output of your migration in the console?

Also the table in the first example is products then in the second its videos, is this by design?

shoxton's avatar

Yeah sorry, just updated my question. How can i get the migration output?

shoxton's avatar

Yeah. The example in the docs updates a not nullable column into a nullable column. As pointed here:

We could also modify a column to be nullable:

Schema::table('users', function (Blueprint $table) {
   $table->string('name', 50)->nullable()->change();
});

In my case, i need the opposite thing.

I have a nullable column, that needs to be a not nullable column with a default value.

So, this is what i tried: Turn the nullable column defined in the table creation:

Schema::create('products', function (Blueprint $table) {
  $table->boolean('active')->nullable();
});

into a not nullable column with a default value:

Schema::table('products', function (Blueprint $table) {
  $table->boolean('active')->default(false)->change();
);

But when i try this, the default value doesnt work.

boboboy's avatar

@Tray2 Hello, I have a question. I am successfully to change column with type integer from nullable to set default 0. But, why the value of the changed column still null?

Tray2's avatar

@boboboy I suggest opening a new thread to place your question.

However I assume that you talk about the existing data in your table. The existing data is not changes with a change of the column change. You need to write a script to update the column manually to fit your need.

I also suggest using a timestamp instead of a boolean, and that timestamp should be nullable. So when something is set, it has a timestamp and when it's not, it is null.

Tray2's avatar

Try this

$table->boolean('active')->nullable(false)->change();
$table->boolean('active')->default(false)->change();
1 like
shoxton's avatar

Well, it seems to be working.

But in the test environment, the active field still as null. When i run the following test, the active field value returns as null, and not as false.

public function testProductHasScopeActive()
{

    $this->withoutExceptionHandling();

    $inactiveProducts = Product::factory()->times(10)->create();

    $activeProducts = Product::factory()->times(5)->create(['active' => true]);

    $scopedActive = Product::active()->get();

    $this->assertInstanceOf(\Illuminate\Support\Collection::class, $scopedActive);
    $this->assertCount(5, $scopedActive);
    $this->assertFalse($inactiveProducts->get(0)->active);

}
There was 1 failure:

1) Tests\Feature\Models\ProductTest::testProductHasScopeActive
Failed asserting that null is false.

/.../videos/tests/Feature/Models/ProductTest.php:36

FAILURES!
Tests: 1, Assertions: 3, Failures: 1.


It seems the migration change doesnt work in the test env.

shoxton's avatar
shoxton
OP
Best Answer
Level 2

Ok. I found the issue. I forgot to load a fresh instance of the product. Solved this by adding refresh():

$this->assertFalse($inactiveProducts->get(0)->refresh()->active);

Also set the active attribute to cast as boolean on the Product model: https://stackoverflow.com/a/58939221

protected $casts = [
    'active' => 'boolean',
];

Now the test is passing ✅✅

Turns out the migration was right, i was only missing the refresh() on the test, which was causing the attribute to be null.

Thanks for the help!

Please or to participate in this conversation.