terça-feira, 12 de maio de 2009

Tratando retornos no PHP

Depois de quase dois meses de correria, e adptações no novo emprego, finalmente volto a postar.
Esses dias precisei manipular retornos de um JSON em um Controlador. Até aí beleza, fui direto pegar o retorno dele com json_decode, sim porque pensei que era exatamente o inverso da json_encode, que recebe um array como parâmetro e codifica em JSON.
Pois bem, pra minha noobística surpresa, a função json_decode retorna um objeto(!). Pensei comigo, ta ok retorna um objeto, mas Controlador que estou trabalhando devolve os dados como array para a view. E agora? Simples passo o segundo parâmetro da função json_decode como true. Tá mas qual é a graça, seria interessante se eu pudesse usar essa idéia e manipular os retornos de minhas funções ao meu "bel-prazer". Até para poder ter retornos dinâmicos para o mesmo dado. Ora necessito dele como array para a view, Ora com objeto dentro de outro objeto.

Pensei um pouco , googleie e cheguei no seguinte código:

function object2array($object){
$arr = array();
foreach ($object as $i => $val):
$arr[$i] = (is_object($val))? object2array($val) : $val;
endforeach;
return $arr;
}

O que ela faz na real, é uma função recursiva, que percorre o objeto, caso o valor também seja um objeto ela chama ela mesma e trata o próximo nível, e assim sucessivamente. Antes o meu array de teste retornava os dados assim:


stdClass Object
(
[0] => a
[1] => b
[c] => stdClass Object
(
[0] => d
[1] => e
)

)
1

Logo depois consegui o resultado esperado:

Array
(
[0] => a
[1] => b
[c] => Array
(
[0] => d
[1] => e
)

)
1

Mas fui além, queria agora que todos os retornos de meus métodos SEMPRE retornem um Objeto. Até para padronizar a saída. Sei que retornando array está padronizada, mas num array com muitos níveis fica chato de acessar ou trocar valores, por exemplo:

$foo['abr']['lero']['some']['index'] = 2;

Achei muito melhor de acessar assim:

$foo->abr->lero->some->index = 2;

Qual o segredo? Usar um recurso do PHP chamado stdClass. Usada pra induzir tipos, e também para criar classes "OnTheFly", podemos usá-la para fazer uma "engenharia" reversa na função object2array() . Segue o código:

function array2object($array){
$obj = new stdClass();
foreach ($array as $i => $val):
$obj->{$i} = (is_array($val))? array2object($val) : $val;
endforeach;
return $obj;
}

Agora podemos aplicar essa função em quaisquer retornos que quisermos e trabalhar sempre com a "notação" de objetos ( $obj->propriedade ).

E é isso, agora não tem mais desculpa pra tratar os retornos, basta convertê-los e usar a sintaxe mais apropriada.
T+!

PS.: Fica mais uma "dica da dica", caso o array seja indexado numéricamente,
acessar uma propriedade assim:
   $foo->0

causaria um parse_error, porém nesses casos, para acessarmos a propriedade basta coloca-lá entre chaves:
   $foo->{0}

Flw!

Um comentário: