bfg / dto
The data transfer object pattern for Laravel
Requires
- php: ^8.0
- illuminate/contracts: *
This package is auto-updated.
Last update: 2024-12-19 19:17:51 UTC
README
The data transfer object pattern
Installation
composer require bfg/dto
after install your can create a new dto by use this command
php artisan make:dto UserDto
Usage
- Introduction
- First steps
- Constructors
- Nested DTO calls
- Binding
- Property extends
- Property casting
- Property hidden
- Property rules
- Property encrypted
- Property mutations
- Computed properties
- Lazy properties
- Method property access
- Collection hinting
- Property by method with
- Property logsEnabled
- Meta
- Attributes
- Events
- Reflection
- Convert DTO to
- DTO Collection
- Commands
- Helpers
- Customize http request
- Default Laravel Support
Introduction
Variety of constructs for creating DTOs
The package provides a variety of methods for creating DTOs (Data Transfer Objects), which significantly improves flexibility. Methods such as fromArray, fromModel, fromRequest, fromJson, fromSerialize and others allow you to conveniently create DTOs from different data sources.
Support for nested DTOs
The package supports nested DTOs with typing, which makes it easy to work with complex data, such as addresses or comments in the user example. This simplifies data processing in cases with dependencies between objects.
Rich customization of properties
Support for data casting, such as datetime, bool, as well as property extension through methods and attributes, such as DtoName, DtoFromConfig, DtoFromRequest are useful and powerful tools that make DTOs even more versatile.
Diving into events
The ability to handle various events (creating, created, mutating and others) provides greater flexibility in managing the state of the DTO. This can be useful for implementing validation logic or transforming data before or after it is used.
DTO Collections Support
Including support for DTO collections with methods for saving them to the database or models is a great addition that makes it easier to work with multiple objects.
Additional Features
Convenient helpers for working with DTOs, such as validate, restore, cache, as well as methods for working with metadata and logs, make this package a great tool for organizing the data structure in large projects.
Ease of Use
The ease of creating DTOs via the php artisan make:dto command and obvious typing of properties make the package developer-friendly, ensuring both clean code and good integration with the Laravel framework.
Overall, this package looks like a powerful tool for structuring data in Laravel, suitable for use in projects with large amounts of data and complex models. Everything looks logical and flexible, which allows you to quickly adapt it to various needs.
First steps
Before you can use the DTO, you need to create a new class that extends the Bfg\Dto\Dto
class.
All you dto properties must be public and have a type hint.
Also you must use the constructor for the DTO. And you can use the dependency injection in the constructor.
use Bfg\Dto\Dto; class UserDto extends Dto { protected array $hidden = [ 'password' ]; public function __construct( public string $name, public string $email, public ?string $password, ) {} }
After creating the DTO, you can use it in your code.
$dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); // Or $dto = UserDto::new( name: 'John Doe', email: 'test@gmail.com', password: '123456' ); echo $dto->name; // John Doe
Constructors
fromEmpty
You can create a new DTO with empty properties.
$dto = UserDto::fromEmpty();
fromArray
You can create a new DTO from an array.
$dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', ]);
fromAnything
You can create a new DTO from anything.
$dto = UserDto::fromAnything(['name' => 'John Doe', 'email' => 'test@gmail.com']); $dto = UserDto::fromAnything([ ['name' => 'John Doe', 'email' => 'test@gmail.com'], ['name' => 'John Doe', 'email' => 'test@gmail.com'], ]); $dto = UserDto::fromAnything(\Illuminate\Foundation\Http\FormRequest::class); $dto = UserDto::fromAnything('{"name":"John Doe","email":"test@gmail.com"}'); $dto = UserDto::fromAnything('C:8:"UserDto":23:{a:2:{s:4:"name";s:8:"John Doe";s:5:"email";s:13:"test@gmail.com";}}'); $dto = UserDto::fromAnything(User::find(1));
fromGet
You can create a new DTO from the get request.
$dto = UserDto::fromGet(string $url, array|string|null $query = null, array $headers = []); UserDto::fromGet('https://test.dev', ['name' => 'John Doe', 'email' => 'test@gmail.com']);
fromPost
You can create a new DTO from the post request.
$dto = UserDto::fromPost(string $url, array $data = [], array $headers = []); UserDto::fromPost('https://test.dev', ['name' => 'John Doe', 'email' => 'test@gmail.com']);
fromHttp
You can create a new DTO from the http request.
$dto = UserDto::fromHttp(string $method, string $url, array|string|null $data = [], array $headers = []): DtoCollection|static|null; UserDto::fromHttp('get', 'https://test.dev', ['name' => 'John Doe', 'email' => 'test@gmail.com']);
fromRequest
You can create a new DTO from the request.
$dto = UserDto::fromRequest(\Illuminate\Foundation\Http\FormRequest::class);
fromJson
You can create a new DTO from json.
$dto = UserDto::fromJson('{"name":"John Doe","email":"test@gmail.com"}');
fromSerialize
You can create a new DTO from serialize.
$dto = UserDto::fromSerialize('C:8:"UserDto":23:{a:2:{s:4:"name";s:8:"John Doe";s:5:"email";s:13:"test@gmail.com";}}');
fromModel
You can create a new DTO from model.
$dto = UserDto::fromModel(User::find(1));
fromStaticCache
You can create a new DTO from static cache.
$dto = UserDto::fromStaticCache('user', function () { return UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', ]); });
fromCollection
You can create a new DTO from collection.
$collection = UserDto::fromCollection([ ['name' => 'John Doe', 'email' => 'test@gmail.com'], ['name' => 'Sam Doe', 'email' => 'test2@gmail.com'], ]);
fromCache
You can create a new DTO from cache.
// You can cache dto before $dto->cache(); $dto = UserDto::fromCache(function () { // If cache not found return UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', ]); });
fromSource
You can create a new DTO from source.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, ) {} public static function sourceV1(...$arguments): array { // Do something return [ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', ]; } }
And after that you can create a new DTO from source.
$dto = UserDto::fromSource('v1', ...$arguments);
Nested DTO calls
For nested DTO calls, you can use type hinting.
use Bfg\Dto\Dto; class AddressDto extends Dto { public function __construct( public string $city, public string $street, ) {} } class CommentDto extends Dto { public function __construct( public string $message, ) {} } class UserDto extends Dto { protected array $hidden = [ 'password' ]; public function __construct( public string $name, public string $email, public ?string $password, public AddressDto $address, public CommentDto|array $comments, ) {} }
Now you can use nested DTOs.
$dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', 'address' => [ 'city' => 'New York', 'street' => 'Wall Street', ], 'comments' => [ ['message' => 'The first comment'], ['message' => 'The second comment'], ] ]); echo $dto->address->city; // New York // And foreach ($dto->comments as $comment) { echo $comment->message; }
Binding
You can use binding for the DTO.
Binding to the model
You can bind the DTO property to the model.
use Bfg\Dto\Dto; use App\Models\User; use Bfg\Dto\Attributes\DtoName; class UserDto extends Dto { public function __construct( public string $name, public string $email, #[DtoName('user_id')] public ?User $user, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'user_id' => 1, // Or 'user' => 1, ]); dump($dto->user); // User model // In Array you will get the id of the model dump($dto->toArray()); // ['name' => 'John Doe', 'email' => 'test@gmail.com', 'user_id' => 1]
If model User with id 1
exists, it will be bound to the DTO property. If not, the property will be null.
Binding to the Carbon
You can bind the DTO property to the Carbon.
Default format for the Carbon is Y-m-d H:i:s
.
You can change the format using the $dateFormat
property.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public \Carbon\Carbon $created_at, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'created_at' => '2025-01-01 00:00:00', ]); dump($dto->created_at); // Carbon object // In Array you will get the date in the format `Y-m-d H:i:s` dump($dto->toArray()); // ['name' => 'John Doe', 'email' => 'test@gmail.com', 'created_at' => '2025-01-01 00:00:00']
Property extends
You can use property extends for extending the DTO.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $email, public ?string $password, ) {} }
class SpecialUserDto extends UserDto { protected static array $extends = [ 'name' => 'string|null', // Or 'name' => ['string', 'null'], ]; }
This way you will expand the properties for DTO.
All properties have identical behavior to properties in the property promotion constructor.
Property casting
You can use property casting like in Laravel models.
use Bfg\Dto\Dto; class UserDto extends Dto { protected static array $casts = [ 'is_admin' => 'bool', 'created_at' => 'datetime', ]; public function __construct( public string $name, public string $email, public ?string $password, public bool $is_admin, public \Carbon\Carbon $created_at, ) {} }
Also, this casting support class casting. You can create a new class casting using the artisan command:
php artisan make:dto-cast UserNameCast
After creating the class casting, you can use it in the DTO.
use Bfg\Dto\Dto; class UserDto extends Dto { protected static array $casts = [ 'is_admin' => 'bool', 'created_at' => 'datetime', 'name' => UserNameCast::class, ]; }
And casting support enum casting. You can create a new enum casting using the artisan command:
php artisan make:enum UserStatusEnum
After creating the enum casting, you can use it in the DTO.
use Bfg\Dto\Dto; class UserDto extends Dto { protected static array $casts = [ 'is_admin' => 'bool', 'created_at' => 'datetime', 'name' => UserNameCast::class, 'status' => UserStatusEnum::class, ]; }
Property hidden
You can use property hidden like in Laravel models.
use Bfg\Dto\Dto; class UserDto extends Dto { protected array $hidden = [ 'password' ]; public function __construct( public string $name, public string $email, public ?string $password, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', ]); echo $dto->toArray(); // ['name' => 'John Doe', 'email' => 'test@gmail.com']
Property rules
You can use property rules like in Laravel requests.
use Bfg\Dto\Dto; class UserDto extends Dto { protected static array $rules = [ 'name' => 'required|string', 'email' => 'required|email', 'password' => 'required|string|min:6', ]; protected static array $ruleMessages = [ 'name.required' => 'The name field is required.', 'email.required' => 'The email field is required.', 'password.required' => 'The password field is required.', ]; public function __construct( public string $name, public string $email, public ?string $password, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', ]); // Throws an exception
Property encrypted
You can use property encrypted for getting encrypted data.
use Bfg\Dto\Dto; class UserDto extends Dto { protected array $encrypted = [ 'password' ]; public function __construct( public string $name, public string $email, public string $password, // Data will be decrypted ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => \Illuminate\Support\Facades\Crypt::encrypt('123456'), ]); echo $dto->password; // You will get decrypted password dump($dto->toArray()); // ['name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => 'encrypted data']
Property mutations
You can use property mutations like in Laravel models.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, ) {} protected function fromArrayName(string $name): string { return ucwords($name); } protected function toArrayName(string $name): string { return strtolower($name); } }
fromArrayName
method will be called when you create a new DTO data from an array.toArrayName
method will be called when you convert DTO data to an array.
This method gets the property value and must return the new value.
Computed properties
You can use computed properties.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $lastName, public string $email, public ?string $password, ) {} public function fullName(): string { return $this->name . ' ' . $this->lastName; } }
Now you can use computed properties.
$dto = UserDto::fromArray([ 'name' => 'John', 'lastName' => 'Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); echo $dto->fullName; // John Doe
Lazy properties
You can use lazy like properties any property or computed property. If you add the prefix "lazy" before the name of a property or a computed property, you will get access to lazy execution. When you request a property, the value that this property receives is cached and all subsequent times the result for the lazy property is taken from the cache and if in DTO the property changes, then in Lazy it will remain the same since it is taken from the cache.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $lastName, public string $email, public ?string $password, ) {} public function fullName(): string { return $this->name . ' ' . $this->lastName; } } $dto = UserDto::fromArray([ 'name' => 'John', 'lastName' => 'Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); echo $dto->lazyEmail; // test@gmail.com echo $dto->lazyFullName; // John Doe, and it put in the cache $dto->set('name', 'Sam'); echo $dto->lazyFullName; // John Doe, because it is taken from the cache
Method property access
You can use the method property access.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', ]); echo $dto->name(); // John Doe // The same as echo $dto->get('name'); // John Doe
Method default for field
You can use the default
method for setting the default value for the field.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, ) {} public static function defaultName() { return 'Jon'; } }
After that, you can escape the name field when creating a DTO.
$dto = UserDto::fromArray([ 'email' => 'test@gmail.com', 'password' => '123456', ]); echo $dto->name; // Jon
Collection hinting
You can use collection hinting.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, public AddressDto|array $address, // Or public AddressDto|\Illuminate\Support\Collection $address, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', 'address' => [ ['city' => 'New York', 'street' => 'Wall Street'], ['city' => 'Los Angeles', 'street' => 'Hollywood Street'], ] ]); foreach ($dto->address as $address) { echo $address->city; }
Property by method with
You can use the with...
method for adding data to the DTO array.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $lastName, public string $email, public ?string $password, ) {} public function withFullName(): string { return $this->name . ' ' . $this->lastName; } } $dto = UserDto::fromArray([ 'name' => 'John', 'lastName' => 'Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); dump($dto->toArray()); // ['name' => 'John', 'lastName' => 'Doe', 'email' => 'test@gmail.com', 'password' => '123456', 'fullName' => 'John Doe']
Property logsEnabled
You can use property logsEnabled for logging data in the DTO memory.
use Bfg\Dto\Dto; class UserDto extends Dto { protected static bool $logsEnabled = true; public function __construct( public string $name, public string $email, public ?string $password, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', ]); $dto->set('name', 'Sam Doe'); dump($dto->logs()); // You will get logs DTO
You can write your own logs to the DTO memory using the log
method.
$dto->log(string $message, array $context = []);
Meta
You can use meta.
$dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', ]); $dto->setMeta(['key' => 'value']); $dto->setMeta(['key2' => 'value2']); echo $dto->getMeta('key'); // value echo $dto->getMeta('key2'); // value2 // You can get all meta dump($dto->getMeta()); // ['key' => 'value', 'key2' => 'value2'] // You can remove meta $dto->unsetMeta('key');
Attributes
You can use attributes.
DtoName
You can use the DtoName
attribute to add the name of the DTO.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( #[DtoName('user')] public string $name, public string $email, public ?string $password, ) {} } $dto = UserDto::fromArray([ 'user' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); // Or $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); echo $dto->name; // John Doe
Here we have added an additional field name to the "name" field and we can now use 2 fields to insert data.
For property extends:
use Bfg\Dto\Dto; class UserDto extends Dto { #[DtoName('user', 'name')] protected static array $extends = [ 'name' => 'string', ]; public function __construct( public string $email, public ?string $password, ) {} }
Since we cannot write an attribute to a separate element of the array, we need to specify the name of the field to which we need to assign an additional name as the second parameter.
DtoFromConfig
You can use the DtoFromConfig
attribute to add the property value from the config.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, #[DtoFromConfig('app.name')] public string $appName, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); echo $dto->appName; // Laravel
DtoFromRequest
You can use the DtoFromRequest
attribute to add the property value from the request.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, #[DtoFromRequest] public string $id, ) {} } // https://test.dev/?id=100 $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); echo $dto->id; // 100
DtoFromRoute
You can use the DtoFromRoute
attribute to add the property value from the route.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, #[DtoFromRoute] public string $id, ) {} } // Route::get('/{id}', function ($id) {}); $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); echo $dto->id; // 100
DtoFromCache
You can use the DtoFromCache
attribute to add the property value from the cache.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, #[DtoFromCache('user')] public string $userFromCache, // Or #[DtoFromCache] public string $user, ) {} } Cache::put('user', 'John Doe', 60); $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456' ]); echo $dto->user; // John Doe
DtoToResource
You can use the DtoToResource
attribute to convert the property for adding to the array.
Create a new resource:
php artisan make:resource UserAddressResource
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, #[DtoToResource(UserAddressResource::class)] public AddressDto $address, ) {} } $dto = UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', 'address' => [ 'city' => 'New York', 'street' => 'Wall Street', ] ]); echo $dto->toArray(); // ['name' => 'John Doe', 'email' => '...', 'password' => '...', 'address' => ['city' => 'New York', 'street' => 'Wall Street']]
Address will be converted to the array using the UserAddressResource
resource.
Events
You can use events.
creating
You can use the creating
event.
UserDto::on('creating', function (array $arguments) { $arguments['name'] = 'John Doe'; return $arguments; });
created
You can use the created
event.
UserDto::on('created', function (UserDto $dto, array $arguments) { $dto->name = 'John Doe'; });
updating
You can use the updating
event.
UserDto::on(['updating', 'name'], function (mixed $value, UserDto $dto) { return strtoupper($value); });
updated
You can use the updated
event.
UserDto::on(['updated', 'name'], function (UserDto $dto) { $dto->name = strtoupper($dto->name); });
mutating
You can use the mutating
event.
UserDto::on(['mutating', 'name'], function (mixed $value, UserDto $dto, array $arguments) { return strtoupper($value); });
mutated
You can use the mutated
event.
UserDto::on(['mutated', 'name'], function (mixed $value, UserDto $dto, array $arguments) { return strtoupper($value); });
serialize
You can use the serialize
event.
UserDto::on('serialize', function (array $arguments, UserDto $dto) { $arguments['name'] = strtoupper($arguments['name']); return $arguments; });
unserialize
You can use the unserialize
event.
UserDto::on('unserialize', function (array $arguments, UserDto $dto) { $arguments['name'] = strtolower($arguments['name']); return $arguments; });
clone
You can use the clone
event.
UserDto::on('clone', function (array $arguments, UserDto $dto) { $arguments['name'] = strtolower($arguments['name']); return $arguments; });
fromModel
You can use the fromModel
event.
UserDto::on('fromModel', function (UserDto $dto, array $arguments) { // You can change the DTO data or something else });
fromEmpty
You can use the fromEmpty
event.
UserDto::on('fromEmpty', function (UserDto $dto, array $arguments) { // You can change the DTO data or something else });
fromArray
You can use the fromArray
event.
UserDto::on('fromArray', function (UserDto $dto, array $arguments) { // You can change the DTO data or something else });
fromRequest
You can use the fromRequest
event.
UserDto::on('fromRequest', function (UserDto $dto, array $arguments) { // You can change the DTO data or something else });
fromJson
You can use the fromJson
event.
UserDto::on('fromJson', function (UserDto $dto, array $arguments) { // You can change the DTO data or something else });
fromSerialize
You can use the fromJson
event.
UserDto::on('fromJson', function (UserDto $dto) { // You can change the DTO data or something else });
prepareModel
You can use the prepareModel
event.
UserDto::on('prepareModel', function (array $arguments) { $arguments['name'] = 'John Doe'; return $arguments; });
prepareSerialize
You can use the prepareSerialize
event.
UserDto::on('prepareSerialize', function (string $serializedString) { // You can change the serialized string or something else return $serializedString; });
prepareJson
You can use the prepareJson
event.
UserDto::on('prepareJson', function (array $arguments) { // You can change the json array or something else return $arguments; });
prepareRequest
You can use the prepareRequest
event.
UserDto::on('prepareRequest', function (array $arguments) { // You can change the request array or something else return $arguments; });
prepareArray
You can use the prepareArray
event.
UserDto::on('prepareArray', function (array $arguments) { // You can change the array or something else return $arguments; });
prepareEmpty
You can use the prepareArray
event.
UserDto::on('prepareEmpty', function () { // You can create a new array or something else return []; });
destruct
You can use the destruct
event.
UserDto::on('destruct', function (UserDto $dto) { // You can do something with the DTO });
Reflection
You can use reflection.
explain
You can use the explain
method for getting the DTO information.
$dto->explain();
vars
You can use the vars
method for getting the DTO properties.
$dto->vars();
getModifiedFields
You can use the getModifiedFields
method for getting the modified fields.
$dto->getModifiedFields();
getRelationNames
You can use the getRelationNames
method for getting the relation names.
$dto->getRelationNames();
getPropertyNames
You can use the getPropertyNames
method for getting the property names.
$dto->getPropertyNames();
getNames
You can use the getNames
method for getting the names.
$dto->getNames();
getReflection
You can use the getReflection
method for getting the reflection.
$dto->getReflection();
Convert DTO to
ToArray
You can convert DTO to array.
$dto->toArray();
ToJson
You can convert DTO to json.
$dto->toJson($options = 0);
ToResponse
You can convert DTO to response.
$dto->toResponse(int $status = 200, array $headers = [], int $options = 0);
ToCollection
You can convert DTO to collection.
$dto->toCollection();
ToBase64
You can convert DTO to base64.
$dto->toBase64();
ToModel
You can convert DTO to model.
$dto->toModel(User::class);
ToSerialize
You can convert DTO to serialize.
$dto->toSerialize();
ToApi
You can convert DTO to api.
$dto->toApi(string $url, string $method = 'post', array $headers = []);
ToString
You can convert DTO to string.
$dto->toString(); //Or echo (string) $dto;
DTO Collection
Dto collection have couple additional methods.
insertToDatabase
For save collection to database you can use saveToDatabase
method.
$collection = UserDto::fromCollection([ ['name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456'], ['name' => 'Sam Doe', 'email' => 'sam@gmail.com', 'password' => '123456'], ]); $collection->insertToDatabase('users');
insertToModel
For save collection to model you can use saveToModel
method.
$collection = UserDto::fromCollection([ ['name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456'], ['name' => 'Sam Doe', 'email' => 'sam@gmail.com', 'password' => '123456'], ]); $collection->insertToModel(\App\Models\User::class);
Commands
You can use commands.
Make dto
You can create a new DTO using the artisan command.
php artisan make:dto UserDto
Make dto cast
You can create a new DTO cast using the artisan command.
php artisan make:dto-cast UserNameCast
Make dto docs
You can build the DTO documentation for extended fields using the artisan command.
php artisan make:dto-docs
Add this command to the
composer.json
file for auto-generating DTO documentation after thecomposer update
andcomposer dump-autoload
command.
"scripts": { "post-autoload-dump": [ "@php artisan make:dto-docs" ], }
Helpers
You can use helpers.
new
You can use the new
helper for creating a new DTO.
UserDto::new( name: 'John Doe', email: 'test@gmail.com', password: '123456', );
version
You can use the version
helper for getting the DTO version.
UserDto::version();
pipeline
You can use the pipeline
helper for creating a new DTO pipeline.
$dto->pipeline([ SomeClassForPipeline::class, ]);
cache
You can use the cache
helper for caching the DTO.
$dto->cache(\DateTimeInterface|\DateInterval|int|null $ttl = null);
cacheKey
You can use the cacheKey
helper for getting the cache key.
$dto->cacheKey('name');
getCachedKey
You can use the getCachedKey
helper for getting the cached key.
$dto->getCachedKey('name');
cacheKeyClear
You can use the cacheKeyClear
helper for clearing the cache key.
$dto->cacheKeyClear('name');
validate
You can use the validate
helper for validating the DTO.
$dto->validate([ 'name' => 'required|string', 'email' => 'required|email', 'password' => 'required|string|min:6', ]); // bool
restore
You can use the restore
helper for restoring the DTO from the original data.
$dto->restore();
originals
You can use the originals
helper for getting the original data.
$dto->originals();
equals
You can use the equals
helper for comparing the DTOs.
$dto->equals(UserDto::fromArray([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', ])); // bool
fill
You can use the fill
helper for filling the DTO.
$dto->fill([ 'name' => 'John Doe', 'email' => 'test@gmail.com', 'password' => '123456', ]);
length
You can use the length
helper for getting the length of the DTO in bytes.
$dto->length(); // Or $dto->length(\Bfg\Dto\Dto::GET_LENGTH_SERIALIZE); // You get the length of the DTO in bytes in serialized form // And you can get the length of the DTO in bytes in json form $dto->length(\Bfg\Dto\Dto::GET_LENGTH_JSON);
count
You can use the count
helper for getting the count of the DTO.
$dto->count();
has
You can use the has
helper for checking the property in the DTO.
$dto->has('name');
You also can use isset
for checking the property in the DTO.
isset($dto['name']);
dataHash
You can use the dataHash
helper for getting the data hash of the DTO.
$dto->dataHash();
hash
You can use the hash
helper for getting the hash of the DTO.
$dto->hash();
clone
You can use the clone
helper for cloning the DTO.
$dto->clone();
str
You can use the str
helper for getting the string representation of the DTO.
$dto->str('name')->camel()->snake();
collect
You can use the collect
helper for wrapping the DTO properties in the collection.
$dto->collect('addresses')->map(function (UserAddressDto $address) { return $address->city; });
boolable
You can use the boolable
helper for inverting the boolean property in the DTO.
$dto->boolable('confirmed');
toggleBool
You can use the toggleBool
helper for toggling the boolean property in the DTO.
$dto->toggleBool('is_admin');
increment
You can use the increment
helper for incrementing the property in the DTO.
$dto->increment('count');
decrement
You can use the decrement
helper for decrementing the property in the DTO.
$dto->decrement('count');
set
You can use the set
helper for setting the property in the DTO.
$dto->set('name', 'John Doe');
get
You can use the get
helper for getting the property in the DTO.
$dto->get('name');
map
You can use the map
helper for mapping the DTO properties.
$dto->map(function (mixed $value, string $key) { return strtoupper($value); });
isEmpty
You can use the isEmpty
helper for checking the DTO is property empty.
$dto->isEmpty('name');
isNotEmpty
You can use the isNotEmpty
helper for checking the DTO is property not empty.
$dto->isNotEmpty('name');
isNull
You can use the isNull
helper for checking the DTO is property null.
$dto->isNull('name');
isNotNull
You can use the isNotNull
helper for checking the DTO is property not null.
$dto->isNotNull('name');
isCanNull
You can use the isCanNull
helper for checking the DTO is property can be null.
$dto->isCanNull('name');
isTrue
You can use the isTrue
helper for checking the DTO is property true.
$dto->isTrue('is_admin');
isFalse
You can use the isFalse
helper for checking the DTO is property false.
$dto->isFalse('is_admin');
isBool
You can use the isBool
helper for checking the DTO is property bool.
$dto->isBool('is_admin');
isEquals
You can use the isEquals
helper for checking the DTO is property equals.
$dto->isEquals('name', 'John Doe');
isNotEquals
You can use the isNotEquals
helper for checking the DTO is property not equals.
$dto->isNotEquals('name', 'John Doe');
isInstanceOf
You can use the isInstanceOf
helper for checking the DTO is property instance of.
$dto->isInstanceOf('address', AddressDto::class);
isNotInstanceOf
You can use the isNotInstanceOf
helper for checking the DTO is property not instance of.
$dto->isNotInstanceOf('address', AddressDto::class);
isString
You can use the isString
helper for checking the DTO is property string.
$dto->isString('name');
isNotString
You can use the isNotString
helper for checking the DTO is property not string.
$dto->isNotString('name');
isInt
You can use the isInt
helper for checking the DTO is property int.
$dto->isInt('id');
isNotInt
You can use the isNotInt
helper for checking the DTO is property not int.
$dto->isNotInt('id');
isFloat
You can use the isFloat
helper for checking the DTO is property float.
$dto->isFloat('price');
isNotFloat
You can use the isNotFloat
helper for checking the DTO is property not float.
$dto->isNotFloat('price');
isArray
You can use the isArray
helper for checking the DTO is property array.
$dto->isArray('addresses');
isNotArray
You can use the isNotArray
helper for checking the DTO is property not array.
$dto->isNotArray('addresses');
isObject
You can use the isObject
helper for checking the DTO is property object.
$dto->isObject('address');
isNotObject
You can use the isNotObject
helper for checking the DTO is property not object.
$dto->isNotObject('address');
isInstanceOfArray
You can use the isInstanceOfArray
helper for checking the DTO is property instance of array.
$dto->isInstanceOfArray('addresses', AddressDto::class);
isNotInstanceOfArray
You can use the isNotInstanceOfArray
helper for checking the DTO is property not instance of array.
$dto->isNotInstanceOfArray('addresses', AddressDto::class);
Customize http request
You can customize the http request.
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, ) {} protected static function httpClient(): PendingRequest { return Http::withoutVerifying() ->withoutRedirecting() ->withCookies(['name' => 'value']) ->withHeaders(['Authorization' => 'Bearer ' . auth()->user()->token]); } }
Or you can customize only headers:
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, ) {} protected static function httpHeaders(): array { return [ 'Authorization' => 'Bearer ' . auth()->user()->token, ]; } }
Also you can customize what fromAnything
can be used for the request POST by default
use Bfg\Dto\Dto; class UserDto extends Dto { protected static bool $postDefault = true; public function __construct( public string $name, public string $email, public ?string $password, ) {} }
And you can customize the parameters data for the request by default
use Bfg\Dto\Dto; class UserDto extends Dto { public function __construct( public string $name, public string $email, public ?string $password, ) {} protected static function httpData(array|string|null $data): array|string|null { // Do something with data return $data; } }
Default Laravel Support
DTO class use a famous Laravel support, such as Illuminate\Support\Traits\Conditionable
, Illuminate\Support\Traits\Dumpable
,
Illuminate\Support\Traits\Macroable
and Illuminate\Support\Traits\Tappable
.
Changelog
Please see CHANGELOG for more information on what has changed recently.
Security
Please see SECURITY for more information about security.
Credits
License
The MIT License (MIT). Please see License File for more information.