Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs folder standardization and other fixes #81

Merged
merged 6 commits into from
Apr 23, 2024
Merged
Changes from 1 commit
Commits
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
Next Next commit
translation into Brazilian Portuguese
luizcmarin committed Apr 8, 2024
commit 82bd99782c5c6c7686e1bcb264d433be2577e9f4
4 changes: 2 additions & 2 deletions docs/guide/en/mapping.md
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ But the data you have has differently named keys:
$data = ['header' => 'First post', 'text' => 'Hello, world!'];
```

Hydrator allows you to map data:
Hydrator allows you to map data:

```php
use Yiisoft\Hydrator\Hydrator;
@@ -100,7 +100,7 @@ class MyClass
To resolve dependencies by specific ID using DI container, use `Di` attribute:

```php
ues \Yiisoft\Hydrator\Attribute\Parameter\Di;
use \Yiisoft\Hydrator\Attribute\Parameter\Di;

class MyClass
{
10 changes: 10 additions & 0 deletions docs/guide/pt-BR/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Yii Hydrator

O pacote fornece uma maneira de criar e hidratar objetos a partir de um conjunto de dados brutos.

- [Uso geral](general-usage.md)
- [Conversão de tipo](typecasting.md)
- [Mapeamento](mapping.md)
- [Criando atributos próprios](creating-own-attributes.md)
- [Attribute resolver factory](attribute-resolver-factory.md)
- [Object Factory](object-factory.md)
31 changes: 31 additions & 0 deletions docs/guide/pt-BR/attribute-resolver-factory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Fábrica de resolvedores de atributos

O hydrator usa a implementação `AttributeResolverFactoryInterface` para criar resolvedores de atributos.
O pacote fornece duas implementações prontas para uso:

- `ReflectionAttributeResolverFactory`. Usa Reflection para criar resolvedores de atributos e pode criar resolvedores de atributos
apenas sem dependências.
- `ContainerAttributeResolverFactory`. Usa Container DI compatível com [PSR-11](https://www.php-fig.org/psr/psr-11/)
para criar o resolvedor de atributos.

O padrão de factory usado depende do ambiente. Ao usar o pacote hydrator dentro do ecossistema Yii (um aplicativo
usa [Yii Config](https://github.com/yiisoft/config)), o padrão é `ContainerAttributeResolverFactory`. De outra forma,
é `ReflectionAttributeResolverFactory`.

## Usando factory de resolução de atributos

Para usar o resolvedor de atributos não padrão, passe-o para o construtor do hydrator:

```php
use Yiisoft\Hydrator\AttributeHandling\ResolverFactory\ContainerAttributeResolverFactory;

/**
* @var Psr\Container\ContainerInterface $container
*/
$attributeResolverFactory = new ContainerAttributeResolverFactory($container);

$hydrator = new Hydrator(
attributeResolverFactory: $attributeResolverFactory,
// ...
);
```
177 changes: 177 additions & 0 deletions docs/guide/pt-BR/creating-own-attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Criando atributos próprios

Existem duas partes principais de um atributo:

- **Attribute class** (Classe de atributos). Ele armazena apenas opções de configuração e uma referência ao seu manipulador.
- **Attribute resolver** (Resolvedor de atributos). Dada um atributo reflection e dados extras, ele resolve um atributo.

Além da separação de responsabilidades, esta abordagem permite que o pacote resolva automaticamente dependências para
o resolvedor de atributos.

## Atributos de dados

Você aplica atributos de dados a uma classe inteira. O objetivo principal é obter dados de fontes externas, como solicitações.
Além disso, é possível especificar como os atributos de origem externa são mapeados para a classe hidratada.

A classe de atributos de dados deve implementar `DataAttributeInterface` e o resolvedor de atributos de dados correspondente deve
implementar `DataAttributeResolverInterface`.

### Exemplo de atributo de dados personalizado

Por exemplo, vamos criar um atributo de dados que usa um array predefinido "data" para preencher o objeto.

Atributo:

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

#[Attribute(Attribute::TARGET_CLASS)]
final class FromArray implements DataAttributeInterface
{
public function __construct(
private array $data,
) {
}

public function getData(): array
{
return $this->data;
}

public function getResolver(): string
{
return FromArrayResolver::class;
}
}
```

Resolver:

```php
use Yiisoft\Hydrator\ArrayData;
use Yiisoft\Hydrator\Attribute\Data\DataAttributeInterface;
use Yiisoft\Hydrator\Attribute\Data\DataAttributeResolverInterface;
use Yiisoft\Hydrator\AttributeHandling\Exception\UnexpectedAttributeException;
use Yiisoft\Hydrator\DataInterface;

final class FromArrayResolver implements DataAttributeResolverInterface
{
public function prepareData(DataAttributeInterface $attribute, DataInterface $data): DataInterface
{
if (!$attribute instanceof FromArray) {
throw new UnexpectedAttributeException(FromArray::class, $attribute);
}

return new ArrayData($attribute->getData());
}
}
```

