Skip to content

Commit

Permalink
CollectionOfCaster
Browse files Browse the repository at this point in the history
  • Loading branch information
fab2s committed Apr 28, 2024
1 parent b58f187 commit 840e810
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 5 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ composer require "fab2s/laravel-dt0"

`Laravel Dt0` only adds Validation implementation and model attribute casting to `Dt0`. All other features will work exactly the same. Have a look at [`Dt0`](https://github.com/fab2s/dt0) to find out more.

## Caster

In addition to [`Dt0 casters`](https://github.com/fab2s/dt0/tree/main/src/docs/casters.md), `Laravel Dt0` adds a [`CollectionOfCaster`](./src/Caster/CollectionOfCaster.php) which can be used to strongly type a Laravel `Collection`:

````php
#[Cast(in: new CollectionOfCaster(MyDt0::class))] // Dt0|UnitEnum|ScalarType|string
public readonly Collection $prop;
````

It can be used as an inspiration to cast into more types.

## Validation

`Laravel Dt0` is able to leverage the full power of Laravel validation on each of its public properties. The validation is performed on the input data prior to any property casting or instantiation.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
],
"require": {
"php": "^8.1",
"fab2s/dt0": "dev-main",
"fab2s/dt0": "v0.x-dev",
"illuminate/translation": "^10.0|^11.0",
"illuminate/validation": "^10.0|^11.0"
},
Expand Down
16 changes: 12 additions & 4 deletions src/Caster/CollectionOfCaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
use fab2s\Dt0\Caster\ScalarType;
use fab2s\Dt0\Dt0;
use fab2s\Dt0\Exception\CasterException;
use fab2s\Dt0\Exception\Dt0Exception;
use fab2s\Dt0\Property\Property;
use Illuminate\Support\Collection;
use JsonException;

class CollectionOfCaster implements CasterInterface
{
Expand All @@ -41,13 +43,17 @@ public function __construct(
}

if (! $logicalType) {
throw new CasterException('[' . Dt0::classBasename(static::class) . "] $type is not an ArrayType nor a ScalarType");
throw new CasterException('[' . Dt0::classBasename(static::class) . "] $type is not a supported type");
}

$this->logicalType = $logicalType;
$this->scalarCaster = $this->logicalType instanceof ScalarType ? new ScalarCaster($this->logicalType) : null;
}

/**
* @throws Dt0Exception
* @throws JsonException
*/
public function cast(mixed $value): ?Collection
{
if (! is_iterable($value)) {
Expand All @@ -58,9 +64,11 @@ public function cast(mixed $value): ?Collection

foreach ($value as $item) {
$result->push(match ($this->logicalType) {
ArrayType::DT0 => $this->type::tryFrom($item),
ArrayType::ENUM => Property::tryEnum($this->type, $item),
default => $this->scalarCaster->cast($item),
ArrayType::DT0 => $this->type::from($item),
ArrayType::ENUM => Property::enumFrom($this->type, $item),
default => $this->scalarCaster->cast($item) ?? throw (new CasterException('Could not cast array item to scalar type ' . $this->logicalType->value))->setContext([
'item' => $item,
]),
});
}

Expand Down
8 changes: 8 additions & 0 deletions tests/Caster/CollectionOfCasterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Exception;
use fab2s\Dt0\Caster\ScalarType;
use fab2s\Dt0\Exception\CasterException;
use fab2s\Dt0\Exception\Dt0Exception;
use fab2s\Dt0\Laravel\Caster\CollectionOfCaster;
use fab2s\Dt0\Laravel\Tests\Artifacts\DumbDt0;
use fab2s\Dt0\Laravel\Tests\TestCase;
Expand All @@ -37,6 +38,13 @@ public function test_exception(): void
new CollectionOfCaster('NotAType');
}

public function test_scalar_exception(): void
{
$this->expectException(Dt0Exception::class);
$caster = new CollectionOfCaster(ScalarType::bool);
$caster->cast([[]]);
}

public static function castProvider(): array
{
return [
Expand Down

0 comments on commit 840e810

Please sign in to comment.