Para quem já está mexendo com CakePHP há algum tempo, algumas
limitações de funcionalidades podem tirar um pouco o sono de quem está
muito mal acostumado com a produtividade da framework. Em geral, toda
framework tem seus pontos fracos.
Há algum tempo, tive um problema curioso: a chave primária de uma
tabela teria valores alfanuméricos. Ou seja: valores como “205-A”,
“JB02 e outros bizarros seriam possíveis. Regra de negócio definida,
modificação do modelo para o nome de chave fora da convenção e tudo
corria bem até que populei um select.
Qual não foi minha surpresa em ver que o CakePHP, além de não marcar o
valor correto, em certos casos ainda selecionava mais de um valor no
select. #fail total.
Pesquisa na internet, perguntas na lista de discussão oficial do CakePHP e as respostas eram:
- Coisas que não tinha nada a ver com o problema
- Sugestões pra mudar a estratégia para resolver o problema
- Gente falando que o CakePHP só trampa com valores numérico (o que de fato acontece!)
O problema
Então, mexendo no código, consegui achar o problema.
No arquivo cake/libs/views/helpers/form.php (cakephp 1.2.5), na linha 1710:
if ((!$selectedIsEmpty && $selected == $name) || ($selectedIsArray && in_array($name, $selected))) {Depois de fuçar e testar um pouco, vi que o problema principal, na
verdade, é um problema com o próprio operador == do PHP: ele trata as
operações entre strings e numéricos (http://php.net/manual/en/language.operators.comparison.php) de uma forma que gera os seguintes resultados:
- um valor como 206-1 por exemplo, o helper casava tanto o valor 206-1 (o correto) quanto 206 (string == integer).
- um valor como JB01 por exemplo, o helper casava tanto o valor JB01 (o correto) quanto 0 (string == integer).
Devido à característica do PHP de resolver qual o tipo da variável
em tempo real, ele tenta fazer o casting da variável sempre e acaba
gerando resultados não esperados pra gente.
Solução
A solução então foi forçar (type casting) as variáveis para serem
tratadas como strings. Assim, evitamos que o PHP transforme nossas
variáveis em tipos distintos (no nosso caso string e integer) e
consequentemente faça a comparação de valores do jeito que precisamos.
A linha 1710 (no cakephp 1.2.5 ou 1748 no cakephp 1.3-dev) ficou assim:
if ((!$selectedIsEmpty && (string)$selected == (string)$name)<br />|| ($selectedIsArray && in_array($name, $selected))) {Note o type casting sendo feito nas variáveis $selected e $name.
Se alguém conseguir uma solução mais bacana ou encontrou outro bug bizarro do CakePHP, compartilhe!
Simbora!
Observação: Eu tinha reportado esse erro há algum tempo no track de bugs do CakePHP. Depois de um tempo, vi que isso havia sido corrigido. Então, quando sair a versão stable do cake 1.3, não precisa mais se preocupar com isso.







