mas quando eu chego no model ele não reconhece este valor como uma data entao eu tratei esse valor para que se transformasse em data no beforeSave do model.
até ai tudo bem.
Mas no caso de existir um erro na minha data ele da um erro
htmlspecialchars() expects parameter 1 to be string, object given
acho que ele exibe isso porque o CMaskedTextField espera uma string e o tipo que está retornando é um objeto DateTime.
Queria que alguem me desse uma luz de como resolver isso.
Um solução pra isso Josafá seria você guardar o timestamp e a formatação da data você escolheria na hora de recuperar, e o legal é que você não precisa validar apenas gravar o timestamp
To com o mesmo problema aqui, com uma pequena diferença, não exibe nenhum erro e a data gravada é = 0.
Aparentemente ele interpreta a data no formato do MySQL(yyyy-mm-dd), mas descobri que, para visualizar corretamente, vc pode usar:
Yii::app()->dateFormatter->formatDateTime
Neste caso, vc formata a data para o modo corrente da sua aplicação(A formatação da data depende da língua configurada no seu main.php).
Atualmente no controller eu to fazendo a operação inversa, mas, não achei nada no Yii que faça isso automaticamente. Provisóriamente estou fazendo assim:
public static function DateToDBDate($date){
$ar = explode('/', $date);
return $ar[2].'-'.$ar[1].'-'.$ar[0];
}
Quanto a validação de datas, ví que tem um validador, mas não consegui usar ele
vc pode usar o validador do próprio Yii desta forma:
public function rules(){
return array(
array('emissao', 'type', 'type'=>'date', 'dateFormat'=>'yyyy-MM-dd'),
);
}
este codigo é dentro do seu Model. Repare que, quando a data chega no model, ela já está invertida, então é necessário passar a máscara invertida também.
ficou razoável, ainda não está perfeito, mas já ta ajudando.
Uma coisa que não entendo são essas máscaras, até entendo mas acho chato, já que o php trabalha com um formato e o Yii com outro, tipo no php ‘Y’ representa um ano com 4 dígitos já no Yii eu tenho que colocar ‘yyyy’.
Eu, particularmente, acho a leitura da máscara do Yii mais intuitiva, mas também não sou a favor dessas coisas despadronizadas. Na minha opnião o padrão do php deveria ser seguido já que é um framework php.
Apesar de ser legível creio que utilizar o explode e o mktime pode deixar o desempenho melhor, já que fazem parte do php e internamente são escritos em C.
Porém não sei até que ponto é válido optar por eles só por causa do desempenho.
Também não gosto de usar dois padrões diferentes. Talvez, esse problema seja elimidado utilizando o CDateTimeParser junto com o CDateFormatter. Ambos tem o mesmo padrão.
No geral, otimização precoce não é uma prática recomendável. Afinal, não faz sentido otimizar se nem sabemos onde estão os problemas de desempenho. A boa prática é desenvolver um código simples e legível, sem se preocupar com desempenho. Somente com o software pronto podemos efetuar medições de desempenho, utilizando-se, por exemplo, de profiling para identificar os "gargalos" na aplicação. É muito difícil que simples instruções como essas vão causar alguma diferença notável na aplicação.
vou tentar me lembrar disso na próxima app que estiver fazendo, agora que jah comecei de uma maneira não é bom mudar.
dependendo do que estiver sendo feito com simples instruções podemos ganhar em performance e muito. mas isso é outra história e também não da pra se exigir performance extrema com um framework
Muito bem, só agora trabalhei pra valer com as datas e, graças às várias dicas úteis daqui, consegui fazer!!
Gostaria de quotar alguns posts e sugerir uma solução.
Muito obrigado, seu post ajudou bastante. Porém, sugiro duas mudanças: ao invés de fazer a conversao no afterValidate, faça-a no beforeSave.
Colocando no primeiro evento, se houver algum problema de validação, a data volta invertida ao form. Se vc fizer no beforeSave, a data somente é invertida se passar pela validacao.
Se fizer a inversão no beforeSave, vc pode utilizar a máscara como ‘dd/MM/yyyy’.
Utilizei suas dicas e dei mais uma incrementada, para utilizar as datas com i18N. No seu model, adicione o seguinte codigo:
protected function beforeSave(){
$this->mydate = date('Y-m-d', CDateTimeParser::parse($this->mydate, Yii::app()->locale->dateFormat));
return true;
}
protected function afterFind(){
$this->mydate = Yii::app()->dateFormatter->formatDateTime(
CDateTimeParser::parse($this->mydate, 'yyyy-MM-dd'),'medium',null);
return true;
}
public function rules()
{
return array(
array('mydate', 'type', 'type'=>'date', 'dateFormat'=>Yii::app()->locale->dateFormat),
);
}
Sim, o codigo da conversao está grande. Porém, penso em criar um componente para efetuar esta conversao ou entao estender o CActiveRecord para reconhecer os campos do tipo data para efetuar a conversao.
Tambem tenho uma duvida existencial: como diferenciar um date de um datetime? no trecho
Vc tem razão. A solução do Davi é bem melhor que a minha. Quando respondi não tinha visto o post dele. (Na verdade, o post dele só fui ver hoje, heheh)
E, a questão do CDateTimeParser, eu tb não o conhecia.
A questão do i18N ficou muito boa. Vou implementar algo parecido.
Na verdade no afterFind não acontece esse problema, afinal a inversão é feita depois da validação. Basta apenas checar a existência de erros com o método hasErrors();
Eu usei o afterFind justamente por isso, para poder fazer a validação com essa máscara
Muito legal a idéia de i18n!
Estranho, aqui o CDateTimeParser não funciona se não informar a formato certo da data. Por exemplo
O código acima não efetua a conversão porque o formato está errado. Por consequência, o formatDateTime também não funciona. Então o "X" da questão aqui é como passar o formato certo para o parse.
Talvez tentando pegar o tipo de dado da coluna, utilizando CDbColummSchema e setando a mascara adequada seja uma solução, no caso de um componente. Para aplicações mais simples, acho que não há problema em deixar o formato fixo.
Mas falei que dava problema com afterValidate, nao com o afterFind, esse ta perfeito. O problema do afterValidate é que ele é executado depois da validacao independentemente se houve erro ou nao. Por isso, prefiro o beforeSave, aonde já nao preciso checar hasErrors()
Realmente nao funciona. O que me acontecia era o contrario: minha datanao tinha hora e a hora era adicionada quando convertia (tava me referindo ao resultado do formatDateTime, nao ao parse)
Mas A questao do date/datetime ja resolvi (na mesma linha de pensanmento que a sua).