mateusjatenee/laravel-persist

This is my package laravel-persist

0.2.1 2023-12-05 15:07 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Introduction

The package offers an extension on top of Eloquent, enabling developers to handle the persistence of entire object graphs as a single unit of work. This package simplifies managing complex data models with multiple interrelated entities, ensuring a more efficient and reliable data handling process.

It works similarly to the native push method, but push does not persist any records for the first time. Therefore, you cannot build an object with its relationships and use push to save everything.

Persist works by hooking on two specific pieces of the lifecycle:

  1. When you assign a property (e.g $post->owner = $user), the package checks whether that property is a relation, and if so, calls setRelation to properly set it.
  2. When you call the persist method, it works in a similar fashion to push, but it adds hooks to persist the related objects before or after the base object. There are subtle differences on persistence order for different relationship types.

On top of that, Persist also runs the entire operation inside a database transaction. This means that if any part of the object graph fails to persist, the entire operation will be rolled back, maintaining database integrity.

Installation

You can install the package via composer:

composer require mateusjatenee/laravel-persist

Usage

Simply add the Persist trait to your models. For example:

namespace App\Models;

class Order extends Model
{
    use Persist;
}

Now you'll be able to persist the entire object graph using the persist method. For example:

class ProcessCheckoutHandler
{
    public function __construct(
        private DatabaseManager $database,
    ) {
    }

    public function handle(ProcessCheckout $command)
    {
        $order = Order::startForCustomer($command->customer->id);
        $order->lines->push($command->cartItems->toOrderLines()); // Pushes an object to the "lines" relationship, which is a HasMany relation.
        
        $charge = $command->gateway->pay($command->pendingPayment);
        
        $order->payment = Payment::fromCharge($charge); // Sets the payment relationship, a "BelongsTo" relation.
        $order->payment->customer = $command->customer; // Sets the customer relationship "2-levels deep".

        $order->persist();
        
        return $order;
    }
}

In the example above, 4 entities will be persisted to the database: Order, OrderLine, Payment, and Customer.
persist runs, by default, within a transaction, so that if any queries fail, the entire transaction is rolled back.

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.