Download the PHP package honeystone/laravel-dto-tools without Composer
On this page you can find all versions of the php package honeystone/laravel-dto-tools. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download honeystone/laravel-dto-tools
More information about honeystone/laravel-dto-tools
Files in honeystone/laravel-dto-tools
Package laravel-dto-tools
Short Description Comprehensive set of DTO Tools for Laravel.
License MIT
Homepage https://honeystone.com
Informations about the package laravel-dto-tools
Honeystone DTO Tools for Laravel
DTO tools is a package designed to bring additional power and convenience to your native PHP data transfer objects. The main motivation for this package was to remove much of the boilerplate created moving data in to and out of DTOs. For example, transforming snake-cased model attributes to camel-cased to be consumed by your presentation layer, or casting a user inputted numerical string (after validation ofc) to an integer.
Features include property casting and mutation, serialization, patch data handling, relationships, and model and collection transformation.
Support us
We are committed to delivering high-quality open source packages maintained by the team at Honeystone. If you would like to support our efforts, simply use our packages, recommend them and contribute.
If you need any help with your project, or require any custom development, please get in touch.
Installation
Publish the configuration file with:
Usage
This package requires very little modification to your existing DTOs. As a minimum, your DTOs need to implement the
Transferable
contract and use the HasTransferableData
trait, like so:
As you can see, this is still just a regular readonly
PHP object. You can instantiate it normally too, however, if you
want to make use of property casting, you'll need to use the static make()
method:
This is really messy, so we'll clean it up in the next section.
Casting properties
Casters are used to intercept and cast/mutate values before instantiating the DTO. They are implemented using PHP
Attributes. In the following example, we'll ensure that our empty description is cast to null
, that the status is cast
to an enum, and that the modified time is represented in an iso-8601 string:
Our data can be a little looser now, but we still benefit from the DTO's type safety:
Much better. The following casters are available, or you can create your own:
To implement your own casters, just create an Attribute
that implements
Honeystone\DtoTools\Casters\Contracts\CastsValues
.
Serialization
There are two primary serialization methods available, getAttributes()
and toArray()
. The difference is that
getAttributes()
will simply provide the property values in an array, whereas toArray()
will recursively convert
Transferable
and Arrayable
properties into arrays.
There are also getRelationships()
and toStorableArray()
, but we'll talk about those later.
Property transformation
Sometimes you need to make sweeping changes to all parameters entering your DTO. To achieve this you can add a static
transformIncoming()
method to your DTO:
The transformOutgoing()
method can also be implemented for DTO serialization:
A very common use-case in Laravel will be converting snake-case properties to camel-case. As such, the
CreatableFromSnake
and SerializesToSnake
traits are available:
Storable data
We've looked at Transferable
data so far, which is great for passing complete data through your service layer, but
what if you need to process partial data (i.e. a patch)? This is Storable
enters the scene.
A basic Storable
is very similar to a Transferable
except the class itself cannot be readonly
. Storable
s need to
have a little bit of state to function, so we mark our properties readonly
instead.
By default, a storable isn't in patching mode. For this we need to add the Patch
class attribute:
We can check if the storable is in patching mode using the isPatching()
method.
When a storable is in patching mode, null
values will be automatically excluded from serialisation using the
toStorableArray()
method:
You can also use the isStorable()
method to check if an individual property can be stored:
Sometimes, null
is a valid value and should be stored. In these cases you can use the force()
method to mark these
properties as storable:
If you need a list of forced properties, use getForced()
.
Storable relationships
Occasionally, when transferring data into your services layer you need to represent changes to relational structures. You could do this with a simple property on your DTO, for example:
There are a few problems with this approach though: there's no real type safety, you can't just add or remove a tag, you have to provide all the tags, and you cant have any meta data (e.g. order). Maybe you upgrade this to be an array of DTOs, but there's an easier way:
Using the ToMany
class attribute we can declare a to-many relationship called 'tags' that can be empty, or integers.
We can now add, remove and replace related tags:
Relationships are stored using the related id. This can be either an integer or a string. You can also provide a
Transferable
or Storable
and the library will use its getKey()
method to determine the id. Additional meta data
can be provided as an array or as a Transferable
:
The following relationship class Attributes
are supported:
And the following relationship methods are available:
Serialized relationships are included in toStorableArray()
, or you can grab just the relationships with
getRelationships()
.
Model transformation
It's not uncommon to convert a Model
into a DTO. They'll be different though. The data of a DTO should be more
specific and situational. This can lead to a lot of boilerplate to handle the transformations. This package includes an
abstract
ModelTransformer
to help clean this up.
Here's the most basic example:
You can now call the transform()
and transformCollection()
methods of your transformer to transform your Model
s to
Transferable
s:
Internally this example will use the toArray()
method of your model.
We can be specific about which fields to include in the transformation using the $only
property:
If we need to do something more complex, we could instead create a map()
method:
We can also pass additional parameters to our map method:
The override()
and exclude()
method can be chained to allow on-the-fly changes to the transformation:
That's all good, but what about relationships:
The includeRelated()
and requireRelated()
methods will convert a Model
using aModelTransformer
based on the
transformation mappings in this package's config file.
The requireRelated()
method will throw a Honeystone\DtoTools\Exceptions\RequiredRelationNotLoadedException
if the
relationship has not been loaded.
You can pass additional parameters to these methods, which will be passed onto their respective ModelTransformer
's
map()
method.
Any exclusions or overrides can also be included as additional parameters:
That's pretty much it! If you find this package useful, we'd love to hear from you.
Changelog
A list of changes can be found in the CHANGELOG.md file.
License
Honeystone Consulting Ltd
All versions of laravel-dto-tools with dependencies
illuminate/contracts Version ^10.0|^11.0
spatie/laravel-package-tools Version ^1.16.4