Problema com IDs alfanuméricos no form->input (select) do CakePHP

25 de novembro de 2009 por Léo Hackin Deixe um comentário »

Para quem já está mexendo com CakePHP a 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.

A 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 haver 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 :P )

O problema

Então, mexendo no código pra cima e pra baixo (sem conotações sexuais por favor) 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) || ($selectedIsArray && in_array($name, $selected))) {

Note o type casting sendo feito nas variáveis $selected e $name. ;)

Se alguem conseguir uma solução mais bacana ou encontrou outro bug bizarro do CakePHP, compartilhe! :)

Simbora!

Update: Eu tinha reportado esse erro a algum tempo no track de bugs do CakePHP  e hoje vi que já corrigiram isso. Então, quando sair a versão stable do cake 1.3, não precisa mais se preocupar com isso. :D

Advertisement

2 comentários

  1. Léo Hackin disse:

    Óia que bacana: eu tinha reportado o bug/correção dessa falha anteriormente para o pessoal do Cake (http://code.cakephp.org/tickets/view/167) mas com outra abordagem pro erro. Alterei a estratégia, enviei de novo e não é ele já tinham corrigido? HAHEHEHAUEe Iradasso. :)

    Então, quando sair a versão stable do cake 1.3, não precisa mais se preocupar com isso.

Trackbacks /
Pingbacks

  1. Léo Hackin

Deixe seu comentário

Get Adobe Flash playerPlugin by wpburn.com wordpress themes