Value objects with batteries included
Installation
You can install the package via composer:
Have you ever...
... worked with an array of data, retrieved form a request, a CSV file or a JSON API; and wondered what was in it?
Here's an example:
{
$dataFromRequest[/* what to do now?? */];
}
The goal of this package is to structure "unstructured data", which is normally stored in associative arrays. By structuring this data into an object, we gain several advantages:
- Structural: we're able to type hint value objects, instead of just calling them
array. - Integrity: by making all properties on our objects typeable, we're sure that their values are never something we didn't expect.
- Clarity: because of typed properties, we can statically analyze them and have auto completion.
Let's look at the example of a JSON API call:
[
'title' => '...',
'body' => '...',
'author_id' => '...',
]
Working with this array is difficult, as we'll always have to refer to documentation to know what's exactly in it. This package allows you to create value object definitions, classes, which will represent the data in a structured way.
We did our best to keep the syntax and overhead as little as possible:
{
/** @var string */
public $title;
/** @var string */
public $body;
/** @var \Author */
public $author;
}
An object of PostData can from now on be constructed like so:
'title' => '...',
'body' => '...',
'author_id' => '...',
]);
It's of course possible to add static constructors to PostData:
{
// ...
public static function fromRequest(Request $request): self
{
return new self([
'title' => $request->get('title'),
'body' => $request->get('body'),
'author' => Author::find($request->get('author_id')),
]);
}
}
By adding doc blocks to our properties, their values will be validated agains the given type;
and a TypeError will be thrown if the value doesn't comply with the given type.
This are the possible ways of declaring types:
{
/**
* Built in types:
*
* @var string
*/
public $property;
/**
* Classes with their FQCN:
*
* @var \App\Models\Author
*/
public $property;
/**
* Lists of types:
*
* @var \App\Models\Author[]
*/
public $property;
/**
* Union types:
*
* @var string|int
*/
public $property;
/**
* Nullable types:
*
* @var string|null
*/
public $property;
/**
* Mixed types:
*
* @var mixed|null
*/
public $property;
/**
* No type, which allows everything
*/
public $property;
}
When PHP 7.4 introduces typed properties, you'll be able to simply remove the doc blocks and type the properties with the new, built-in syntax.
A note on immutability
These value objects are meant to be only constructed once, and not changed thereafter. You should never write data to the properties once the value object is created, even though technically it's possible.
Helper functions
There are also some helper functions provided for working with multiple properties at once.
$postData
->only('title', 'body')
->toArray();
$postData
->except('author')
->toArray();
You can also chain these methods:
->except('title')
->except('body')
->toArray();
It's important to note that except and only are immutable, they won't change the original value object.
Exception handling
Beside property type validation, you can also be certain that the value object in its whole is always valid.
On constructing a value object, we'll validate whether all required (non-nullable) properties are set.
If not, a Spatie\ValueObject\ValueObjectError will be thrown.
Likewise, if you're trying to set non-defined properties, you'll get a ValueObjectError.
Testing
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email freek@spatie.be instead of using the issue tracker.
Postcardware
You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.
Our address is: Spatie, Samberstraat 69D, 2060 Antwerp, Belgium.
We publish all received postcards on our company website.
Credits
Our Arr class contains functions copied from Laravels Arr helper.
Support us
Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.
Does your business depend on our contributions? Reach out and support us on Patreon. All pledges will be dedicated to allocating workforce on maintenance and new awesome stuff.
License
The MIT License (MIT). Please see License File for more information.