In Laravel, the Eloquent ORM is a powerful tool for working with databases. It allows you to interact with your database tables using PHP objects. While Eloquent provides great flexibility for creating, updating, and deleting records, there are scenarios where you might want to ensure the immutability of certain models. This blog post will guide you through creating an Eloquent model trait that raises a RuntimeException when you attempt to edit or delete the model, effectively making it immutable.

Why make a model immutable?

Before we dive into creating the trait, let's briefly discuss why you might want to make an Eloquent model immutable in your Laravel application.

  1. Data Integrity: In some cases, you want to ensure that once a record is created, it remains unchanged to maintain data integrity. For example, you might want to lock down historical data to prevent accidental modifications.

  2. Audit Trails: Immutable models are useful when you need to track changes to records. Instead of updating existing records, you can create new ones, effectively preserving a historical record of changes.

  3. Security: To enhance the security of critical data, immutability can be a safeguard against unauthorized changes. Certain data, such as financial records or user roles, should be kept immutable to prevent tampering.

Creating an immutable model trait

To make an Eloquent model immutable, we'll create a custom trait that uses model events to provide immutability. Here are the steps to achieve this:

Create a new trait

Start by creating a new PHP trait in your Laravel application. You can place it in the app/Traits directory or any directory of your choice. Let's call this trait ImmutableModelTrait.

// app/Traits/ImmutableModelTrait.php

namespace App\Traits;

use RuntimeException;

trait ImmutableModelTrait
{
    public static function bootImmutableModelTrait()
    {
        static::updating(function(): never {
            throw new RuntimeException("This model is immutable and cannot be updated.");
        });

        static::deleting(function(): never {
            throw new RuntimeException("This model is immutable and cannot be deleted.");
        });
    }
}

Use the trait in your model

To make an Eloquent model immutable, simply use the ImmutableModelTrait in your model class. This will register the model events that raise the RuntimeException when attempting to update or delete the model.

// app/Models/YourModel.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Traits\ImmutableModelTrait;

class YourModel extends Model
{
    use ImmutableModelTrait;

    // Your model-specific code here
}

Now, any attempts to update or delete a model that uses the ImmutableModelTrait will result in a RuntimeException being thrown.

Example Usage

Let's see how this works in practice. Assume we have a User model that we want to make immutable:

// Attempting to update a user
$user = User::find(1);
$user->update(['name' => 'New Name']); // This will throw a RuntimeException

// Attempting to delete a user
$user = User::find(1);
$user->delete(); // This will throw a RuntimeException

Conclusion

In Laravel, making Eloquent models immutable can be a valuable strategy for maintaining data integrity, enhancing security, and preserving historical records. By creating a custom trait that raises a RuntimeException when attempting to update or delete a model, you can easily implement immutability in your application where needed. This approach ensures that certain models remain unchanged and unmodifiable, meeting your application's specific requirements for data integrity and security.