How to Save JSON Data in Database in Laravel (With Example)

Using JSON typed data in a Laravel database provides a flexible solution for saving dynamic attributes or unstructured data for any purpose In this tutorial, we will walk through the process of creating migration and model to use a JSON typed data structure om a Laravel database, using a practical example of storing product attributes.

By the end of this tutorial, you will have a clear understanding of how to store and retrieve JSON data efficiently using Laravel.

Let’s get started!

Step 1: Setting up a Laravel Project

Create a new Laravel project using the following command:

laravel new json-data-storage

Step 2: Creating the Products Table Migration

Generate a migration file to create the products table using the command:

php artisan make:migration create_products_table --create=products

Inside the generated migration file, define the table schema with a JSON column for the attributes:

database/migrations/2023_06_21_192057_create_products_table.php
<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->json('attributes');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

Step 3: Running the Migration

Now run the migration using the following command:

php artisan migrate

Step 4: Creating the Product Model

Now let’s generate a Product model using the command:

php artisan make:model Product

Afterwards open the Product model (app/Models/Product.php) and add the $casts property and use it to specify that the property “attributes” should be treated as JSON:

app/Models/Product.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;

    protected $casts = [
        'attributes' => 'json',
    ];
}

Step 5: Storing Product Attributes as JSON

To store product attributes as JSON, we can simply use Laravel’s Eloquent model. Create a new Product instance, set the desired attributes as an array, and save it:

use App\Models\Product;

$product = new Product;
$product->attributes = [
    'color' => 'red',
    'size' => 'medium',
    'weight' => 0.5,
];
$product->save();

Step 6: Retrieving JSON Data

To retrieve the attributes of a product, you can access the attributes property on the model:

$product = Product::find(1);
$attributes = $product->attributes;

If you want to access a specific attribute within the JSON data, you can do so by using array access:

$color = $product->attributes['color'];

By accessing the attributes property, you can retrieve the JSON data associated with the product and access specific attributes as needed.

Step 7: Manipulating JSON Data (Full Array)

To update all the attributes of the product at once, you can assign a new array with all the key-value pairs and use Eloquent’s save() method to update the record directly.

$product = \App\Models\Product::find(1);
$product->attributes = [
    'color' => 'green',
    'size' => 'large',
    'weight' => 2.5,
];
$product->save();

Step 8: Manipulating JSON Data (One Value)

Updating a single value within the JSON data requires a slightly different approach in Laravel and has one important caveat. Directly modifying the attribute like $product->attributes['weight'] = 1.0 and saving the product will result in an ErrorException: “Indirect modification of overloaded property App\Models\Product::$attributes has no effect.”

To overcome this issue, you can follow the solution below:

$product = \App\Models\Product::find(1);
$attributes = $product->attributes; // create a copy of the array
$attributes['weight'] = 0.6; // modify the value in the copied array
$product->attributes = $attributes; // assign the copied array back to $product->attributes
$product->save();

Conclusion

Storing JSON typed columns in a database table using Laravel provides flexibility and convenience when working with dynamic or unstructured data.

By following the steps outlined in this tutorial, you have learned how to create the necessary migrations and models, store and retrieve JSON data, and manipulate the JSON data efficiently. This knowledge opens up possibilities for saving complex data structures.

Tip: If you are looking to search a JSON typed column read: How to Search in a JSON Column Using Eloquent

Now you can use these JSON typed columns in your Laravel migrations and models to support any kind custom unstructured data. Happy coding!

References:

This entry is part 1 of 3 in the series Automatic Casting With Eloquent $casts

  1. How to Save JSON Data in Database in Laravel (With Example)
  2. How to Encrypt and Decrypt Model Data Using Casts in Laravel
  3. How to Search a JSON Column Using Laravel Eloquent

Johan van den Broek

Johan is the creator of laracoding.com. As a child, he began tinkering with various programming languages, many of which have been long forgotten today. Currently, he works exclusively with PHP and Laravel, and his passion for programming remains to this day.

6 thoughts on “How to Save JSON Data in Database in Laravel (With Example)

    1. That’s an excellent question, thank you for asking 🙂

      To search array data encoded in a json column using Eloquent one can use Model::whereJsonContains(‘column’, [‘key’ => ‘value’]). For example when searching for products which are of green color, you can simply use:
      Product::whereJsonContains('attributes', ['color' => 'green'])->get();

      1. You could also do
        Product::where(‘attributes.colour’,’green’)->get()
        Just be aware for larger projects that using eloquent for searching on a json column in the database is a quite expensive request.

        Therefore most of the time json columns should only be used for data that you need to have but aren’t going to search for directly.

        Most of the time I personally make a separate database table with a relation in case I need to search on some sort of metadata ????

        1. Thank you for pointing this out and adding a word of caution. In most cases json columns indeed can and should be avoided in favor of relational tables with normalized columns.

  1. Why cast to json and not cast to array.
    I don’t see the advantage of doing it like that.

    1. Although it’s not obvious, using the cast ‘json’ or ‘array’ are equivalent in Eloquent. I checked in the Laravel 10 sourcecode. One might prefer ‘array’ over ‘json’ as it might be more descriptive of what it does. Check out:
      https://laravel.com/docs/10.x/eloquent-mutators#array-and-json-casting
      https://github.com/illuminate/database/blob/master/Eloquent/Concerns/HasAttributes.php#L768

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Posts