Skip to content

Commit

Permalink
Allow to specify attribute name in type class
Browse files Browse the repository at this point in the history
  • Loading branch information
azzumed committed Aug 19, 2024
1 parent 16a842a commit 3fee7d1
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
27 changes: 27 additions & 0 deletions docs/validation/working-with-the-validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,33 @@ class SongData extends Data
}
```

### Defining attribute in type

If you want to define attribute name in the type itself, you can implement the `HasValidationAttributeName` interface:

```php
class SongData extends Data
{
public function __construct(
public Title $title,
) {
}
}

class Title implements HasValidationAttributeName
{
public function __construct(
public string $value,
) {
}

public static function validationAttributeName(): string
{
return 'Song title';
}
}
```

## Overwriting other validation functionality

Next to overwriting the validator, attributes and messages it is also possible to overwrite the following functionality.
Expand Down
8 changes: 8 additions & 0 deletions src/Contracts/HasValidationAttributeName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Spatie\LaravelData\Contracts;

interface HasValidationAttributeName
{
public static function validationAttributeName(): string;
}
10 changes: 10 additions & 0 deletions src/Resolvers/DataValidationMessagesAndAttributesResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Spatie\LaravelData\Resolvers;

use Illuminate\Support\Arr;
use Spatie\LaravelData\Contracts\HasValidationAttributeName;
use Spatie\LaravelData\Support\DataConfig;
use Spatie\LaravelData\Support\Types\NamedType;
use Spatie\LaravelData\Support\Validation\ValidationPath;

class DataValidationMessagesAndAttributesResolver
Expand Down Expand Up @@ -62,6 +64,14 @@ public function execute(

continue;
}

if ($dataProperty->type->type instanceof NamedType) {
$typeClass = $dataProperty->type->type->name;

if (is_a($typeClass, HasValidationAttributeName::class, true)) {
$attributes[$propertyPath->get()] = app()->call([$typeClass, 'validationAttributeName']);
}
}
}

if (method_exists($class, 'messages')) {
Expand Down
31 changes: 27 additions & 4 deletions tests/ValidationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use Spatie\LaravelData\Attributes\Validation\StringType;
use Spatie\LaravelData\Attributes\Validation\Unique;
use Spatie\LaravelData\Attributes\WithoutValidation;
use Spatie\LaravelData\Contracts\HasValidationAttributeName;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
Expand Down Expand Up @@ -1921,10 +1922,24 @@ public static function attributes(): array
});

it('can manually set collected validation attributes ', function () {
class Address implements HasValidationAttributeName {
public function __construct(
public string $value,
) {
}

public static function validationAttributeName(): string
{
return 'Home address';
}
}

class TestCollectedValidationAttributesData extends Data
{
public string $name;

public Address $address;

public static function attributes(): array
{
return [
Expand All @@ -1940,12 +1955,20 @@ public static function attributes(): array

DataValidationAsserter::for($data)
->assertAttributes(
['collection.*.name' => 'rickster'],
payload: ['collection' => [['name' => null]]],
[
'collection.*.name' => 'rickster',
'collection.*.address' => 'Home address',
],
payload: ['collection' => [['name' => null, 'address' => new Address('')]]],
)
->assertErrors(
payload: ['collection' => [['name' => null]]],
errors: ['collection.0.name' => [__('validation.required', ['attribute' => 'rickster'])]]
payload: [
'collection' => [['name' => null, 'address' => new Address('')]]
],
errors: [
'collection.0.name' => [__('validation.required', ['attribute' => 'rickster'])],
'collection.0.address' => [__('validation.required', ['attribute' => 'Home address'])],
]
);
})->skip('Feature not supported by Laravel at the moment');

Expand Down

0 comments on commit 3fee7d1

Please sign in to comment.