Quick Note: Default Value for JSON in Laravel

Many RDBMS today have json data type implemented. MySQL has it since 5.7.8 and PostgreSQL since 9.3. MariaDB, a MySQL-like RDBMS solution, has json as an alias to longtext , that means while MySQL and PostgreSQL can search and validate JSON data, MariaDB does not.

Laravel also supports JSON columns since 5.x. They do not, however, sometimes work as you expect it to be. I ran across a problem about setting a default value for a JSON column and, in this article, I would like to present you how I've solved the issue.

How to Do It

After starting a new Laravel project with laravel new whatever, we need to create an example model with its migrations that we can work on.

php artisan make:model Article -m

This will both generate the model and migration file for us.

Then we write our migration as such:

$table->text("content");  // for the sake of example
$table->json("tags")->default("[]");

The column tags here is a json typed column but here is the catch: It might not work (tested in PostgreSQL). In such cases, you can use a pre-create (creating) hook to set the default value before saving. To do that, we need to open up our model, app/Article.php in this case, and override built-in static booted method of the model:

 protected static function booted() {
     // when the model is loaded
 }

Here we can define any event in lifetime of our model. You can see a list here. In our case, we need to define a creating event as such:

 protected static function booted() {
     static::creating(function ($article) {
         if ($article->tags === null) {
             // if tags are not provided on creation
             $article->tags = "[]";  // set empty json array
         }
     });
 }

Note that we actually check if tags property is null. We need it to be set to empty JSON array only in case we have not provided values by hand on creation.

Also another note is that, on creating event, we do not call any save method or something alike (which is querying the database). It's because we are literally injecting a value to $article instance, which is not yet saved. Laravel will save it after creating event runs.

After this, it will set default value to empty JSON array in database. Thanks for reading.

No Comments Yet