ibrostudio/laravel-data-repository

This is my package laravel-data-repository

1.12.0 2024-11-21 15:08 UTC

This package is auto-updated.

Last update: 2024-11-21 15:08:37 UTC


README

Save Data Transfer Objects (from Spatie's Laravel Data) and Value Objects (from Michael Rubel's Laravel Value Objects) in database and attach to eloquent models.

Installation

Install the package via composer:

composer require ibrostudio/laravel-data-objects-repository

Then run the installer:

php artisan data-repository:install

Usage

Add the trait IBroStudio\DataRepository\Concerns\HasDataRepository to your Eloquent models.

The trait implements a MorphManyDataObjects relationship that extends MorphMany.

namespace App\Models;

use IBroStudio\DataRepository\Concerns\HasDataRepository;
use Illuminate\Database\Eloquent\Model;

class YourEloquentModel extends Model
{
    use HasDataRepository;
}

Working with DTO

Create your DTO following Spatie's Laravel Data documentation.

namespace App\DataObjects;

use Spatie\LaravelData\Data;

class SongData extends Data
{
    public function __construct(
        public string $title,
        public string $artist,
    ) {
    }
}
$data = new SongData(
    title: 'Walk', 
    artist: 'Pantera'
);

Working with Value Objects

Use built-in Value Objects or create one following Michael Rubel's Value Objects documentation.

$data = new \MichaelRubel\ValueObjects\Collection\Complex\Name('Pantera');

Save the Value Object attached to the model in database:

$model->data_repository()->add($data);

For more complex usage, you can use Value Objects in DTO:

namespace App\DataObjects;

use Spatie\LaravelData\Data;
use MichaelRubel\ValueObjects\Collection\Complex\Name;

class SongData extends Data
{
    public function __construct(
        public Name $title,
        public Name $artist,
    ) {
    }
}

Creating or updating objects

The following method save the object in database and attach it to the model:

$model->data_repository()->add($data);

If an object with the sans data class is already attached to the model, its values will be replaced.

Unique data class

You can attach many objects to a model but only one for each data class by default. Considering the previous examples, the model can have only one SongData object (and other DTO or Value Objects).

Multiple data class

If you need more than one object from the same data class, use the valuesAttributes parameter when you create or update an object:

$song1 = new SongData(
    title: 'Walk', 
    artist: 'Pantera'
);

$model->data_repository()->add($data);

$song2 = new SongData(
    title: 'Cowboys From Hell', 
    artist: 'Pantera'
);

$model->data_repository()->add(
    data: $song2,
    valuesAttributes: [
        'values->title' => $song2->title,
    ]
);

$song3 = new SongData(
    title: 'Davidian', 
    artist: 'Machine Head'
);

$model->data_repository()->add(
    data: $song3,
    valuesAttributes: [
        'values->artist' => $song3->artist,
    ]
);

Retrieving objects

You access to all MorphManyDataObjects relations for a model with:

$model->data_repository();

You can limit the instance to a specific data class to access a single object:

$model->data_repository(dataClass: SongData::class);

The object is then retrieved by the values() method:

$song = $model->data_repository(dataClass: SongData::class)->values();

If necessary, you can also constrain the retrieval of the object to certain values of this object with the valuesQuery parameter:

$model->data_repository(
    dataClass: SongData::class,
    valuesQuery: ['title' => 'Walk']
);

Eloquent attribute casting

You can get direct access to an object value like $model->song instead of $model->data_repository(dataClass: SongData::class).

Add a unsignedBigInteger column to your model:

$table->unsignedBigInteger('song')->nullable();

And then add the cast to the model class:

use IBroStudio\DataRepository\Casts\DataObjectCast;

class YourEloquentModel extends Model
{
    protected function casts(): array
    {
        return [
            'song' => DataObjectCast::class,
        ];
    }
}

Usage:

use IBroStudio\DataRepository\Casts\DataObjectCast;

class YourEloquentModel extends Model
{
    protected function casts(): array
    {
        return [
            'song' => DataObjectCast::class,
        ];
    }
}

$model = YourEloquentModel::create([
    'song' => new SongData(
        title: 'Walk', 
        artist: 'Pantera'
    ),
]);
// or
$model->song = new SongData(
    title: 'Walk', 
    artist: 'Pantera'
);

$model->save();

You can constrain the property to a defined data class by adding it to the cast:

use IBroStudio\DataRepository\Casts\DataObjectCast;

class YourEloquentModel extends Model
{
    protected function casts(): array
    {
        return [
            'song' => DataObjectCast::class.':'.SongData::class,
        ];
    }
}

This adds data validation and automatic instantiation of the data class, allowing you to simply pass an array to the property setter:

$model = YourEloquentModel::create([
    'song' => [
        'title' => 'Walk', 
        'artist' => 'Pantera'
    ]
]);

Built-in Objects Values

  • ByteUnit
  • EncryptableText
  • GitSshUrl
  • HashedPassword
  • IpAddress
  • SemanticVersion
  • Timecode
  • VersionedComposerJson
  • Name, FirstName, LastName, Fullname, CompanyName
  • Email
  • Phone
  • TaxNumber

Testing

composer test

Changelog

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

License

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