> For the complete documentation index, see [llms.txt](https://docs.opensoutheners.com/oss/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opensoutheners.com/oss/laravel-data-mapper/advanced/extending-mapper.md).

# 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
<?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
<?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.

{% hint style="warning" %}
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.
{% endhint %}

Now this mapper class should be registered in the `boot` method of any of your application service provider:

```php
use OpenSoutheners\LaravelDataMapper\ServiceProvider;
use App\Mappers\CarbonDataMapper;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    ServiceProvider::registerMapper(CarbonDataMapper::class);
}
```

{% hint style="info" %}
This package makes extensive use of [Symfony's PropertyInfo](https://symfony.com/doc/current/components/property_info.html) package which analyses the types of each class/object property (these are stored on the `MappingValue` object passed on each mapping method).
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.opensoutheners.com/oss/laravel-data-mapper/advanced/extending-mapper.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
