Skip to content

Commit df1406d

Browse files
feat: add convertEmptyToNull support for validateArray()
1 parent 8c2d317 commit df1406d

File tree

10 files changed

+1102
-946
lines changed

10 files changed

+1102
-946
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/vendor/
2-
/.idea/
2+
/.idea/
3+
composer.lock

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,53 @@ if ($validation->validateArray($data) === true) {
7272
}
7373
```
7474

75+
### Example 3: Converting Empty Strings to `null`
76+
77+
By default, when using `validate(ServerRequestInterface $request)`, the **convertEmptyToNull** option is automatically enabled.
78+
This ensures that all empty strings (`""`) are converted to `null` before validation.
79+
80+
When using `validateArray(array $data)` directly, you need to enable this option manually:
81+
82+
```php
83+
use PhpDevCommunity\Validator\Validation;
84+
use PhpDevCommunity\Validator\Assert\NotNull;
85+
use PhpDevCommunity\Validator\Assert\Item;
86+
use PhpDevCommunity\Validator\Assert\Alphabetic;
87+
88+
// Define validation rules
89+
$validation = new Validation([
90+
'person' => [new NotNull(), new Item([
91+
'first_name' => [new NotNull(), new Alphabetic()],
92+
'last_name' => [new NotNull(), new Alphabetic()],
93+
])]
94+
]);
95+
96+
// Example input with an empty string
97+
$validInput = [
98+
'person' => [
99+
'first_name' => '', // will be converted to null
100+
'last_name' => 'Doe'
101+
]
102+
];
103+
104+
// Manually enable conversion of "" to null
105+
$validation->convertEmptyToNull();
106+
107+
if ($validation->validateArray($validInput) === true) {
108+
echo "Data is valid!";
109+
} else {
110+
$errors = $validation->getErrors();
111+
echo "Validation errors: " . json_encode($errors, JSON_PRETTY_PRINT);
112+
}
113+
```
114+
115+
In this example:
116+
117+
* Before validation, empty strings are converted to `null`.
118+
* This prevents validators such as `NotNull()` from failing because of an empty string.
119+
* When using `validate($request)` with a PSR-7 request, this option is automatically enabled.
120+
121+
75122
### Additional Examples
76123

77124
Let's explore more examples covering various validators:

src/Assert/Collection.php

Lines changed: 82 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,82 @@
1-
<?php
2-
3-
declare(strict_types=1);
4-
5-
namespace PhpDevCommunity\Validator\Assert;
6-
7-
use PhpDevCommunity\Validator\Validation;
8-
use PhpDevCommunity\Validator\ValidationProcessor;
9-
use function ctype_alpha;
10-
11-
final class Collection extends AbstractValidator
12-
{
13-
private string $message = 'This value should be of type {{ type }}.';
14-
15-
/**
16-
* @param array<ValidatorInterface> $validators
17-
*/
18-
private array $validators;
19-
private array $errors = [];
20-
21-
/**
22-
* @param array<ValidatorInterface> $validators
23-
*/
24-
public function __construct(array $validators)
25-
{
26-
foreach ($validators as $validator) {
27-
if ($validator instanceof ValidatorInterface === false) {
28-
throw new \InvalidArgumentException(sprintf('The validator must be an instance of %s', ValidatorInterface::class));
29-
}
30-
}
31-
$this->validators = $validators;
32-
}
33-
public function validate($value): bool
34-
{
35-
if ($value === null) {
36-
return true;
37-
}
38-
39-
if (is_array($value) === false) {
40-
$this->error($this->message, ['value' => $value, 'type' => 'collection']);
41-
return false;
42-
}
43-
44-
$validationProcessor = new ValidationProcessor();
45-
$errors = [];
46-
foreach ($value as $key => $element) {
47-
$errors = array_merge($errors, $validationProcessor->process($this->validators, $key, $element));
48-
}
49-
50-
if ($errors !== []) {
51-
$this->errors = $errors;
52-
return false;
53-
}
54-
55-
return true;
56-
}
57-
58-
public function message(string $message): self
59-
{
60-
$this->message = $message;
61-
return $this;
62-
}
63-
64-
public function getErrors(): array
65-
{
66-
return $this->errors;
67-
}
68-
}
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpDevCommunity\Validator\Assert;
6+
7+
use PhpDevCommunity\Validator\Validation;
8+
use PhpDevCommunity\Validator\ValidationProcessor;
9+
use function ctype_alpha;
10+
11+
final class Collection extends AbstractValidator
12+
{
13+
private string $message = 'This value should be of type {{ type }}.';
14+
15+
/**
16+
* @param array<ValidatorInterface> $validators
17+
*/
18+
private array $validators;
19+
20+
private ValidationProcessor $validationProcessor;
21+
private array $errors = [];
22+
23+
/**
24+
* @param array<ValidatorInterface> $validators
25+
*/
26+
public function __construct(array $validators)
27+
{
28+
foreach ($validators as $validator) {
29+
if ($validator instanceof ValidatorInterface === false) {
30+
throw new \InvalidArgumentException(sprintf('The validator must be an instance of %s', ValidatorInterface::class));
31+
}
32+
}
33+
$this->validators = $validators;
34+
$this->validationProcessor = new ValidationProcessor();
35+
}
36+
public function convertEmptyToNull(): self
37+
{
38+
$this->validationProcessor->convertEmptyToNull();
39+
return $this;
40+
}
41+
42+
public function noConvertEmptyToNull(): self
43+
{
44+
$this->validationProcessor->noConvertEmptyToNull();
45+
return $this;
46+
}
47+
48+
public function validate($value): bool
49+
{
50+
if ($value === null) {
51+
return true;
52+
}
53+
54+
if (is_array($value) === false) {
55+
$this->error($this->message, ['value' => $value, 'type' => 'collection']);
56+
return false;
57+
}
58+
59+
$errors = [];
60+
foreach ($value as $key => $element) {
61+
$errors = array_merge($errors, $this->validationProcessor->process($this->validators, $key, $element));
62+
}
63+
64+
if ($errors !== []) {
65+
$this->errors = $errors;
66+
return false;
67+
}
68+
69+
return true;
70+
}
71+
72+
public function message(string $message): self
73+
{
74+
$this->message = $message;
75+
return $this;
76+
}
77+
78+
public function getErrors(): array
79+
{
80+
return $this->errors;
81+
}
82+
}

src/Assert/Item.php

Lines changed: 68 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,68 @@
1-
<?php
2-
3-
declare(strict_types=1);
4-
5-
namespace PhpDevCommunity\Validator\Assert;
6-
7-
use InvalidArgumentException;
8-
use PhpDevCommunity\Validator\Validation;
9-
10-
final class Item extends AbstractValidator
11-
{
12-
private string $message = 'This value should be of type {{ type }}.';
13-
private string $messageKeyNotExist = 'The key {{ value }} does not exist.';
14-
15-
private Validation $validation;
16-
private array $errors = [];
17-
18-
/**
19-
* @param array<string,ValidatorInterface[]> $validators
20-
*/
21-
public function __construct(array $validators)
22-
{
23-
$this->validation = new Validation($validators);
24-
}
25-
26-
public function validate($value): bool
27-
{
28-
if ($value === null) {
29-
return true;
30-
}
31-
32-
if (is_array($value) === false) {
33-
$this->error($this->message, ['value' => $value, 'type' => 'array']);
34-
return false;
35-
}
36-
37-
$this->validation->validateArray($value);
38-
if ($this->validation->getErrors() !== []) {
39-
$this->errors = $this->validation->getErrors();
40-
return false;
41-
}
42-
43-
return true;
44-
}
45-
46-
public function message(string $message): self
47-
{
48-
$this->message = $message;
49-
return $this;
50-
}
51-
52-
public function getErrors(): array
53-
{
54-
return $this->errors;
55-
}
56-
}
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpDevCommunity\Validator\Assert;
6+
7+
use InvalidArgumentException;
8+
use PhpDevCommunity\Validator\Validation;
9+
10+
final class Item extends AbstractValidator
11+
{
12+
private string $message = 'This value should be of type {{ type }}.';
13+
private string $messageKeyNotExist = 'The key {{ value }} does not exist.';
14+
15+
private Validation $validation;
16+
private array $errors = [];
17+
18+
/**
19+
* @param array<string,ValidatorInterface[]> $validators
20+
*/
21+
public function __construct(array $validators)
22+
{
23+
$this->validation = new Validation($validators);
24+
}
25+
26+
public function convertEmptyToNull(): self
27+
{
28+
$this->validation->convertEmptyToNull();
29+
return $this;
30+
}
31+
32+
public function noConvertEmptyToNull(): self
33+
{
34+
$this->validation->noConvertEmptyToNull();
35+
return $this;
36+
}
37+
38+
public function validate($value): bool
39+
{
40+
if ($value === null) {
41+
return true;
42+
}
43+
44+
if (is_array($value) === false) {
45+
$this->error($this->message, ['value' => $value, 'type' => 'array']);
46+
return false;
47+
}
48+
49+
$this->validation->validateArray($value);
50+
if ($this->validation->getErrors() !== []) {
51+
$this->errors = $this->validation->getErrors();
52+
return false;
53+
}
54+
55+
return true;
56+
}
57+
58+
public function message(string $message): self
59+
{
60+
$this->message = $message;
61+
return $this;
62+
}
63+
64+
public function getErrors(): array
65+
{
66+
return $this->errors;
67+
}
68+
}

0 commit comments

Comments
 (0)