Skip to content

maybePHP sem null.
Erros sem try/catch.

Option, Result, Schema e DTO para PHP 7.4+. Adote uma fronteira por vez, sem reescrita.

composer require gabrielalmir/maybe
customer.php
$result = Schema::shape([
    'email' => Schema::string()->trimmed(),
])->safeParse($payload)
    ->andThen(fn (array $data) => saveCustomer($data));

$result->match(
    fn (Customer $customer) => "Ok: saved",
    fn (mixed $error) => "Err: fix input"
);
A PHP Result pipeline that makes success and failure explicit
1
dependência de runtime (opis/closure)
7.4 → 8.5
versões de PHP testadas na CI
Windows
job Async roda na CI, sem pcntl
MIT
permissiva, sem contrapartidas

Mesmo caminho de código. Só um deles conta o que aconteceu.

Um e-mail de confirmação de pedido falha. Ou o checkout inteiro quebra por causa de um efeito colateral não crítico, ou a falha é engolida e ninguém descobre que o cliente nunca foi avisado.

Sem Maybe
// Silently invisible:
@mail($to, $subject, $body);

// "Handled", but the outcome is thrown away:
try {
    $mailer->send($to, $subject, $body);
} catch (\Exception $e) {
    error_log($e->getMessage());
}

Quem chamou não tem como saber se o cliente foi avisado, nem como distinguir um endereço malformado de um relay que deu timeout.

Com Maybe
$emailResult = $emailSchema->safeParse($message)
    ->andThen(static fn (array $valid): Result
        => sendWithFallback($valid));

$emailResult->match(
    static fn (string $ref): string => "sent ({$ref})",
    static fn (array $error): string => $error['retryable']
        ? "queued for retry"
        : "rejected: fix the input"
);

O payload de erro mantém `retryable` explícito. Um endereço malformado e um relay SMTP instável são problemas diferentes: um pede correção de dado, o outro uma fila de retry. O tipo impede que sejam tratados igual por acidente.

Cinco blocos, uma filosofia.

Os blocos foram desenhados para compor entre si, em uma única dependência que instala no PHP 7.4.

  • SchemaResult

    safeParse() nunca lança. Devolve um Result carregando um ValidationErrorBag.

  • DTOSchema

    Um schema, um objeto tipado e imutável, construído a partir de input bruto.

  • OptionResult

    okOr() transforma um valor ausente em um erro nomeado na fronteira.

O nicho

Roda onde o PHP legado realmente vive.

Não é reescrita, não é framework. Uma dependência pequena que instala no PHP que você já tem.

  • PHP 7.4 para cima

    Sem enums, sem promotion, sem readonly. Testado na CI contra 7.4, 8.2, 8.3, 8.4 e 8.5.

  • Windows, sem extensões

    Async usa proc_open, não pcntl. Um job de CI dedicado prova isso no Windows.

  • CodeIgniter 3

    Helpers globais e uma library carregável. Adote um controller por vez.

  • Honesto sobre async

    Concorrência por processos, deliberadamente não um event loop. Precisa de um? Use amphp ou reactphp.

Em produção

Três fronteiras que valem nomear.

  • E-mail transacional que não pode derrubar o checkout

    Um e-mail de confirmação falha. Ou o checkout inteiro quebra por um efeito colateral não crítico, ou a falha é silenciosamente engolida.

  • Enviar pedidos ao SAP sem perder dado em silêncio

    O SAP falha por razões estruturadas: documento duplicado, centro de custo ausente, sessão expirada, timeout. Código legado colapsa tudo na mesma não-resposta.

  • Validação de contratos com regras entre campos

    Validação espalhada por um controller deixa um contrato ser salvo pela metade em estado inválido, com erros desestruturados demais para uma tela de revisão apontar o campo culpado.

Aponte seu agente para a API exata.

Um llms.txt publicado com nomes e assinaturas exatos, incluindo os getters que deliberadamente não existem, para o assistente parar de inventá-los.

Combinado com o AGENTS.md do repositório, para quem contribui usando um assistente.

https://gabrielalmir.github.io/maybe/llms.txt

Quando não usar Maybe

Honestidade primeiro. Procure outra coisa quando:

  • Você está em PHP moderno (8.1+) e já padronizou numa biblioteca especialista madura com a qual está satisfeito.
  • Você precisa de um event loop async completo com I/O não bloqueante. Use amphp ou reactphp, não o Async.
  • Você precisa de um motor de validação com catálogo grande de regras e mensagens i18n prontas.
  • Seu time prefere exceções e não vai adotar Result nas fronteiras. O valor vem do uso consistente.
Ver a comparação completa →

Comece na fronteira que você já tem.

Sem acoplamento a framework e sem reescrita. Valide o input, modele uma operação falível e decida o resultado na borda.

composer require gabrielalmir/maybe

Comece em 5 minutosLer o tutorial

v0.4.0 · MIT · PHP ≥ 7.4

Novato por aqui? Leia Por que Maybe? para entender os trade-offs, siga o Tutorial para construir um fluxo validado de ponta a ponta, ou mantenha a Referência de API aberta enquanto trabalha.