PHP

NumberFormatter no PHP: R$ formatado e valor por extenso em pt-BR

O number_format($v, 2, ',', '.') resolve os separadores e para por aí: ele não sabe pôr o R$ na frente nem escrever “mil duzentos e trinta e quatro reais” no rodapé do boleto. Quem faz isso é a classe NumberFormatter, que vem com a extensão intl e já entende pt-BR sem você escrever um único array de dezenas.

Moeda e extenso em cinco linhas

$moeda = new NumberFormatter('pt_BR', NumberFormatter::CURRENCY);
echo $moeda->formatCurrency(1234.5, 'BRL');  // R$ 1.234,50

$extenso = new NumberFormatter('pt_BR', NumberFormatter::SPELLOUT);
echo $extenso->format(1234);  // mil duzentos e trinta e quatro

Para o valor cheio, separe reais e centavos antes. Jogar 1234.50 direto no SPELLOUT devolve mil duzentos e trinta e quatro vírgula cinco, que não serve para nota nem para boleto:

$valor = 1234.50;
$centavos = (int) round(fmod($valor, 1) * 100);
$texto = $extenso->format((int) $valor) . ' reais';
if ($centavos > 0) {
    $texto .= ' e ' . $extenso->format($centavos) . ' centavos';
}
echo $texto;  // mil duzentos e trinta e quatro reais e cinquenta centavos

Dois tropeços que custam tempo

O primeiro é o erro Uncaught Error: Class "NumberFormatter" not found. Falta a extensão: sudo apt install php8.3-intl e depois sudo systemctl restart php8.3-fpm. Confirme com php -m | grep intl, e lembre que o CLI e o FPM podem carregar php.ini diferentes — funcionar no terminal não quer dizer funcionar no site.

O segundo é mais silencioso: o espaço entre o R$ e o número é um espaço não separável (U+00A0), não o espaço da barra. Se você compara a string com 'R$ 1.234,50' num teste, ou tenta um str_replace('R$ ', '', $s), nunca bate. Para voltar ao float use $moeda->parseCurrency($s, $cur), que devolve o número e ainda preenche $cur com BRL, em vez de mexer no texto na unha.

Post Recentes

Could not ping search engine no Magento 2: OpenSearch fora do ar

Categoria vazia e busca sem resultado no Magento 2.4.8? Teste o OpenSearch com curl, confira o bloco catalog/search do env.php…

1 dia atrás

Bookmarks da grid do Magento 2: colunas somem e o filtro fica preso

Editou o listing.xml e o admin continua com as colunas antigas ou um filtro travado? O estado da grid está…

2 dias atrás

array_chunk no PHP: processar 50 mil registros em lotes sem estourar memória

Importação morrendo com Allowed memory size exhausted? Fatie o processamento com array_chunk e, quando nem o array couber, leia o…

2 dias atrás

Unknown module in the enabled modules list: erro no Magento 2

Apagou a pasta do módulo e agora todo bin/magento morre reclamando de módulo desconhecido? A lista continua no app/etc/config.php, e…

3 dias atrás

Ordenar posts por meta_value_num: o preço em ordem certa no WP_Query

Preço gravado em post meta sai fora de ordem porque o MySQL compara texto. Use orderby meta_value_num e inclua quem…

4 dias atrás

Action Scheduler travado no WooCommerce: milhares de ações pendentes

Fila do Action Scheduler com dezenas de milhares de ações pendentes na loja? Rode a fila pelo WP-CLI, limpe o…

4 dias atrás