O script a seguir é destinado àqueles que utilizaram a função money_format no Linux e ficaram decepcionados ao notar que a função não estava disponível para Windows. Criei este script para tentar simular o comportamento da função original. Entretanto, nem todas as opções foram implementadas. Caso queira ajudar, fique a vontade, pois o código é livre e gratuito.
Linguagem: PHP
Copyright 2010 Rubens Takiguti Ribeiro
Licença: LGPL 3 ou superior
/**
* Formata um numero em notacao de moeda, assim como a funcao money_format do PHP
* @author Rubens Takiguti Ribeiro
* @see http://php.net/manual/en/function.money-format.php
* @param string $formato Formato aceito por money_format
* @param float $valor Valor monetario
* @return string Valor formatado
*/
function my_money_format($formato, $valor) {
// Se a funcao money_format esta disponivel: usa-la
if (function_exists('money_format')) {
return money_format($formato, $valor);
}
// Se nenhuma localidade foi definida, formatar com number_format
if (setlocale(LC_MONETARY, 0) == 'C') {
return number_format($valor, 2);
}
// Obter dados da localidade
$locale = localeconv();
// Extraindo opcoes do formato
$regex = '/^'. // Inicio da Expressao
'%'. // Caractere %
'(?:'. // Inicio das Flags opcionais
'\=([\w\040])'. // Flag =f
'|'.
'([\^])'. // Flag ^
'|'.
'(\+|\()'. // Flag + ou (
'|'.
'(!)'. // Flag !
'|'.
'(-)'. // Flag -
')*'. // Fim das flags opcionais
'(?:([\d]+)?)'. // W Largura de campos
'(?:#([\d]+))?'. // #n Precisao esquerda
'(?:\.([\d]+))?'. // .p Precisao direita
'([in%])'. // Caractere de conversao
'$/'; // Fim da Expressao
if (!preg_match($regex, $formato, $matches)) {
trigger_error('Formato invalido: '.$formato, E_USER_WARNING);
return $valor;
}
// Recolhendo opcoes do formato
$opcoes = array(
'preenchimento' => ($matches[1] !== '') ? $matches[1] : ' ',
'nao_agrupar' => ($matches[2] == '^'),
'usar_sinal' => ($matches[3] == '+'),
'usar_parenteses' => ($matches[3] == '('),
'ignorar_simbolo' => ($matches[4] == '!'),
'alinhamento_esq' => ($matches[5] == '-'),
'largura_campo' => ($matches[6] !== '') ? (int)$matches[6] : 0,
'precisao_esq' => ($matches[7] !== '') ? (int)$matches[7] : false,
'precisao_dir' => ($matches[8] !== '') ? (int)$matches[8] : $locale['int_frac_digits'],
'conversao' => $matches[9]
);
// Sobrescrever $locale
if ($opcoes['usar_sinal'] && $locale['n_sign_posn'] == 0) {
$locale['n_sign_posn'] = 1;
} elseif ($opcoes['usar_parenteses']) {
$locale['n_sign_posn'] = 0;
}
if ($opcoes['precisao_dir']) {
$locale['frac_digits'] = $opcoes['precisao_dir'];
}
if ($opcoes['nao_agrupar']) {
$locale['mon_thousands_sep'] = '';
}
// Processar formatacao
$tipo_sinal = $valor >= 0 ? 'p' : 'n';
if ($opcoes['ignorar_simbolo']) {
$simbolo = '';
} else {
$simbolo = $opcoes['conversao'] == 'n' ? $locale['currency_symbol']
: $locale['int_curr_symbol'];
}
$numero = number_format(abs($valor), $locale['frac_digits'], $locale['mon_decimal_point'], $locale['mon_thousands_sep']);
/*
//TODO: dar suporte a todas as flags
list($inteiro, $fracao) = explode($locale['mon_decimal_point'], $numero);
$tam_inteiro = strlen($inteiro);
if ($opcoes['precisao_esq'] && $tam_inteiro < $opcoes['precisao_esq']) {
$alinhamento = $opcoes['alinhamento_esq'] ? STR_PAD_RIGHT : STR_PAD_LEFT;
$numero = str_pad($inteiro, $opcoes['precisao_esq'] - $tam_inteiro, $opcoes['preenchimento'], $alinhamento).
$locale['mon_decimal_point'].
$fracao;
}
*/
$sinal = $valor >= 0 ? $locale['positive_sign'] : $locale['negative_sign'];
$simbolo_antes = $locale[$tipo_sinal.'_cs_precedes'];
// Espaco entre o simbolo e o numero
$espaco1 = $locale[$tipo_sinal.'_sep_by_space'] == 1 ? ' ' : '';
// Espaco entre o simbolo e o sinal
$espaco2 = $locale[$tipo_sinal.'_sep_by_space'] == 2 ? ' ' : '';
$formatado = '';
switch ($locale[$tipo_sinal.'_sign_posn']) {
case 0:
if ($simbolo_antes) {
$formatado = '('.$simbolo.$espaco1.$numero.')';
} else {
$formatado = '('.$numero.$espaco1.$simbolo.')';
}
break;
case 1:
if ($simbolo_antes) {
$formatado = $sinal.$espaco2.$simbolo.$espaco1.$numero;
} else {
$formatado = $sinal.$numero.$espaco1.$simbolo;
}
break;
case 2:
if ($simbolo_antes) {
$formatado = $simbolo.$espaco1.$numero.$sinal;
} else {
$formatado = $numero.$espaco1.$simbolo.$espaco2.$sinal;
}
break;
case 3:
if ($simbolo_antes) {
$formatado = $sinal.$espaco2.$simbolo.$espaco1.$numero;
} else {
$formatado = $numero.$espaco1.$sinal.$espaco2.$simbolo;
}
break;
case 4:
if ($simbolo_antes) {
$formatado = $simbolo.$espaco2.$sinal.$espaco1.$numero;
} else {
$formatado = $numero.$espaco1.$simbolo.$espaco2.$sinal;
}
break;
}
// Se a string nao tem o tamanho minimo
if ($opcoes['largura_campo'] > 0 && strlen($formatado) < $opcoes['largura_campo']) {
$alinhamento = $opcoes['alinhamento_esq'] ? STR_PAD_RIGHT : STR_PAD_LEFT;
$formatado = str_pad($formatado, $opcoes['largura_campo'], $opcoes['preenchimento'], $alinhamento);
}
return $formatado;
}
Exemplo de uso:
// Definindo a localidade "portugues do Brasil"
setlocale(LC_MONETARY, 'pt_BR.UTF-8', 'Portuguese_Brazil.1252');
echo my_money_format('%n', 1.9);
// R$ 1,90
// Definindo a localidade "ingles americano"
setlocale(LC_MONETARY, 'en_US.UTF-8');
echo my_money_format('%n', 1.9);
// $1.90
6 comentários
Olá Rubens.
Parabéns pelo post, foi incrível, salvou meus dias.
Só um detalhe, quando você diz: "Entretando nem todas as opções foram implementadas", a quais opções você se refere.
Obrigado
Olá Evandromar,
As flagas que me refiro estão lá na documentação da função money_format. Veja só:
http://br.php.net/manual/en/function.money-format.php
São só algumas flags pouco usadas (precisão à esquerda/direita). Mas para o básico a função funciona bem.
ummm,,
can u email me the english version?
please send to horcrux@rocketmail.com.
thank you.
@andhi arifin.. use google translate.. :D
Grazie!
a posição estar errada!
O cerreto é:
setlocale(LC_MONETARY, 'pt_BR.UTF-8', 'Portuguese_Brazil.1252');
echo money_format('%n', 1.9);
// R$ 1,90
echo "
";
// Definindo a localidade "ingles americano"
setlocale(LC_MONETARY, 'en_US.UTF-8');
echo my_money_format( '%n', 1.9);
// $1.90
echo "
";
Postar um comentário
Nota: fique a vontade para expressar o que achou deste artigo ou do blog.
Dica: para acompanhar as respostas, acesse com uma conta do Google e marque a opção "Notifique-me".
Atenção: o blogger não permite inclusão de tags nos comentários, por isso, use algum site externo para postar seu código com dúvidas e deixe o link aqui. Exemplo: pastebin.com