Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fab2s committed Apr 22, 2024
1 parent 46617f5 commit 31bc1ab
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 6 deletions.
43 changes: 39 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,62 @@

[![CI](https://github.com/fab2s/laravel-dt0/actions/workflows/ci.yml/badge.svg)](https://github.com/fab2s/laravel-dt0/actions/workflows/ci.yml) [![CI](https://github.com/fab2s/laravel-dt0/actions/workflows/ci.yml/badge.svg)](https://github.com/fab2s/laravel-dt0/actions/workflows/ci.yml)

Laravel support for [Dt0](https://github.com/fab2s/dt0), a DTO (_Data-Transport-Object_) PHP implementation than can both secure mutability and implement convenient ways to take control over input and output in various format.
Laravel support for [fab2s/dt0](https://github.com/fab2s/dt0), a DTO (_Data-Transport-Object_) PHP implementation than can both secure mutability and implement convenient ways to take control over input and output in various formats.

## Installation

`Dt0` can be installed using composer:

```shell
composer require "fab2s/dt0"
composer require "fab2s/laravel-dt0"
```

Once done, you can start playing :
## Validation

Laravel `Dt0` is able to leverage the full power of Laravel validation on each of its properties. The validation is performed on the input data prior to any property casting or instantiation.

```php

// either get a Dt0 instance or a ValidationException
$dt0 = SomeValidatableDt0::withValidation(...\Illuminate\Http\Request::all());
```

## Model Attribute casting

Should you want to use a `Dt0` as a Laravel Model attribute, you cas use [Dt0Cast](./src/Casts/Dt0Cast.php) to cast it.

````php
use Illuminate\Database\Eloquent\Model;

class SomeModel extends Model
{
protected $casts = [
'some_dt0' => SomeDt0::class,
'some_nullable_dt0' => SomeNullableDt0::class.':nullable',
];
}

$model = new SomeModel;

$model->some_dt0 = '{"field":"value"}';
// or
$model->some_dt0 = ['field' => 'value'];
// or
$model->some_dt0 = SomeDt0::from(['field' => 'value']);

// then
$model->some_dt0->equals(SomeDt0::from('{"field":"value"}')); // true

$model->some_dt0 = null; // throws a NotNullableException
$model->some_nullable_dt0 = null; // works

// can thus be tried
$model->some_nullable_dt0 = SomeNullableDt0::tryFrom($anyInput);
````

## Requirements

`Dt0` is tested against php 8.1 and 8.2
`Dt0` is tested against php 8.1 and 8.2 and Laravel 10 / 11

## Contributing

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": "*",
"fab2s/dt0": "v0.x-dev",
"illuminate/translation": "^10.0|^11.0",
"illuminate/validation": "^10.0|^11.0"
},
Expand Down
79 changes: 79 additions & 0 deletions src/Casts/Dt0Cast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

/*
* This file is part of fab2s/laravel-dt0.
* (c) Fabrice de Stefanis / https://github.com/fab2s/dt0
* This source file is licensed under the MIT license which you will
* find in the LICENSE file or at https://opensource.org/licenses/MIT
*/

namespace fab2s\Dt0\Laravel\Casts;

use fab2s\Dt0\Exception\Dt0Exception;
use fab2s\Dt0\Laravel\Dt0;
use fab2s\Dt0\Laravel\Exceptions\NotNullableException;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
use JsonException;

class Dt0Cast implements CastsAttributes
{
/**
* @var class-string<Dt0>
*/
protected string $dt0Class;
protected bool $isNullable = false;

/**
* @param class-string<Dt0> $enumClass
* @param string[] ...$options
*/
public function __construct(string $enumClass, ...$options)
{
$this->dt0Class = $enumClass;

$this->isNullable = in_array('nullable', $options);
}

/**
* Cast the given value.
*
* @param Model $model
*
* @throws NotNullableException
* @throws JsonException
* @throws Dt0Exception
*/
public function get($model, string $key, $value, array $attributes): ?Dt0
{
return $this->getDt0($model, $key, $value);
}

/**
* Prepare the given value for storage.
*
* @param Model $model
*
* @throws Dt0Exception
* @throws NotNullableException
* @throws JsonException
*/
public function set($model, string $key, $value, array $attributes): ?string
{
return $this->getDt0($model, $key, $value)?->toJson();
}

/**
* @throws Dt0Exception
* @throws NotNullableException
* @throws JsonException
*/
protected function getDt0(Model $model, string $key, mixed $value): ?Dt0
{
if ($value === null) {
return $this->isNullable ? null : throw NotNullableException::make($key, $model);
}

return $this->dt0Class::from($value);
}
}
24 changes: 24 additions & 0 deletions src/Dt0.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/*
* This file is part of fab2s/laravel-dt0.
* (c) Fabrice de Stefanis / https://github.com/fab2s/dt0
* This source file is licensed under the MIT license which you will
* find in the LICENSE file or at https://opensource.org/licenses/MIT
*/

namespace fab2s\Dt0\Laravel;

use fab2s\Dt0\Dt0 as BaseDt0;
use fab2s\Dt0\Laravel\Casts\Dt0Cast;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Support\Arrayable;

abstract class Dt0 extends BaseDt0 implements Arrayable, Castable
{
public static function castUsing(array $arguments): CastsAttributes
{
return new Dt0Cast(static::class, ...$arguments);
}
}
28 changes: 28 additions & 0 deletions src/Exceptions/NotNullableException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/*
* This file is part of fab2s/laravel-dt0.
* (c) Fabrice de Stefanis / https://github.com/fab2s/dt0
* This source file is licensed under the MIT license which you will
* find in the LICENSE file or at https://opensource.org/licenses/MIT
*/

namespace fab2s\Dt0\Laravel\Exceptions;

use fab2s\Dt0\Exception\Dt0Exception;
use Illuminate\Database\Eloquent\Model;

class NotNullableException extends Dt0Exception
{
public static function make(string $field, Model $model): self
{
$modelClass = get_class($model);

return (new self("Field {$field} is not nullable in model {$modelClass}"))
->setContext([
'model' => $modelClass,
'data' => $model->toArray(),
])
;
}
}
2 changes: 1 addition & 1 deletion tests/Artifacts/ValidatableDt0.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use fab2s\Dt0\Attribute\Rule;
use fab2s\Dt0\Attribute\Rules;
use fab2s\Dt0\Attribute\Validate;
use fab2s\Dt0\Dt0;
use fab2s\Dt0\Laravel\Dt0;
use fab2s\Dt0\Laravel\Tests\Artifacts\Rules\Lowercase;
use fab2s\Dt0\Laravel\Validator;

Expand Down

0 comments on commit 31bc1ab

Please sign in to comment.