Como converter datas no CakePHP para o padrão que você precisar Artigo

Conheça os cursos gratuitos do WebDevBr! - Inscreva-se!


Este artigo foi publicado a 5 anos, 1 semana, 3 dias atrás.

Este artigo é muito antigo ou seu conteúdo foi descontinuado, com certeza outro artigo foi escrito para substituí-lo, use o campo de pesquisa logo acima e desculpe o incomodo!

Uma coisa que vez ou outra vejo as pessoas procurando é sobre datas, como pegar a data padrão do CakePHP (que vem em datetime, exemplo: 2013/08/15 20:30:41) e transformar em 15/08/2013 ou quinta-feira, 15 de agosto de 2013, 20h30m, embora seja muito prático, as vezes não paramos pra pensar que o CakePHP ainda é PHP, e podemos usar recursos do próprio framework com um pouco de lógica php e criar o que queremos, neste caso, um behavior.

Qual a diferença entre behavior e componente?

Componentes são pacotes com funções lógicas... tá isso você lê no manual, a grande diferença aqui é que Componentes são extensões para Controllers e Behaviors são para Models. Como queremos que nosso CakePHP seja capaz de automaticamente converter dados após uma consulta find, que faz parte dos models, achei mais cabível então usar um behavior.

Qual lógica usaremos para converter as datas no CakePHP?

Bem precisamos que após uma consulta find, o array gerado seja analisado por uma função, da seguinte forma:

Gostou deste artigo?

Receba atualizações semanais com novos artigos do WebDevBr e outras dicas!

O valor é um array:

Sim: Execute novamente a função novamente para encontrar os valores dela

Não: Então, se não é um array é um campo do banco de dados, pergunte novamente.

O tipo do campo no banco de dados é datetime?

Sim: Faça a conversão e adicione ao array de retorno

Não: Não faça nada, apenas adicione ao array de retorno

Ok, então com isso em mente, vamos montar a estrutura inicial:

Crie um arquivo chamado DataPtBrBehavior.php em app/Model/Behavior, abra a tag do php e adicione o código:

class DataPtBrBehavior extends ModelBehavior {

    public function replace(Model $Model, $resultados){

        //em cada resultado do array
        foreach($resultados as $key => $value):

            //verifico se ele é um array
            if(is_array($value)){

                //se for eu executo a função novamente
                $res[$key]=$Model->replace($value);

            //se não
            }else{

                //pego as colunas do model atual com o tipo de cada uma no banco
                $colunas = $Model->getColumnTypes();

                //em cada coluna
                foreach($colunas as $coluna => $tipo){

                    //verifico se é do tipo datetime e removo se não for
                    if($tipo != 'datetime')
                        unset($colunas[$coluna]);

                }
                //se o campo atual ainda existir no array colunas então ele é do tipo datetime
                if(array_key_exists($key,$colunas)){

                    //em cada coluna
                    foreach($colunas as $coluna => $tipo){

                        //adiciono ao array final o resultado da função organiza
                        $res[$coluna]=$this->organiza($value);

                    }

                //se não
                } else{

                    //apenas adiciono o valor ao array final
                    $res[$key]=$value;

                }

            }

        endforeach;

        //retorno o valor
        if(isset($res))return $res;

    }
}

Ok, agora, note que eu chamei uma função organiza ali, isso porque se eu separar as coisas, posso alterar meu behavior de conversão para o que eu precisar muito mais facilmente, inclusive outros formatos de data.

Convertendo as datas!

Eu vou dar um exemplo mais difícil, vocês se encarregam de dar outros exemplos nos comentários, o mais legal vai ganhar em grande abraço da mãe, ou do pai, ou do irmão, ou da irmã, ou da esposa, ou do esposo ... sei lá... de alguém. Crie a função aabaixo organiza:

public function organiza($datahora, $options=array('data'=>true,'hora'=>true)) {

}