## Atributos de parâmetro

Você aplica atributos de parâmetro às propriedades de classe e parâmetros de construtor. Você usa esses atributos para obter
valor para um parâmetro específico ou para preparar o valor (por exemplo, por conversão de tipo).

A classe de atributo de parâmetro deve implementar `ParameterAttributeInterface` e o atributo de parâmetro correspondente
o resolvedor deve implementar `ParameterAttributeResolverInterface`.

### Exemplo de atributo de parâmetro personalizado

Por exemplo, vamos criar um atributo de parâmetro que forneça um valor aleatório para a propriedade do objeto.

Atributo:

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

#[Attribute(Attribute::TARGET_PROPERTY)]
final class RandomInt implements ParameterAttributeInterface
{
public function __construct(
private int $min = 0,
private int $max = 99,
) {
}

public function getMin(): int
{
return $this->min;
}

public function getMax(): int
{
return $this->max;
}

public function getResolver(): string
{
return RandomIntResolver::class;
}
}
```

Resolver:

```php
use Yiisoft\Hydrator\ArrayData;
use Yiisoft\Hydrator\Attribute\Data\DataAttributeInterface;
use Yiisoft\Hydrator\Attribute\Data\DataAttributeResolverInterface;
use Yiisoft\Hydrator\AttributeHandling\Exception\UnexpectedAttributeException;
use Yiisoft\Hydrator\DataInterface;

final class FromArrayResolver implements DataAttributeResolverInterface
{
public function prepareData(DataAttributeInterface $attribute, DataInterface $data): DataInterface
{
if (!$attribute instanceof FromArray) {
throw new UnexpectedAttributeException(FromArray::class, $attribute);
}

return new ArrayData($attribute->getData());
}
}
```

## Usando uma única classe para atributo e resolvedor

Se o seu atributo for simples e não exigir dependências, você poderá combinar o atributo e seu resolvedor em uma única classe.
Por exemplo:

```php
use Attribute;
use Yiisoft\Hydrator\ArrayData;
use Yiisoft\Hydrator\Attribute\Data\DataAttributeInterface;
use Yiisoft\Hydrator\Attribute\Data\DataAttributeResolverInterface;
use Yiisoft\Hydrator\AttributeHandling\Exception\UnexpectedAttributeException;
use Yiisoft\Hydrator\DataInterface;

#[Attribute(Attribute::TARGET_CLASS)]
final class FromArray implements DataAttributeInterface, DataAttributeResolverInterface
{
public function __construct(
private array $data,
) {
}

public function getData(): array
{
return $this->data;
}

public function getResolver(): self
{
return $this;
}

public function prepareData(DataAttributeInterface $attribute, DataInterface $data): DataInterface
{
if (!$attribute instanceof FromArray) {
throw new UnexpectedAttributeException(FromArray::class, $attribute);
}

return new ArrayData($attribute->getData());
}
}
```
55 changes: 55 additions & 0 deletions docs/guide/pt-BR/general-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Uso geral

Para hidratar um objeto existente:

```php
use Yiisoft\Hydrator\Hydrator;

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

Para criar um novo objeto e preenchê-lo com os dados:

```php
use Yiisoft\Hydrator\Hydrator;

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

Para passar argumentos para o construtor de um objeto aninhado, use array aninhado ou notação de ponto:

```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',
]);
```

Isso passaria o argumento construtor `name` do objeto `Car` e criaria um novo objeto `Engine` para `engine`
passando o argumento `V8` como o argumento `name` para seu construtor.
114 changes: 114 additions & 0 deletions docs/guide/pt-BR/mapping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Mapeamento

Em muitos casos, os nomes dos atributos de classe diferem das chaves de dados com as quais você preenche e/ou cria objetos da classe.
Por exemplo, temos uma classe de postagem de blog:

```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;
}
}
```

Mas os dados que você possui têm chaves com nomes diferentes:

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

O Hydrator permite mapear os dados:

```php
use Yiisoft\Hydrator\Hydrator;
use Yiisoft\Hydrator\ArrayData;

$hydrator = new Hydrator();

$map = ['title' => 'header', 'body' => 'text'];
$post = $hydrator->create(Post::class, new ArrayData($data, $map));
```

Desta forma, pegamos a chave `header` para `title` e a chave `text` para `body`.

## Strict mode (Modo estrito)

Você pode ativar o modo estrito passando `true` como terceiro argumento de `ArrayData`:

```php
use Yiisoft\Hydrator\Hydrator;
use Yiisoft\Hydrator\ArrayData;

$hydrator = new Hydrator();

