Transformers & value objects
Transformers are objects that are used to transform the ‘raw’ API response data to value objects for easy use in your own code. Each repository requires one or more transformers.
Value objects are very simple objects that only consist of a few properties which hold the data. Their only goal is to pass along the data.
Default transformers
The default transformers are very simple. Each transformer has a $dto
property which defines into which value object
the data is transformed. Each transformer also has an optional $mapping
property which defines how the data is
transformed into value objects. For each transformer there is also a value object available in this package. If you
don’t need anything else, but just want to receive the data in a convenient object-oriented way, then you can just use
the provided transformers and value objects.
If you want to add some more complex logic to your transformers, for instance to transform the data directly into you own models instead of the default value objects, you can expand upon the default transformers or write your own transformers completely.
Custom mapping
If you look at the most basic transformer, the ColorTransformer
, you will see that there is no $mapping
property
defined (instead it’s defined on the base object, but it has no values). That is because by default every transformer
transforms the response from the Bricklink API to the same names in the value object, only camel cased.
For instance, if the response of the Bricklink API for a color is something like this:
{
"color_id": 1,
"color_name": "White",
"category": 3,
"color_type": "Solid"
}
This is automatically translated into a value object if it has the same properties as keys in the response, only in camel case:
<?php
class Color
{
public function __construct(
public ?int $colorId,
public ?string $colorName,
public ?int $category,
public ?string $colorType,
) {}
}
If your Transformer object looks like this, the mapping will automatically work:
<?php
class ColorTransformer
{
public string $dto = Color::class;
}
Custom name
But what if the property in the value object has a name that is not the camel cased version of the same thing in the
API response? In that case you can provide your own mapping to the transformer. You only need to add custom mappings
for properties that have different names. If for instance the $category
property in the value object would be named
$categoryId
, you can create the following transformer with this custom mapping:
<?php
class ColorTransformer
{
public string $dto = Color::class;
public array $mapping = [
'category' => 'categoryId'
];
}
Datetime types
By default, the exact value of the API response is stored in the value object property it is mapped to. If you have
a response property that represents a date and time, you can easily transform this into a \DateTime
property by adding
datetime
as the type in the mapping.
Let’s say we had a date_created
property in the response of the API for our color, we could add the following
mapping to transform it into a \DateTime
object:
<?php
class ColorTransformer
{
public string $dto = Color::class;
public array $mapping = [
'category' => 'categoryId',
'date_created' => ['dateCreated', 'datetime']
];
}
As you can see we added an array mapping to our transformer. The first item in the array is the name of the property
this is mapped to, and the second item is the type, in this case datetime
.
Custom types
If we have a property which value should be mapped in a more complex way and that isn’t a datetime
, you can specify a
transformer as the second parameter. This second parameter should extend the
Davesweb\BrinklinkApi\Transformers\BaseTransformer
class and transform the content in the same way as other
transformers.
Let’s say the response doesn’t just include a category id, but a complete category object in the response:
{
"color_id": 1,
"color_name": "White",
"color_type": "Solid",
"category": {
"id": 3,
"name": "Solid colors"
}
}
In that case we can create our own ColorCategory transformer that knows how to transform this category to a value object:
<?php
class ColorCategoryTransformer
{
public string $dto = ColorCategory::class;
}
And then we can add this custom transformer to our mapping for a color:
<?php
class ColorTransformer
{
public string $dto = Color::class;
public array $mapping = [
'category' => ['category', ColorCategoryTransformer::class],
];
}
As you can see we again added an array mapping to our transformer. The first item in the array is still the name of the
property this is mapped to, and the second item is the custom transformer, in this case ColorCategoryTransformer
.
Arrays and custom array types
For simple values that are a just an array of values, you may specify the mapping as an array in the same way as the
datetime
mapping:
<?php
class ColorTransformer
{
public string $dto = Color::class;
public array $mapping = [
'categories' => ['categoryIds', 'array'],
];
}
If the array values are of a more complex type and need their own transformers, you can add the transformer as the third value in the array:
<?php
class ColorTransformer
{
public string $dto = Color::class;
public array $mapping = [
'categories' => ['categories', 'array', ColorCategoryTransformer::class],
];
}
Custom transformers
You are off course free to write your own custom transformers. Transformers don’t have an interface they have to
adhere to, instead they are typehinted directly in the repositories. This is because each repository requires
its own transformer with the correct mapping. So if you want to provide your own transformer for the
ColorRepository
for instance, you’d need to overwrite the ColorTransformer
and pass along your custom object
to the ColorRepository
.
If you want to provide your own transform logic, which is defined in this package by the BaseTransformer
, you’d
have to add it to each custom implementation, or maybe use a trait in a smart way.
Custom value objects
If you want to keep the default mapping of the transformers as it is defined by this package, but you still want to use custom value objects, you’d still need to overwrite the transformers as they are.
Say you have a custom Color
value object that can work with the ColorTransformer
as it is, you’d still need to
overwrite the ColorTransformer
because the value object class name is hardcoded in the $dto
property:
<?php
class MyColorTransformer
{
public string $dto = MyCustomColorDTO::class;
}
The mapping options will still work the same as in the default ColorTransformer
. Now you van just pass this new
MyColorTransformer
to the ColorRepository
.
If you add your own value objects with the default transformer logic, please keep in mind that the value objects are created like this:
$object = new ValueObject(...$values);
. This means that each property should be a parameter in the constructor of your value object, otherwhise you’ll get an error likeUnknown named property 'xyz'
.