Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a787da8
Initial plan
Copilot Jan 1, 2026
3fcbb2f
Add ToArrayOfIntegers attribute and resolver with tests
Copilot Jan 1, 2026
97d3fe1
Improve documentation for ToArrayOfIntegers
Copilot Jan 1, 2026
6866db0
Revert accidental composer.json change
Copilot Jan 1, 2026
51ea93e
Remove stdClass test case that generates PHP warning
Copilot Jan 8, 2026
c2a3fe1
Apply fixes from StyleCI
StyleCIBot Jan 8, 2026
c9360b8
Add CHANGELOG entry and documentation for ToArrayOfIntegers
Copilot Jan 8, 2026
8980060
Update docs translation
Copilot Jan 8, 2026
d2d042d
Optimize ToArrayOfIntegersResolver by using inline cast
Copilot Jan 8, 2026
192afff
Remove Russian translation for ToArrayOfIntegers
Copilot Jan 12, 2026
1addd53
Update docs translation
Copilot Jan 12, 2026
bd52c6f
Add string splitting functionality to ToArrayOfIntegers
Copilot Jan 12, 2026
c8fb372
Apply fixes from StyleCI
StyleCIBot Jan 12, 2026
718ee63
Update docs translation
samdark Jan 12, 2026
a77de8a
Fix ToArrayOfIntegers to remove separator when splitResolvedValue is …
Copilot Jan 14, 2026
49287e7
Make test data more readable by adding keys
samdark Jan 15, 2026
f49249d
More readability for tests, adjust tests, fix behavior
samdark Jan 15, 2026
f1b0ae7
Add edge cases
samdark Jan 15, 2026
2610e72
Merge branch 'master' into copilot/add-to-array-of-integers
samdark Jan 15, 2026
b7ab47a
Fix rector and bc
samdark Jan 15, 2026
bd51684
Apply PHP CS Fixer and Rector changes (CI)
samdark Jan 15, 2026
9208b95
Keep empty integer items when casting
Copilot May 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/bc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.1']
['8.3']
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 1.6.4 under development

- New #116: Add `ToArrayOfIntegers` parameter attribute (@samdark)
- Enh #117: Explicitly import functions and constants in "use" section (@mspirkov)

## 1.6.3 December 16, 2025
Expand Down
26 changes: 26 additions & 0 deletions docs/guide/en/typecasting.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,29 @@ Attribute parameters:
- `splitResolvedValue` — split resolved value by separator (boolean, default `true`);
- `separator` — the boundary string (default, `\R`), it's a part of regular expression so should be taken into account
or properly escaped with `preg_quote()`.

### `ToArrayOfIntegers`

Use `ToArrayOfIntegers` attribute to cast a value to an array of integers:

```php
use Yiisoft\Hydrator\Attribute\Parameter\ToArrayOfIntegers;

final class Post
{
#[ToArrayOfIntegers]
public array $ratings = [];
}
```

If the resolved value is iterable, each element will be cast to an integer. For example, array `['1', '2', '3']` will be
converted to `[1, 2, 3]`.

If the resolved value is not iterable, it will be cast to a string, split by separator, and then each element will be
cast to an integer. For example, string `'1,2,3'` will be converted to `[1, 2, 3]`.

Attribute parameters:

- `splitResolvedValue` — split non-array resolved value by separator (boolean, default `true`);
- `separator` — the boundary string (default `,`), it's a part of regular expression so should be taken into account
or properly escaped with `preg_quote()`.
30 changes: 30 additions & 0 deletions docs/guide/ru/typecasting.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,33 @@ final class Post
- `separator` — символ перевода строки (по умолчанию, `\R`). Это часть
регулярного выражения, поэтому ее следует учитывать или правильно
экранировать с помощью `preg_quote()`.

### `ToArrayOfIntegers`

Use `ToArrayOfIntegers` attribute to cast a value to an array of integers:

```php
use Yiisoft\Hydrator\Attribute\Parameter\ToArrayOfIntegers;

final class Post
{
#[ToArrayOfIntegers]
public array $ratings = [];
}
```

If the resolved value is iterable, each element will be cast to an
integer. For example, array `['1', '2', '3']` will be converted to `[1, 2,
3]`.

If the resolved value is not iterable, it will be cast to a string, split by
separator, and then each element will be cast to an integer. For example,
string `'1,2,3'` will be converted to `[1, 2, 3]`.

Параметры атрибута:

- `splitResolvedValue` — split non-array resolved value by separator
(boolean, default `true`);
- `separator` — the boundary string (default `,`), it's a part of regular
expression so should be taken into account or properly escaped with
`preg_quote()`.
68 changes: 67 additions & 1 deletion docs/po/typecasting.md/ru/typecasting.md.ru.po
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2025-06-18 12:27+0000\n"
"POT-Creation-Date: 2026-01-12 22:34+0000\n"
"PO-Revision-Date: 2025-03-01 15:15+0500\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
Expand Down Expand Up @@ -577,3 +577,69 @@ msgstr "`splitResolvedValue` — разделить значения по раз
#: guide/en/typecasting.md
msgid "`separator` — the boundary string (default, `\\R`), it's a part of regular expression so should be taken into account or properly escaped with `preg_quote()`."
msgstr "`separator` — символ перевода строки (по умолчанию, `\\R`). Это часть регулярного выражения, поэтому ее следует учитывать или правильно экранировать с помощью `preg_quote()`."