$map = ['title' => 'header', 'body' => 'text'],;
$post = $hydrator->create(Post::class, new ArrayData($data, $map, true));
```

Neste caso, as chaves ausentes do mapa são ignoradas, portanto tudo deve ser mapeado explicitamente.

## Usando atributos

Alternativamente à especificação do mapeamento como um array, você pode usar o atributo `Data` para definir o mapeamento 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',
]);
```

Para pular a hidratação de uma propriedade específica, use o atributo `SkipHydration`:

```php
use \Yiisoft\Hydrator\Attribute\SkipHydration;

class MyClass
{
#[SkipHydration]
private $property;
}
```

## Resolvendo dependências

Para resolver dependências por ID específico usando o contêiner DI, use o atributo `Di`:

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

class MyClass
{
public function __construct(
#[Di(id: 'importConnection')]
private ConnectionInterface $connection,
) {}
}
```

A anotação instruirá o hydrator a obter `$connection` do contêiner DI pelo ID `importConnection`.
31 changes: 31 additions & 0 deletions docs/guide/pt-BR/object-factory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Object Factory (Fábrica de Objetos)

O hydrator usa a implementação `ObjectFactoryInterface` para criar o objeto quando você usa o método `Hydrator::create()`:
O hydrator passa os argumentos do construtor resolvidos para o factory e obtém o objeto criado para a próxima hidratação.
O pacote fornece duas implementações prontas para uso:

- `ReflectionObjectFactory`. Usa Reflection para criar objetos. Não é possível criar objetos quando alguns argumentos do construtor
não estão resolvidos. Este object factory é usado por padrão.
- `ContainerObjectFactory`. Usa [Yii Injector](https://github.com/yiisoft/injector) para criar objetos que permitem usar o
[PSR-11](https://www.php-fig.org/psr/psr-11/) um contêiner DI compatível para resolver argumentos do construtor não resolvidos
pelo hydrator.

## Usando o object factory

Para usar o object factory não padrão, passe-o para o construtor do hydrator:

```php
use Yiisoft\Injector\Injector;
use Yiisoft\Hydrator\ObjectFactory\ContainerObjectFactory;

/**
* @var Psr\Container\ContainerInterface $container
*/
$injector = new Injector($container)
$objectFactory = new ContainerObjectFactory($injector);

$hydrator = new Hydrator(
objectFactory: $objectFactory,
// ...
);
```
175 changes: 175 additions & 0 deletions docs/guide/pt-BR/typecasting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Typecasting

Quando os tipos PHP são definidos na classe, a conversão de tipo acontece automaticamente na criação ou hidratação do objeto:

```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]);
```

## Ajustando a conversão de tipos

Você pode ajustar a conversão de tipo passando um type-caster para o hidratador:

```php
use Yiisoft\Hydrator\TypeCaster\CompositeTypeCaster;
use Yiisoft\Hydrator\TypeCaster\PhpNativeTypeCaster;
use Yiisoft\Hydrator\TypeCaster\HydratorTypeCaster

$typeCaster = new CompositeTypeCaster(
new PhpNativeTypeCaster(),
new HydratorTypeCaster(),
);
$hydrator = new Hydrator($typeCaster);
```

O conjunto acima é o usado por padrão.

Fora da caixa, os seguintes type-casters estão disponíveis:

- `CompositeTypeCaster` permite combinar vários type-casters
- `PhpNativeTypeCaster` baseados em tipos PHP definidos na classe
- `HydratorTypeCaster` converte arrays em objetos
- `NullTypeCaster` type-casters configurável para converter `null`, string vazia e array vazio para `null`
- `NoTypeCaster` não faça nada

## Sua própria conversão de tipo

Você pode definir type-casters personalizados, se necessário:

```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();
```

## Usando atributos

Para converter um valor para string explicitamente, você pode usar o atributo `ToString`:

```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',
]);
```

Para converter um valor para o objeto `DateTimeImmutable` ou `DateTime` explicitamente, você pode usar o atributo `ToDateTime`:

```php
use DateTimeImmutable;
use Yiisoft\Hydrator\Attribute\Parameter\ToDateTime;

class Person
{
public function __construct(
#[ToDateTime(locale: 'ru')]
private ?DateTimeImmutable $birthday = null,
) {}
}

$person = $hydrator->create(Person::class, ['birthday' => '27.01.1986']);
```

Para remover espaços em branco (ou outros caracteres) do início e/ou final de um valor de string resolvido, você pode usar os atributos
`Trim`, `LeftTrim` ou `RightTrim`:

```php
use DateTimeImmutable;
use Yiisoft\Hydrator\Attribute\Parameter\Trim;

class Person
{
public function __construct(
#[Trim] // ' John ' → 'John'
private ?string $name = null,
) {}
}

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