CakePHP 3.0 – O Fim do Locale

 

A nova versão do meu framework favorito está em estágio avançado e trás uma infinidade de coisas legais.

Dentre as novidades, quero deixar uma dica rápida para um problema comum a qualquer um que não use data/decimais em formato dos EUA: até hoje, para o Cake 1.3 e 2.x eu utilizo o plugin Locale, que já falei a respeito aqui antes.

Com o CakePHP 3.0, o plugin é completamente desnecessário: o novo ORM é capaz de interpretar os dados enviados em formato local para o formato nativo da máquina, de forma transparente.

Você só precisa registrar que os tipos do ORM deve utilizar localização…

Diga ao seu ambiente qual seu locale (pode fazer isso no bootstrap.php):

ini_set('intl.default_locale', 'pt_BR');

Inclua as linhas abaixo no início do seu AppController:

use Cake\Database\Type;
// Habilita o parseamento de datas localizadas
Type::build('date')
 ->useLocaleParser()
 ->setLocaleFormat('dd/MM/yyyy');
Type::build('datetime')
 ->useLocaleParser()
 ->setLocaleFormat('dd/MM/yyyy HH:mm:ss');
Type::build('timestamp')
 ->useLocaleParser()
 ->setLocaleFormat('dd/MM/yyyy HH:mm:ss');
 
// Habilita o parseamento de decimal localizaddos
Type::build('decimal')
 ->useLocaleParser();
Type::build('float')
 ->useLocaleParser();

Pronto, os dados do seu formulário serão interpretados e convertidos antes de serem salvos.

Para alterar a validação de data, você deve usar algo assim:

$validator->add('birthday', 'valid', [
 'rule' => ['date', 'dmy'], // esse é o importante, onde você avisa que a data estará localizada
 'message' => __('Informe uma data válida')
 ]);

E em substituição ao LocaleHelper, você pode formatar suas datas com o método format disponível (já que o registro agora é um objeto), e no caso de float/decimal, você usa a lib Number.

use Cake\I18n\Number;
$data = $user->birthday->format('d/m/Y');
$salary = Number::format($user->salary);

E é isso, sem nenhum plugin, sua aplicação estará falando português (ou qualquer outra linguagem/localização que você deseje utilizar).

3F: Férias da Faculdade, Finalmente.

Para quem nunca viu a página “Mea Culpa” deste blog, sou acadêmico de Ciência da Computação na UFMS, e após um grande sufoco, consegui progredir de série. Agora posso desfrutar de 2 “longos” meses de descanso, da faculdade. O trabalho não para, ainda bem.

Para quebrar o marasmo, segue abaixo três funções em PHP que criei hoje para corrigir um problema na formatação de datas em uma página web.

Os dois primeiros são triviais, conversão de datas do padrão brasileiro para o padrão SQL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function data_to_sql($sdata)
{
	$data = explode('/', $sdata);
	$data = implode('-', array_reverse($data));
 
	return $data;
}
//converte data do formato SQL para o brasileiro
function data_from_sql($sdata)
{
	$data = explode('-', $sdata);
	$data = implode('/', array_reverse($data));
 
	return $data;
}

E o terceiro é um pouco mais interessante, ele pode ser usado quando você quer montar um cabeçalho do tipo: quinta-feira, 12 de dezembro de 2009. O PHP fornece uma função nativa para isso, a função strftime(), mas ela tem como dependência um servidor com suporte a locale, e no meu caso, o locale pt_BR. Para contornar isso, fiz a seguinte função que resolve automáticamente a melhor forma de apresentar o cabeçalho desejado (considerando que strftime tem melhor desempenho do que algumas chamadas a função date(), time() e concatenação de strings):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
 * monta cabeçalho para impressao da data em portugues
 *  
 * @param $sdata time, passa a data desejada
 * @param $week boolean, se irá conter o nome da semana ou não
 * @return $data string, a data formatada para impressao
 */
function data_header($sdata, $week = false)
{
	$months = array('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'); 
	$weeks = array('Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado');
	$data = '';
 
	//se possuir suporte a setlocale com a região brasil, utiliza a função nativa
	if(setlocale(LC_TIME, "pt_BR"))
	{
		if($week)
			$strformat = '%A, %d de %B de %Y';
		else
			$strformat = '%d de %B de %Y';
 
		$data = strftime($strformat,$sdata);
	}
	else
	{
		if($week)
			$data .= strtolower($weeks[date('w', $sdata)]) . ', ';
 
		$data .= date('j', $sdata) . ' de ' . strtolower($months[date('n', $sdata)-1]) . ' de ' . date('Y', $sdata);
	}
 
	return $data;
}

São funções simples mas que podem quebrar um galho em um dia apertado.