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:
<?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:
<?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
- How to Save JSON Data in Database in Laravel (With Example)
- How to Encrypt and Decrypt Model Data Using Casts in Laravel
- How to Search a JSON Column Using Laravel Eloquent
how to search in json data column using eloquent
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();
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 ????
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.
Why cast to json and not cast to array.
I don’t see the advantage of doing it like that.
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