Skip to content

Commit

Permalink
More docs
Browse files Browse the repository at this point in the history
  • Loading branch information
samdark committed Jan 11, 2024
1 parent 6ac0a26 commit eab3cfb
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 46 deletions.
5 changes: 5 additions & 0 deletions docs/guide/en/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@

The package provides a way to create and hydrate objects from a set of raw data.

- [General usage](general-usage.md)
- [Configuration with PHP attributes](configuration-with-attributes.md)
- [Creating own attributes](creating-own-attributes.md)
- Attribute reslover factory
- Object factory
- [Mapping](mapping.md)
- [Type casting](typecasting.md)
45 changes: 0 additions & 45 deletions docs/guide/en/configuration-with-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,6 @@

You can configure how the hydrator creates or hydrates a specific class using attributes.

## Mapping

To map attributes to specific data keys, use `Data` attribute:

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

final class Person
{
public function __construct(
#[Data('first_name')]
private string $firstName,
#[Data('last_name')]
private string $lastName,
) {}
}

$person = $hydrator->create(Person::class, [
'first_name' => 'John',
'last_name' => 'Doe',
]);
```

## Casting value to string

To cast a value to string, use `ToString` attribute:

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

class Money
{
public function __construct(
#[ToString]
private string $value,
private string $currency,
) {}
}

$money = $hydrator->create(Money::class, [
'value' => 4200,
'currency' => 'AMD',
]);
```

## Skipping hydration

To skip hydration of a specific property, use `SkipHydration` attribute:
Expand Down
57 changes: 57 additions & 0 deletions docs/guide/en/general-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# General usage

To hydrate existing object:

```php
use Yiisoft\Hydrator\Hydrator;

$hydrator = new Hydrator();
$hydrator->hydrate($object, $data);
```

To create a new object and fill it with the data:

```php
use Yiisoft\Hydrator\Hydrator;

$hydrator = new Hydrator();
$object = $hydrator->create(MyClass::class, $data);
```

To pass arguments to the constructor of a nested object, use nested array or dot-notation:

```php
final class Engine
{
public function __construct(
private string $name,
) {}
}

final class Car
{
public function __construct(
private string $name,
private Engine $engine,
) {}
}

// nested array
$object = $hydrator->create(Car::class, [
'name' => 'Ferrari',
'engine' => [
'name' => 'V8',
]
]);

// or dot-notation
$object = $hydrator->create(Car::class, [
'name' => 'Ferrari',
'engine.name' => 'V8',
]);
```

That would pass the `name` constructor argument of the `Car` object and create a new `Engine` object for `engine`
argument passing `V8` as the `name` argument to its constructor.

// TODO: strict mode
67 changes: 67 additions & 0 deletions docs/guide/en/mapping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Mapping

In many cases, class attribute names differ from data keys you fill or create objects of the class with. For example,
we have a blog post class:

```php
final class Post
{
public function __construct(
private string $title,
private string $body,
) {
}

public function getTitle(): string
{
return $this->title;
}

public function getBody(): string
{
return $this->body;
}
}
```

But the data you have has differently named keys:

```php
$data = ['header' => 'First post', 'text' => 'Hello, world!'];
```

Hydrator allows you to map data:

```php
$hydrator = new Hydrator();

$object = new SimpleClass();

$map = ['title' => 'header', 'body' => 'text'],;
$hydrator->hydrate($object, new ArrayData($data, $map));
```

This way we take `header` key for `title` and `text` key for `body`.

## Using attributes

Alternatively to specifying mapping as an array, you can use `Data` attribute to define mapping inline:

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

final class Person
{
public function __construct(
#[Data('first_name')]
private string $firstName,
#[Data('last_name')]
private string $lastName,
) {}
}

$person = $hydrator->create(Person::class, [
'first_name' => 'John',
'last_name' => 'Doe',
]);
```
117 changes: 117 additions & 0 deletions docs/guide/en/typecasting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Typecasting

When PHP types are defined in the class, type-casting automatically happens on object creation or hydration:

```php
final class Lock
{
public function __construct(
private string $name,
private bool $isLocked
)
{
}
}

$hydrator = new Hydrator();
$lock = $hydrator->create(Lock::class, ['name' => 'The lock', 'isLocked' => 1]);
```

## Custom type-casting

You can define custom type-casters if needed:

```php
use Yiisoft\Hydrator\TypeCaster\TypeCastContext;
use Yiisoft\Hydrator\TypeCaster\TypeCasterInterface;
use Yiisoft\Hydrator\Result;
use Yiisoft\Hydrator\Hydrator;
use Yiisoft\Hydrator\TypeCaster\CompositeTypeCaster;

final class User
{
public function __construct(
private string $nickname
)
{
}

public function getNickName(): string
{
return $this->nickname;
}
}

final class NickNameTypeCaster implements TypeCasterInterface
{
public function cast(mixed $value, TypeCastContext $context): Result
{
$type = $context->getReflectionType();

if (
$context->getReflection()->getName() === 'author'
&& $type instanceof ReflectionNamedType
&& $type->isBuiltin()
&& $type->getName() === 'string'
&& preg_match('~^@(.*)$~', $value, $matches)
) {
$user = new User($matches[1]);
return Result::success($user);
}

return Result::fail();
}
}

final class Post
{
public function __construct(
private string $title,
private User $author
)
{
}

public function getTitle(): string
{
return $this->title;
}

public function getAuthor(): User
{
return $this->author;
}
}

$typeCaster = new CompositeTypeCaster(
new NickNameTypeCaster(),
);
$hydrator = new Hydrator($typeCaster);

$post = $hydrator->create(Post::class, ['title' => 'Example post', 'author' => '@samdark']);
echo $post->getAuthor()->getNickName();
```

## Using attributes

To cast a value to string explicitly, you can use `ToString` attribute:

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

class Money
{
public function __construct(
#[ToString]
private string $value,
private string $currency,
) {}
}

$money = $hydrator->create(Money::class, [
'value' => 4200,
'currency' => 'AMD',
]);
```


2 changes: 1 addition & 1 deletion src/HydratorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Yiisoft\Hydrator\Exception\NonInstantiableException;

/**
* Creates or hydrate objects from a set of raw data.
* Creates or hydrates objects from a set of raw data.
*/
interface HydratorInterface
{
Expand Down

0 comments on commit eab3cfb

Please sign in to comment.