Introduction | laravel-data | Spatie

 SPATIE

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

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-data](https://spatie.be/docs/laravel-data/v4)  Validation  Introduction

 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)

 Introduction
============

###  On this page

1. [ When does validation happen? ](#content-when-does-validation-happen)
2. [ A quick glance at the validation functionality ](#content-a-quick-glance-at-the-validation-functionality)
3. [ Validation of nested data objects ](#content-validation-of-nested-data-objects)
4. [ Validation of nested data collections ](#content-validation-of-nested-data-collections)
5. [ Default values ](#content-default-values)
6. [ Mapping property names ](#content-mapping-property-names)
7. [ Retrieving validation rules for a data object ](#content-retrieving-validation-rules-for-a-data-object)

Laravel data, allows you to create data objects from all sorts of data. One of the most common ways to create a data object is from a request, and the data from a request cannot always be trusted.

That's why it is possible to validate the data before creating the data object. You can validate requests but also arrays and other structures.

The package will try to automatically infer validation rules from the data object, so you don't have to write them yourself. For example, a `?string` property will automatically have the `nullable` and `string` rules.

### Important notice

Validation is probably one of the coolest features of this package, but it is also the most complex one. We'll try to make it as straightforward as possible to validate data, but in the end, the Laravel validator was not written to be used in this way. So there are some limitations and quirks you should be aware of.

In a few cases it might be easier to just create a custom request class with validation rules and then call `toArray` on the request to create a data object than trying to validate the data with this package.

When does validation happen?
------------------------------------------------------------------------------------------------------------------------------------------

Validation will always happen BEFORE a data object is created, once a data object is created, it is assumed that the data is valid.

At the moment, there isn't a way to validate data objects, so you should implement this logic yourself. We're looking into ways to make this easier in the future.

Validation runs automatically in the following cases:

- When injecting a data object somewhere and the data object gets created from the request
- When calling the `from` method on a data object with a request

On all other occasions, validation won't run automatically. You can always validate the data manually by calling the `validate` method on a data object:

```
SongData::validate(
    ['title' => 'Never gonna give you up']
); // ValidationException will be thrown because 'artist' is missing
```

When you also want to create the object after validation was successful you can use `validateAndCreate`:

```
SongData::validateAndCreate(
    ['title' => 'Never gonna give you up', 'artist' => 'Rick Astley']
); // returns a SongData object
```

### Validate everything

It is possible to validate all payloads injected or passed to the `from` method by setting the `validation_strategy` config option to `Always`:

```
'validation_strategy' => \Spatie\LaravelData\Support\Creation\ValidationStrategy::Always->value,
```

Completely disabling validation can be done by setting the `validation_strategy` config option to `Disabled`:

```
'validation_strategy' => \Spatie\LaravelData\Support\Creation\ValidationStrategy::Disabled->value,
```

If you require a more fine-grained control over when validation should happen, you can use [data factories](/docs/laravel-data/v4/as-a-data-transfer-object/factories) to manually specify the validation strategy.

A quick glance at the validation functionality
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

We've got a lot of documentation about validation and we suggest you read it all, but if you want to get a quick glance at the validation functionality, here's a quick overview:

### Auto rule inferring

The package will automatically infer validation rules from the data object. For example, for the following data class:

```
class ArtistData extends Data{
    public function __construct(
        public string $name,
        public int $age,
        public ?string $genre,
    ) {
    }
}
```

The package will generate the following validation rules:

```
[
    'name' => ['required', 'string'],
    'age' => ['required', 'integer'],
    'genre' => ['nullable', 'string'],
]
```

The package follows an algorithm to infer rules from the data object. You can read more about it [here](/docs/laravel-data/v4/validation/auto-rule-inferring).

### Validation attributes

It is possible to add extra rules as attributes to properties of a data object:

```
class SongData extends Data
{
    public function __construct(
        public string $title,
        #[Max(20)]
        public string $artist,
    ) {
    }
}
```

When you provide an artist with a length of more than 20 characters, the validation will fail.

There's a complete [chapter](/docs/laravel-data/v4/validation/using-validation-attributes) dedicated to validation attributes.

### Manual rules

Sometimes you want to add rules manually, this can be done as such:

```
class SongData extends Data
{
    public function __construct(
        public string $title,
        public string $artist,
    ) {
    }

    public static function rules(): array
    {
        return [
            'title' => ['required', 'string'],
            'artist' => ['required', 'string'],
        ];
    }
}
```

You can read more about manual rules in its [dedicated chapter](/docs/laravel-data/v4/validation/manual-rules).

### Using the container

You can resolve a data object from the container.

```
app(SongData::class);
```

We resolve a data object from the container, its properties will already be filled by the values of the request with matching key names. If the request contains data that is not compatible with the data object, a validation exception will be thrown.

### Working with the validator

We provide a few points where you can hook into the validation process. You can read more about it in the [dedicated chapter](/docs/laravel-data/v4/validation/working-with-the-validator).

It is for example to:

- overwrite validation messages &amp; attributes
- overwrite the validator itself
- overwrite the redirect when validation fails
- allow stopping validation after a failure
- overwrite the error bag

### Authorizing a request

Just like with Laravel requests, it is possible to authorize an action for certain people only:

```
class SongData extends Data
{
    public function __construct(
        public string $title,
        public string $artist,
    ) {
    }

    public static function authorize(): bool
    {
        return Auth::user()->name === 'Ruben';
    }
}
```

If the method returns `false`, then an `AuthorizationException` is thrown.

Validation of nested data objects
-----------------------------------------------------------------------------------------------------------------------------------------------------------

When a data object is nested inside another data object, the validation rules will also be generated for that nested object.

```
class SingleData{
    public function __construct(
        public ArtistData $artist,
        public SongData $song,
    ) {
    }
}
```

The validation rules for this class will be:

```
[
    'artist' => ['array'],
    'artist.name' => ['required', 'string'],
    'artist.age' => ['required', 'integer'],
    'artist.genre' => ['nullable', 'string'],
    'song' => ['array'],
    'song.title' => ['required', 'string'],
    'song.artist' => ['required', 'string'],
]
```

There are a few quirky things to keep in mind when working with nested data objects, you can read all about it [here](/docs/laravel-data/v4/validation/nesting-data).

Validation of nested data collections
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Let's say we want to create a data object like this from a request:

```
class AlbumData extends Data
{
    /**
    * @param array $songs
    */
    public function __construct(
        public string $title,
        public array $songs,
    ) {
    }
}
```

Since the `SongData` has its own validation rules, the package will automatically apply them when resolving validation rules for this object.

In this case the validation rules for `AlbumData` would look like this:

```
[
    'title' => ['required', 'string'],
    'songs' => ['required', 'array'],
    'songs.*.title' => ['required', 'string'],
    'songs.*.artist' => ['required', 'string'],
]
```

More info about nested data collections can be found [here](/docs/laravel-data/v4/validation/nesting-data).

Default values
--------------------------------------------------------------------------------------------------

When you've set some default values for a data object, the validation rules will only be generated if something else than the default is provided.

For example, when we have this data object:

```
class SongData extends Data
{
    public function __construct(
        public string $title = 'Never Gonna Give You Up',
        public string $artist = 'Rick Astley',
    ) {
    }
}
```

And we try to validate the following data:

```
SongData::validate(
    ['title' => 'Giving Up On Love']
);
```

Then the validation rules will be:

```
[
    'title' => ['required', 'string'],
]
```

Mapping property names
--------------------------------------------------------------------------------------------------------------------------

When mapping property names, the validation rules will be generated for the mapped property name:

```
class SongData extends Data
{
    public function __construct(
        #[MapInputName('song_title')]
        public string $title,
    ) {
    }
}
```

The validation rules for this class will be:

```
[
    'song_title' => ['required', 'string'],
]
```

There's one small catch when the validation fails; the error message will be for the original property name, not the mapped property name. This is a small quirk we hope to solve as soon as possible.

Retrieving validation rules for a data object
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

You can retrieve the validation rules a data object will generate as such:

```
AlbumData::getValidationRules($payload);
```

This will produce the following array with rules:

```
[
    'title' => ['required', 'string'],
    'songs' => ['required', 'array'],
    'songs.*.title' => ['required', 'string'],
    'songs.*.artist' => ['required', 'string'],
]
```

### Payload requirement

We suggest always providing a payload when generating validation rules. Because such a payload is used to determine which rules will be generated and which can be skipped.
