PHP code example of silviosln / arbor-validator

1. Go to this page and download the library: Download silviosln/arbor-validator library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

silviosln / arbor-validator example snippets


use Arbor\Validator\Attributes as V;
use Arbor\Validator\ArborValidator;

final readonly class RegisterUserDTO
{
    public function __construct(
        #[V\Required, V\FullName]
        public string $name,

        #[V\Required, V\Email]
        public string $email,

        #[V\Required, V\MinLength(8)]
        public string $password,

        #[V\Required, V\SameAs('password', message: 'A confirmação de senha não confere')]
        public string $passwordConfirmation,

        #[V\Required, V\Cpf(stripMask: true)]
        public string $cpf,

        #[V\Required, V\Phone(format: 'BR', stripMask: true)]
        public string $phone,

        #[V\Optional, V\Cnpj(allowAlphanumeric: true, stripMask: true)]
        public ?string $cnpj = null,

        #[V\Optional, V\Date(format: 'Y-m-d')]
        public ?\DateTimeImmutable $birthDate = null,

        #[V\Optional, V\Time(format: 'H:i')]
        public ?string $preferredContactTime = null,

        #[V\Optional, V\Domain]
        public ?string $websiteDomain = null,

        #[V\Optional, V\Url]
        public ?string $profileUrl = null,

        #[V\Optional, V\Uuid]
        public ?string $affiliateUuid = null,

        #[V\Optional, V\NoHtml]
        public ?string $bio = null,

        #[V\Optional, V\UploadedFile(
            maxSize: '5MB',
            extensions: ['jpg', 'jpeg', 'png', 'webp'],
            mimeTypes: ['image/jpeg', 'image/png', 'image/webp']
        )]
        public ?array $avatar = null,
    ) {}
}

// Execução no Controller / Endpoint:
$result = ArborValidator::validate(RegisterUserDTO::class, array_merge($_POST, $_FILES));

if ($result->failed()) {
    // Retorna mapa de erros: ['cpf' => ['O campo cpf contém um CPF inválido.'], ...]
    return response()->json(['errors' => $result->errors()], 422);
}

/** @var RegisterUserDTO $dto */
$dto = $result->data(); // Instância pronta, validada e estritamente tipada
echo $dto->name;
echo $dto->cpf; // '11144477735' (sanitizado com stripMask)
echo $dto->birthDate->format('d/m/Y'); // \DateTimeImmutable

use Arbor\Validator\AV;

$registerSchema = AV::shape([
    'name'     => AV::string()->fullName()->min(3)->max(100),
    'email'    => AV::string()->email()->transform(fn($e) => strtolower(trim($e))),
    'password' => AV::string()->min(8),
    'password_confirmation' => AV::string(),
    'cpf'      => AV::string()->cpf(stripMask: true),
    'cnpj'     => AV::string()->cnpj(allowAlphanumeric: true, stripMask: true)->optional(),
    'phone'    => AV::string()->phone('BR', stripMask: true),
    'domain'   => AV::string()->domain()->optional(),
    'url'      => AV::string()->url()->optional(),
    'time'     => AV::string()->time('H:i')->optional(),
    'date'     => AV::string()->date('Y-m-d')->coerceDate(), // Converte para \DateTimeImmutable
    'avatar'   => AV::file()
                    ->maxSize('5MB')
                    ->extension(['jpg', 'png', 'webp'])
                    ->mimeType(['image/jpeg', 'image/png', 'image/webp'])
                    ->optional(),
])
// Confirmação de senha
->sameAs('password_confirmation', 'password', 'A confirmação de senha não coincide');

// Validação segura (não lança exceção)
$result = $registerSchema->safeParse(array_merge($_POST, $_FILES));

if (!$result->success) {
    return response()->json(['errors' => $result->errors()], 422);
}

$cleanData = $result->data(); // array com dados sanitizados e convertidos

AV::file()
    ->maxSize('5MB') // Converte strings legíveis ('500KB', '2GB') em bytes reais
    ->minSize('10KB')
    ->extension(['jpg', 'png', 'pdf'])
    ->mimeType(['image/jpeg', 'image/png', 'application/pdf']);

$file = $result->data()['avatar']; // Instância de Arbor\Validator\Files\UploadedFile

echo $file->clientName();     // "foto.jpg"
echo $file->mimeType();       // "image/jpeg" (inspecionado via finfo)
echo $file->extension();      // "jpg"
echo $file->size();           // 204800 (bytes)

// Move o arquivo com segurança para o destino
$file->moveTo('/var/www/uploads/avatar_123.jpg');

use Arbor\Validator\Attributes as V;

final readonly class OrderDTO
{
    public function __construct(
        #[V\Required]
        public string $customer,

        #[V\Required, V\Nested(AddressDTO::class)]
        public AddressDTO $address,

        #[V\Required, V\Each(OrderItemDTO::class)]
        public array $items,
    ) {}
}

$result = ArborValidator::validate(OrderDTO::class, $requestData);

if ($result->failed()) {
    // Erros pontilhados:
    // [
    //     'address.street' => ['O campo address.street é obrigatório.'],
    //     'items.0.price'  => ['O campo items.0.price deve ser um número.']
    // ]
    return response()->json(['errors' => $result->errors()], 422);
}

$result = ArborValidator::validate($dtoOrSchema, $data);

$result->isValid();               // bool (true se passou)
$result->failed();                // bool (true se falhou)
$result->data();                  // Retorna DTO ou array limpo (lança ValidationException se falhou)
$result->safeData();              // Retorna dados sem lançar exceção
$result->errors();                // array<string, list<string>> com todos os erros
$result->firstError();            // ?string com o primeiro erro global
$result->error('cpf');            // ?string com o primeiro erro do campo
$result->fieldErrors('cpf');      // list<string> com todos os erros do campo
$result->hasError('cpf');         // bool

use Arbor\Validator\ArborValidator;
use Arbor\Validator\Exceptions\ValidationException;

try {
    $dto = ArborValidator::parse(RegisterUserDTO::class, $_POST);
    // Dados 100% válidos...
} catch (ValidationException $e) {
    return response()->json([
        'message' => $e->getMessage(),
        'errors'  => $e->errors(),
    ], 422);
}

use Arbor\Validator\ArborValidator;

// Altera o idioma global para Inglês
ArborValidator::setLocale('en');

// Adiciona ou sobrescreve mensagens personalizadas
ArborValidator::addMessages('pt-BR', [
    'cpf' => 'O CPF informado não é válido perante a Receita Federal.',
]);

use Arbor\Validator\Integration\ValidatesRequestTrait;

class Request
{
    use ValidatesRequestTrait;
}

// Dentro do seu Action/Controller do Arbor Router:
return function(Request $request) {
    $result = $request->validate(UpdateProfileDTO::class);

    if ($result->failed()) {
        return ActionResult::error($result->errors());
    }

    $dto = $result->data();
    // Execução segura...
};