Vejam que adicionei opções ali, data e hora, os dois como true (verdadeiro), isso porque depois quando eu voltar aqui e não quiser ou a data ou a hora, não quero ter que apagar nada, só mudar o valor na outra função, porque sou preguiçoso? Não, porque acho que fica mais fácil de implementar depois.

Dentro da função organiza eu coloquei o código:

//inicia a variável de retorno vazia
$res='';

//separa a data e a hora
$array=explode(' ',$datahora);

//armazena a data
$data=array_shift($array);

//armazena a hora
$hora=array_pop($array);

//extrai as variáveis options
extract ($options, EXTR_PREFIX_SAME, "se");

//se data enviado no options for true (verdadeiro)
if($se_data){

    //separa o dia mes e ano
    $data=explode('-',$data);

    //Seta o mes
    switch ($data[1]){
        case '00':$mes = "none"; break;
        case '01':$mes = "Janeiro"; break;
        case '02':$mes = "Fevereiro"; break;
        case '03':$mes = "Março"; break;
        case '04':$mes = "Abril"; break;
        case '05':$mes = "Maio"; break;
        case '06':$mes = "Junho"; break;
        case '07':$mes = "Julho"; break;
        case '08':$mes = "Agosto"; break;
        case '09':$mes = "Setembro"; break;
        case '10':$mes = "Outubro"; break;
        case '11':$mes = "Novembro"; break;
        case '12':$mes = "Dezembro"; break;
    };

    //Pega o valor numérico referente ao dia da semana
    $dia = date('w', strtotime($datahora));

    //Define o dia da semana
    switch ($dia){
        case 0:$semana = 'Domingo'; break;
        case 1:$semana = 'Segunda-feira'; break;
        case 2:$semana = 'Terça-feira'; break;
        case 3:$semana = 'Quarta-feira'; break;
        case 4:$semana = 'Quinta-feira'; break;
        case 5:$semana = 'Sexta-feira'; break;
        case 6:$semana = 'Sábado'; break;
    };

    //Monta a saída da data corretamente segundo padrão: Terça-feira, 21 de Maio de 2013,
    $res .= $semana.', '.$data[2].' de '.$mes.' de '.$data[0];

    //se hora enviado no options for true (verdadeiro), adiciono uma virgula e espaço para separar
    if($se_hora and )
        $res .=', ';
}

//se hora enviado no options for true (verdadeiro)
if($se_hora){
    //Pegamos os valores separados da hora
    $hora=explode(':',$hora);
    //Organizamos a hora:
    $res .= ' '.$hora[0].'h:'.$hora[1].'m';
}

//Retornamos a string no formato: Terça-feira, 21 de Maio de 2013, 11h:21m
return $res;

Esse exemplo converte os campos date time para o formato Terça-feira, 21 de Maio de 2013, 11h:21m de uma forma prática, já que agora você não precisa alterar mais nada em lugar nenhum, o CakePHP vai se virar para fazer tudo isso, toda vez que você der um find, paginate ou qualquer coisa que retorne os dados do banco de dados, sozinho... ou quase, ainda falta uma ultima coisa, coloque isso no fim de tudo:

public function afterFind(Model $Model, $resultados, $primary){ $resultados=$this->replace($Model, $resultados); return $resultados; }

Pronto, agora sim está pronto, esse função executa um callback no find dizendo para executar nosso código após a consulta e substituindo o resultado anterior.

Agora para usar basta adicionar a chamada no seu model, ou no appModel se quiser acertar a data de toda a aplicação, assim: public $actsAs = array('DataPtBr');

Com isso já encerramos nossa função que converte datetime do banco de dados em data por extenso.

E você, consegue alterar a função organiza() para mostrar a data da forma que você precisa, compartilha nos comentários.

Aqui o arquivo DataPtBrBehavior.php finalizado pra você copiar..


Cursos relacionados


* Parcelamento apenas cartão de crédito! Pode haver uma pequena variação no parcelamento em relação a simulações apresentadas!