Extending mapper
Data mapper can be extended to understand other classes or by using first-hand crafted classes.
There is 2 ways of extending the data mapper.
Use MapeableObject interface
There are cases where there is classes created within the Laravel application (not being 3rd party) or some extensions over other 3rd party classes, in these cases you can use the interface with the mappingFrom
method:
<?php
use OpenSoutheners\LaravelDataMapper\Contracts\MapeableObject;
use OpenSoutheners\LaravelDataMapper\MappingValue;
class MyMapeableClass implements MapeableObject
{
public function mappingFrom(MappingValue $mappingValue): void
{
$mappedValue->data = /** mapping logic here */;
}
}
The MappingValue
class has this data where it stores original and modified values, mapped values should be stored on this so they will be returned by the data mapper.
Creating a DataMapper class
When treating with 3rd party classes that aren't extended or modified on the Laravel application this can be used to teach the mapper about these new types.
<?php
namespace App\Mappers;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Illuminate\Support\Carbon;
use OpenSoutheners\LaravelDataMapper\MappingValue;
final class CarbonDataMapper extends DataMapper
{
/**
* Assert that this mapper resolves property with types given.
*/
public function assert(MappingValue $mappingValue): bool
{
return in_array(gettype($mappingValue->data), ['string', 'integer'], true)
&& ($mappingValue->preferredTypeClass === CarbonInterface::class
|| is_subclass_of($mappingValue->preferredTypeClass, CarbonInterface::class));
}
/**
* Resolve mapper that runs once assert returns true.
*/
public function resolve(MappingValue $mappingValue): void
{
$mappingValue->data = match (true) {
gettype($mappingValue->data) === 'integer' || is_numeric($mappingValue->data) => Carbon::createFromTimestamp($mappingValue->data),
default => Carbon::make($mappingValue->data),
};
if ($mappingValue->preferredTypeClass === CarbonImmutable::class) {
$mappingValue->data = $mappingValue->data->toImmutable();
}
}
}
This is the same as the interface method above but adding the assert method which ensures all types and data is right.
Take in mind this will be run below other mappers using similar assert logic, in case this doesn't get there you should register them in a different order but at your own risk of breaking some package default functionality.
Now this mapper class should be registered in the boot
method of any of your application service provider:
use OpenSoutheners\LaravelDataMapper\ServiceProvider;
use App\Mappers\CarbonDataMapper;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
ServiceProvider::registerMapper(CarbonDataMapper::class);
}
Last updated
Was this helpful?