#. type: Title ###
#: guide/en/typecasting.md
#, fuzzy, no-wrap
#| msgid "`ToArrayOfStrings`"
msgid "`ToArrayOfIntegers`"
msgstr "`ToArrayOfStrings`"

#. type: Plain text
#: guide/en/typecasting.md
#, fuzzy
#| msgid "Use `ToArrayOfStrings` attribute to cast a value to an array of strings:"
msgid "Use `ToArrayOfIntegers` attribute to cast a value to an array of integers:"
msgstr "Используйте атрибут `ToArrayOfStrings` для приведения значения к массиву строк:"

#. type: Fenced code block (php)
#: guide/en/typecasting.md
#, fuzzy, no-wrap
#| msgid ""
#| "use Yiisoft\\Hydrator\\Attribute\\Parameter\\ToArrayOfStrings;\n"
#| "\n"
#| "final class Post\n"
#| "{\n"
#| " #[ToArrayOfStrings(separator: ',')]\n"
#| " public array $tags = []; \n"
#| "}\n"
msgid ""
"use Yiisoft\\Hydrator\\Attribute\\Parameter\\ToArrayOfIntegers;\n"
"\n"
"final class Post\n"
"{\n"
" #[ToArrayOfIntegers]\n"
" public array $ratings = []; \n"
"}\n"
msgstr ""
"use Yiisoft\\Hydrator\\Attribute\\Parameter\\ToArrayOfStrings;\n"
"\n"
"final class Post\n"
"{\n"
" #[ToArrayOfStrings(separator: ',')]\n"
" public array $tags = []; \n"
"}\n"

#. type: Plain text
#: guide/en/typecasting.md
msgid "If the resolved value is iterable, each element will be cast to an integer. For example, array `['1', '2', '3']` will be converted to `[1, 2, 3]`."
msgstr ""

#. type: Plain text
#: guide/en/typecasting.md
msgid "If the resolved value is not iterable, it will be cast to a string, split by separator, and then each element will be cast to an integer. For example, string `'1,2,3'` will be converted to `[1, 2, 3]`."
msgstr ""

#. type: Bullet: '- '
#: guide/en/typecasting.md
#, fuzzy
#| msgid "`splitResolvedValue` — split resolved value by separator (boolean, default `true`);"
msgid "`splitResolvedValue` — split non-array resolved value by separator (boolean, default `true`);"
msgstr "`splitResolvedValue` — разделить значения по разделителю (логическое значение, по умолчанию `true`);"

#. type: Bullet: '- '
#: guide/en/typecasting.md
#, fuzzy
#| msgid "`separator` — the boundary string (default, `\\R`), it's a part of regular expression so should be taken into account or properly escaped with `preg_quote()`."
msgid "`separator` — the boundary string (default `,`), it's a part of regular expression so should be taken into account or properly escaped with `preg_quote()`."
msgstr "`separator` — символ перевода строки (по умолчанию, `\\R`). Это часть регулярного выражения, поэтому ее следует учитывать или правильно экранировать с помощью `preg_quote()`."
57 changes: 56 additions & 1 deletion docs/po/typecasting.md/typecasting.md.pot
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2025-06-18 12:27+0000\n"
"POT-Creation-Date: 2026-01-12 22:34+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -409,3 +409,58 @@ msgid ""
"expression so should be taken into account or properly escaped with "
"`preg_quote()`."
msgstr ""

#. type: Title ###
#: guide/en/typecasting.md
#, no-wrap
msgid "`ToArrayOfIntegers`"
msgstr ""

#. type: Plain text
#: guide/en/typecasting.md
msgid ""
"Use `ToArrayOfIntegers` attribute to cast a value to an array of integers:"
msgstr ""

#. type: Fenced code block (php)
#: guide/en/typecasting.md
#, no-wrap
msgid ""
"use Yiisoft\\Hydrator\\Attribute\\Parameter\\ToArrayOfIntegers;\n"
"\n"
"final class Post\n"
"{\n"
" #[ToArrayOfIntegers]\n"
" public array $ratings = []; \n"
"}\n"
msgstr ""

#. type: Plain text
#: guide/en/typecasting.md
msgid ""
"If the resolved value is iterable, each element will be cast to an integer. "
"For example, array `['1', '2', '3']` will be converted to `[1, 2, 3]`."
msgstr ""

