ibrostudio / laravel-data-repository
This is my package laravel-data-repository
Requires
- php: ^8.2
- darsyn/ip: ^5.0
- gabrielelana/byte-units: ^0.5.0
- illuminate/contracts: ^11.0
- michael-rubel/laravel-value-objects: ^7.0
- spatie/laravel-data: ^4.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- larastan/larastan: ^2.0.1
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^9.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- pestphp/pest-plugin-type-coverage: ^3.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
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
- 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.