Laravel Database

Use Database Expressions for Dynamic Migration Defaults

Punyapal Shah 2 min read
edit this tip
Pass an Expression instance to Laravel's migration default() method to define raw SQL functions, dynamic timestamps, and calculated defaults directly in your database schema.

In Laravel migrations, passing a scalar string to default() treats the value as a literal string in the generated SQL clause (DEFAULT 'CURRENT_TIMESTAMP'), causing syntax errors when attempting to call SQL functions.

To instruct the database engine to evaluate an SQL function upon insertion, wrap the value in an Illuminate\Database\Query\Expression.


Literal vs Expression

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Facades\Schema;

Schema::create('orders', function (Blueprint $table) {
    $table->id();

    // Static literal (escaped as a string)
    $table->string('status')->default('pending');

    // ❌ Quotes literal string: DEFAULT 'CURRENT_TIMESTAMP'
    // $table->timestamp('placed_at')->default('CURRENT_TIMESTAMP');

    // ✅ Unquoted SQL expression: DEFAULT CURRENT_TIMESTAMP
    $table->timestamp('placed_at')->default(new Expression('CURRENT_TIMESTAMP'));

    // MySQL 8.0+ expressions require enclosing parentheses
    $table->uuid('uuid')->default(new Expression('(UUID())'));
    $table->json('settings')->default(new Expression('(JSON_OBJECT())'));

    // PostgreSQL expressions
    // $table->uuid('id')->primary()->default(new Expression('gen_random_uuid()'));
    // $table->jsonb('preferences')->default(new Expression("'{}'::jsonb"));
});

Key Considerations

  • Engine Evaluation: Defaults set via Expression are evaluated directly by the database engine, ensuring valid fallback values even during raw SQL queries, external ETL scripts, or bulk inserts outside Eloquent.
  • MySQL 8.0+ Syntax: Functional default expressions in MySQL must be enclosed in parentheses (e.g. (UUID()) or (JSON_ARRAY())).
  • Portability: Normal static values ('pending', 0, true) should use standard default('pending') to maintain database-agnostic portability.
Tags: Laravel Migrations Database Eloquent SQL
Share on

// Found an issue or want to contribute a tip? github.com/MrPunyapal/tips