#. type: Plain text
#: guide/en/typecasting.md
msgid ""
"If the resolved value is not iterable, it will be cast to a string, split by "
"separator, and then each element will be cast to an integer. For example, "
"string `'1,2,3'` will be converted to `[1, 2, 3]`."
msgstr ""

#. type: Bullet: '- '
#: guide/en/typecasting.md
msgid ""
"`splitResolvedValue` — split non-array resolved value by separator (boolean, "
"default `true`);"
msgstr ""

#. type: Bullet: '- '
#: guide/en/typecasting.md
msgid ""
"`separator` — the boundary string (default `,`), it's a part of regular "
"expression so should be taken into account or properly escaped with "
"`preg_quote()`."
msgstr ""
1 change: 1 addition & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
NewInInitializerRector::class,
ReadOnlyPropertyRector::class,
__DIR__ . '/tests/Support/Classes/SimpleClass.php',
__DIR__ . '/tests/TestEnvironments/Php84/Hydrator/PublicPrivateSetProperty/Figure.php'
]);
};
30 changes: 30 additions & 0 deletions src/Attribute/Parameter/ToArrayOfIntegers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Hydrator\Attribute\Parameter;

use Attribute;

/**
* Casts the resolved value to array of integers.
*/
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER | Attribute::IS_REPEATABLE)]
final class ToArrayOfIntegers implements ParameterAttributeInterface
{
/**
* @param bool $splitResolvedValue Split non-array resolved value to array of strings by {@see $separator}
* before casting each element to integer.
* @param string $separator The boundary string. It is a part of regular expression
* so should be taken into account or properly escaped with {@see preg_quote()}.
*/
public function __construct(
public readonly bool $splitResolvedValue = true,
public readonly string $separator = ',',
) {}

public function getResolver(): string
{
return ToArrayOfIntegersResolver::class;
}
}
64 changes: 64 additions & 0 deletions src/Attribute/Parameter/ToArrayOfIntegersResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Hydrator\Attribute\Parameter;

use Stringable;
use Yiisoft\Hydrator\AttributeHandling\Exception\UnexpectedAttributeException;
use Yiisoft\Hydrator\AttributeHandling\ParameterAttributeResolveContext;
use Yiisoft\Hydrator\Result;

use function is_scalar;
use function is_string;

final class ToArrayOfIntegersResolver implements ParameterAttributeResolverInterface
{
public function getParameterValue(
ParameterAttributeInterface $attribute,
ParameterAttributeResolveContext $context,
): Result {
if (!$attribute instanceof ToArrayOfIntegers) {
throw new UnexpectedAttributeException(ToArrayOfIntegers::class, $attribute);
}

if (!$context->isResolved()) {
return Result::fail();
}

$resolvedValue = $context->getResolvedValue();
if (is_iterable($resolvedValue)) {
$array = [];
foreach ($resolvedValue as $value) {
$array[] = (int) $value;
}
} else {
$value = $this->castValueToString($resolvedValue);
if ($attribute->splitResolvedValue) {
$array = [];
if (trim($value) !== '') {

Check warning on line 39 in src/Attribute/Parameter/ToArrayOfIntegersResolver.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "UnwrapTrim": @@ @@ $value = $this->castValueToString($resolvedValue); if ($attribute->splitResolvedValue) { $array = []; - if (trim($value) !== '') { + if ($value !== '') { /** * @var string[] $stringArray We assume valid regular expression is used here, so `preg_split()` always returns * an array of strings.
/**
* @var string[] $stringArray We assume valid regular expression is used here, so `preg_split()` always returns
* an array of strings.
*/
$stringArray = preg_split('~' . $attribute->separator . '~u', $value);

foreach ($stringArray as $item) {
$array[] = (int) $item;
}
}
} elseif (trim($value) === '') {

Check warning on line 50 in src/Attribute/Parameter/ToArrayOfIntegersResolver.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "UnwrapTrim": @@ @@ $array[] = (int) $item; } } - } elseif (trim($value) === '') { + } elseif ($value === '') { $array = []; } else { $array = [(int) $value];
$array = [];
} else {
$array = [(int) $value];
}
}

return Result::success($array);
}

private function castValueToString(mixed $value): string
{
return is_scalar($value) || $value instanceof Stringable ? (string) $value : '';

Check warning on line 62 in src/Attribute/Parameter/ToArrayOfIntegersResolver.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "LogicalOrAllSubExprNegation": @@ @@ private function castValueToString(mixed $value): string { - return is_scalar($value) || $value instanceof Stringable ? (string) $value : ''; + return !is_scalar($value) || !$value instanceof Stringable ? (string) $value : ''; } }

Check warning on line 62 in src/Attribute/Parameter/ToArrayOfIntegersResolver.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "InstanceOf_": @@ @@ private function castValueToString(mixed $value): string { - return is_scalar($value) || $value instanceof Stringable ? (string) $value : ''; + return is_scalar($value) || !$value instanceof Stringable ? (string) $value : ''; } }
}
}
Loading
Loading