Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Normalizable object functionality. Object can give its normalized view without any external access to its private properties.

License

Notifications You must be signed in to change notification settings

era269/normalizable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

normalizable

PHP Stan Badge codecov

The main idea is that normalized object is presented as array(including nested) of any combination of scalar values:

  • int
  • float
  • bool
  • string
  • null

Any normalized ValueObject can implement DenormalizableInterface to give functionality for its restoring from the normalized view. In the case with Domain object it is not common situation due to complicated logic of creation.

The NormalizableInterface purpose is to simplify the object normalization in OOP way.

  • we are keeping an encapsulation
  • no additional serializers needed. But could be used in pair
  • no performance penalty

However, it is needed to extract internals of the object when we are returning the http response with it. Keeping in mind that object has to know ins normalized structure and to avoid an extra getters, which are destroying the encapsulation, we can use NormalizableInterface.

The normalized view can be used in any communication on Infrastructure level like requests to the DB or any protocol based messages (HTTP, AMQP, ...)

Examples

Exception normalization

  • Adapter is valuable only in the case when it is not supposed to denormalize the normalized data. The best example in ThrowableToNormalizableAdapter.

Domain exception extending

<?php

use Era269\Normalizable\Adapter\ThrowableToNormalizableAdapter;use Era269\Normalizable\NormalizableInterface;

final class ModelNotFoundException extends RuntimeException implements NormalizableInterface
{
    private $modelId;
    private $modelClassName;
    
    public function __construct($modelId, $modelClassName, Throwable $previous)
    {
        parent::__construct('Model not found.', 0, $previous);
        $this->modelId = $modelId;
        $this->modelClassName = $modelClassName;
    }
    
    public function normalize() : array
    {
        return (new ThrowableToNormalizableAdapter($this))->normalize() + [
             'model' => $this->modelClassName,
             'modelId' => $this->modelId,
        ];
    }
    
    public function getType(): string
    {
        return self::class;
    }
}

Serializer integration

<?php

use Era269\Normalizable\Adapter\ThrowableToNormalizableAdapter;

final class ExceptionNormalizer implements NormalizerInterface
{    
    public function normalize(object $object) : array
    {
        /** @var Throwable $object */
        return (new ThrowableToNormalizableAdapter($object))->normalize();
    }
    
    public function supports(string $type): bool
    {
        return Throwable::class === $type;
    }
    
}

Domain model normalization

<?php

use Era269\Normalizable\DenormalizableInterface;use Era269\Normalizable\NormalizableInterface;use Era269\Normalizable\Object\DateTimeRfc3339Normalizable;use Era269\Normalizable\Traits\AbstractNormalizableTrait;

final class DomainEvent implements NormalizableInterface, DenormalizableInterface
{
    use AbstractNormalizableTrait;

    private string $name;
    private DateTimeRfc3339Normalizable $createdAt;

    public function __construct(string $name)
    {
        $this->createdAt = (new DateTimeRfc3339Normalizable());
        $this->name = $name;
    }
    
    protected function getNormalized() : array
    {
        return [
            'name' => $this->name,
            'created' => $this->createdAt->normalize(),
        ];
    }
    public static function denormalize(array $data) : static
    {
        $self = new self($data['name']);
        $self->createdAt = DateTimeRfc3339Normalizable::denormalize($data);
        return $self;
    }
}

$event = new DomainEvent('first');

echo json_encode($event->normalize());

output:

{
  "@type": "DomainEvent",
  "name": "first",
  "createdAt": {
    "@type": "\\Era269\\Normalizable\\Object\\DateTimeRfc3339Normalizable",
    "dateTime": "2021-02-06T20:07:55.621766+0000"
  }
}

About

Normalizable object functionality. Object can give its normalized view without any external access to its private properties.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •  

Languages