Transforming data | laravel-data | Spatie

 SPATIE

  Laravel Data
===============

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-data](https://spatie.be/docs/laravel-data/v4)  As-a-resource  Transforming data

 Version   v4   v3   v2   v1

 Other versions for crawler [v4](https://spatie.be/docs/laravel-data/v4) [v3](https://spatie.be/docs/laravel-data/v3) [v2](https://spatie.be/docs/laravel-data/v2) [v1](https://spatie.be/docs/laravel-data/v1)

- [ Introduction ](https://spatie.be/docs/laravel-data/v4/introduction)
- [ Support us ](https://spatie.be/docs/laravel-data/v4/support-us)
- [ Requirements ](https://spatie.be/docs/laravel-data/v4/requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-data/v4/installation-setup)
- [ Third party packages ](https://spatie.be/docs/laravel-data/v4/third-party-packages)
- [ Questions and issues ](https://spatie.be/docs/laravel-data/v4/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-data/v4/changelog)
- [ About us ](https://spatie.be/docs/laravel-data/v4/about-us)

Getting started
---------------

- [ Quickstart ](https://spatie.be/docs/laravel-data/v4/getting-started/quickstart)

As a DTO
--------

- [ Creating a data object ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/creating-a-data-object)
- [ Nesting ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/nesting)
- [ Collections ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/collections)
- [ Abstract Data ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/abstract-data)
- [ Casts ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/casts)
- [ Optional properties ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/optional-properties)
- [ Mapping property names ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/mapping-property-names)
- [ Default values ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/defaults)
- [ Computed values ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/computed)
- [ From a request ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/request-to-data-object)
- [ From a model ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/model-to-data-object)
- [ Injecting property values ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/injecting-property-values)
- [ Factories ](https://spatie.be/docs/laravel-data/v4/as-a-data-transfer-object/factories)

Validation
----------

- [ Introduction ](https://spatie.be/docs/laravel-data/v4/validation/introduction)
- [ Auto rule inferring ](https://spatie.be/docs/laravel-data/v4/validation/auto-rule-inferring)
- [ Using validation attributes ](https://spatie.be/docs/laravel-data/v4/validation/using-validation-attributes)
- [ Manual rules ](https://spatie.be/docs/laravel-data/v4/validation/manual-rules)
- [ Working with the validator ](https://spatie.be/docs/laravel-data/v4/validation/working-with-the-validator)
- [ Nesting Data ](https://spatie.be/docs/laravel-data/v4/validation/nesting-data)
- [ Skipping validation ](https://spatie.be/docs/laravel-data/v4/validation/skipping-validation)

As a resource
-------------

- [ From data to array ](https://spatie.be/docs/laravel-data/v4/as-a-resource/from-data-to-array)
- [ From data to resource ](https://spatie.be/docs/laravel-data/v4/as-a-resource/from-data-to-resource)
- [ Mapping property names ](https://spatie.be/docs/laravel-data/v4/as-a-resource/mapping-property-names)
- [ Appending properties ](https://spatie.be/docs/laravel-data/v4/as-a-resource/appending-properties)
- [ Wrapping ](https://spatie.be/docs/laravel-data/v4/as-a-resource/wrapping)
- [ Including and excluding properties ](https://spatie.be/docs/laravel-data/v4/as-a-resource/lazy-properties)
- [ Transforming data ](https://spatie.be/docs/laravel-data/v4/as-a-resource/transformers)

Advanced usage
--------------

- [ Eloquent casting ](https://spatie.be/docs/laravel-data/v4/advanced-usage/eloquent-casting)
- [ Transforming to TypeScript ](https://spatie.be/docs/laravel-data/v4/advanced-usage/typescript)
- [ Working with dates ](https://spatie.be/docs/laravel-data/v4/advanced-usage/working-with-dates)
- [ Normalizers ](https://spatie.be/docs/laravel-data/v4/advanced-usage/normalizers)
- [ Pipeline ](https://spatie.be/docs/laravel-data/v4/advanced-usage/pipeline)
- [ Creating a cast ](https://spatie.be/docs/laravel-data/v4/advanced-usage/creating-a-cast)
- [ Creating a transformer ](https://spatie.be/docs/laravel-data/v4/advanced-usage/creating-a-transformer)
- [ Creating a rule inferrer ](https://spatie.be/docs/laravel-data/v4/advanced-usage/creating-a-rule-inferrer)
- [ Use with Inertia ](https://spatie.be/docs/laravel-data/v4/advanced-usage/use-with-inertia)
- [ Use with Livewire ](https://spatie.be/docs/laravel-data/v4/advanced-usage/use-with-livewire)
- [ Internal structures ](https://spatie.be/docs/laravel-data/v4/advanced-usage/internal-structures)
- [ Mapping rules ](https://spatie.be/docs/laravel-data/v4/advanced-usage/mapping-rules)
- [ Validation attributes ](https://spatie.be/docs/laravel-data/v4/advanced-usage/validation-attributes)
- [ Get data from a class quickly ](https://spatie.be/docs/laravel-data/v4/advanced-usage/get-data-from-a-class-quickly)
- [ Performance ](https://spatie.be/docs/laravel-data/v4/advanced-usage/performance)
- [ Commands ](https://spatie.be/docs/laravel-data/v4/advanced-usage/commands)
- [ Traits and interfaces ](https://spatie.be/docs/laravel-data/v4/advanced-usage/traits-and-interfaces)
- [ In Packages ](https://spatie.be/docs/laravel-data/v4/advanced-usage/in-packages)
- [ Available property mappers ](https://spatie.be/docs/laravel-data/v4/advanced-usage/available-property-mappers)

 Transforming data
=================

###  On this page

1. [ Local transformers ](#content-local-transformers)
2. [ Global transformers ](#content-global-transformers)
3. [ Getting a data object without transforming ](#content-getting-a-data-object-without-transforming)
4. [ Getting a data object (on steroids) ](#content-getting-a-data-object-on-steroids)
5. [ Transformation depth ](#content-transformation-depth)

Transformers allow you to transform complex types to simple types. This is useful when you want to transform a data object to an array or JSON.

No complex transformations are required for the default types (string, bool, int, float, enum and array), but special types like `Carbon` or a Laravel Model will need extra attention.

Transformers are simple classes that will convert a such complex types to something simple like a `string` or `int`. For example, we can transform a `Carbon` object to `16-05-1994`, `16-05-1994T00:00:00+00` or something completely different.

There are two ways you can define transformers: locally and globally.

Local transformers
--------------------------------------------------------------------------------------------------------------

When you want to transform a specific property, you can use an attribute with the transformer you want to use:

```
class ArtistData extends Data{
    public function __construct(
        public string $name,
        #[WithTransformer(DateTimeInterfaceTransformer::class)]
        public Carbon $birth_date
    ) {
    }
}
```

The `DateTimeInterfaceTransformer` is shipped with the package and will transform objects of type `Carbon`, `CarbonImmutable`, `DateTime` and `DateTimeImmutable` to a string.

The format used for converting the date to string can be set in the `data.php` config file. It is also possible to manually define a format:

```
class ArtistData extends Data{
    public function __construct(
        public string $name,
        #[WithTransformer(DateTimeInterfaceTransformer::class, format: 'm-Y')]
        public Carbon $birth_date
    ) {
    }
}
```

Next to a `DateTimeInterfaceTransformer` the package also ships with an `ArrayableTransformer` that transforms an `Arrayable` object to an array.

It is possible to create transformers for your specific types. You can find more info [here](/docs/laravel-data/v4/advanced-usage/creating-a-transformer).

Global transformers
-----------------------------------------------------------------------------------------------------------------

Global transformers are defined in the `data.php` config file and are used when no local transformer for a property was added. By default, there are two transformers:

```
use Illuminate\Contracts\Support\Arrayable;
use Spatie\LaravelData\Transformers\ArrayableTransformer;
use Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer;

/*
 * Global transformers will take complex types and transform them into simple
 * types.
 */
'transformers' => [
    DateTimeInterface::class => DateTimeInterfaceTransformer::class,
    Arrayable::class => ArrayableTransformer::class,
],
```

The package will look through these global transformers and tries to find a suitable transformer. You can define transformers for:

- a **specific implementation** (e.g. CarbonImmutable)
- an **interface** (e.g. DateTimeInterface)
- a **base class** (e.g. Enum)

Getting a data object without transforming
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

It is possible to get an array representation of a data object without transforming the properties. This means `Carbon` objects won't be transformed into strings. And also, nested data objects and `DataCollection`s won't be transformed into arrays. You can do this by calling the `all` method on a data object like this:

```
ArtistData::from($artist)->all();
```

Getting a data object (on steroids)
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Internally the package uses the `transform` method for operations like `toArray`, `all`, `toJson` and so on. This method is highly configurable, when calling it without any arguments it will behave like the `toArray` method:

```
ArtistData::from($artist)->transform();
```

Producing the following result:

```
[
    'name' => 'Rick Astley',
    'birth_date' => '06-02-1966',
]
```

It is possible to disable the transformation of values, which will make the `transform` method behave like the `all` method:

```
use Spatie\LaravelData\Support\Transformation\TransformationContext;

ArtistData::from($artist)->transform(
    TransformationContextFactory::create()->withoutValueTransformation()
);
```

Outputting the following array:

```
[
    'name' => 'Rick Astley',
    'birth_date' => Carbon::parse('06-02-1966'),
]
```

The [mapping of property names](/docs/laravel-data/v4/as-a-resource/mapping-property-names) can also be disabled:

```
ArtistData::from($artist)->transform(
    TransformationContextFactory::create()->withoutPropertyNameMapping()
);
```

It is possible to enable [wrapping](/docs/laravel-data/v4/as-a-resource/wrapping-data) the data object:

```
use Spatie\LaravelData\Support\Wrapping\WrapExecutionType;

ArtistData::from($artist)->transform(
    TransformationContextFactory::create()->withWrapping()
);
```

Outputting the following array:

```
[
    'data' => [
        'name' => 'Rick Astley',
        'birth_date' => '06-02-1966',
    ],
]
```

You can also add additional global transformers as such:

```
ArtistData::from($artist)->transform(
    TransformationContextFactory::create()->withGlobalTransformer(
        'string',
        StringToUpperTransformer::class
    )
);
```

Transformation depth
--------------------------------------------------------------------------------------------------------------------

When transforming a complicated structure of nested data objects it is possible that an infinite loop is created of data objects including each other. To prevent this, a transformation depth can be set, when that depth is reached when transforming, either an exception will be thrown or an empty array is returned, stopping the transformation.

This transformation depth can be set globally in the `data.php` config file:

```
'max_transformation_depth' => 20,
```

Setting the transformation depth to `null` will disable the transformation depth check:

```
'max_transformation_depth' => null,
```

It is also possible if a `MaxTransformationDepthReached` exception should be thrown or an empty array should be returned:

```
'throw_when_max_transformation_depth_reached' => true,
```

It is also possible to set the transformation depth on a specific transformation by using a `TransformationContextFactory`:

```
ArtistData::from($artist)->transform(
    TransformationContextFactory::create()->maxDepth(20)
);
```

By default, an exception will be thrown when the maximum transformation depth is reached. This can be changed to return an empty array as such:

```
ArtistData::from($artist)->transform(
    TransformationContextFactory::create()->maxDepth(20, throw: false)
);
```
