Diogo Besson :: tecnologia

Trabalhando com ArrayObject no PHP

Trabalhando com ArrayObject no PHP

Trabalhando com ArrayObject no PHP vai tentar te ajudar a… a… adivinha???

Confesso: O PHP é minha linguagem preferida.

Fico aborrecido quando eu tento comparar certas facilidades que algumas linguagens apresentam e comprovo que elas deixam a desejar no PHP.

O conceito de application é uma delas. No ASP é perfeito, no Java é perfeito e no PHP nem existe previsão de quando será implementado. #triste

Outra coisa é o polimorfismo. No PHP, eu acho polimorfético.

Segundo cita SOARES*, na página 291:

“Polimorfismo(…) É a capacidade de dois ou mais objetos responderem à mesma mensagem de diferentes maneiras. Em termos de classes podemos pensar em superclasses e subclasses, em que o mesmo método possui comportamentos e resultados diferentes na superclasse e nas subclasses, desta forma quem chama o método não precisa distinguir qual deve chamar.”

Uma boa definição, mas eu iria ainda mais longe ao opinar que o polimorfismo é uma propriedade das classes onde seus objetos instanciados podem ser vistos de maneira distinta pelo servidor ou pelo interpretador de acordo com o contexto onde eles são declarados.

Ficou confuso? Sim… Você tem um “ser humano”. Também possui dois tipos distintos de “ser humano”, onde um deles é “homem” e outro é “mulher”. “Homem” é um “ser humano” e “mulher” também é. Todo “homem” pode ser instanciado… referenciado… como “homem” ou “ser humano” e toda “mulher” pode ser instanciada… referenciada… como “mulher” ou “ser humano”. A diferença está em ver características a mais, a menos, ou comportamentos distintos de acordo com esse contexto onde você está referenciando o terráqueo em questão. Opa! “terráqueo” pode ser uma interface implementada por “ser humano”, logo, qualquer ser humano também pode ser considerado um “terráqueo”, a menos que descubram seres humanos em outros planetas… Isso é o Polimorfismo.

Mas e o PHP?

Os tipos em PHP são emulados, mas não precisam ser declarados, pois o PHP tem o conceito de “mixed” e “resource” que atrapalham um pouco ou polimorfismo, ou facilitam de acordo com aquilo que você precisa fazer. Às vezes é um saco, mas às vezes é uma mão na roda.

No mais, o máximo que eu vi de polimorfismo em PHP foi casting de ArrayObject pra Array, mas eu não posso dizer se isso está correto, a menos que você já opte por definir um array como uma coleção. O que no PHP não deixa de ser uma verdade.

Que seria mais ou menos isso:

$array = (array) new ArrayObject();

No Java você precisa de um List ou um Set pra fazer uma coleção usando array, porém no PHP você já trata o array como algo sem tamanho definitivo, ou seja, pode crescer, diminuir, classificar, etc, usando a API padrão, que já é o próprio PHP. A própria matriz de valores cresce, diminui e se comporta como uma coleção.

O exemplo acima é totalmente inútil no PHP porque você vai esperar que o interpretador do Apache veja a sua nova instância de ArrayObject como um array simples. Bicho… declara logo um array[] e pára de complicar o código!!!

Falando de ArrayObject, vou mostrar aqui algumas coisas mais interessantes a fazer com essa classe do que apenas casting inúteis.

O construtor do ArrayObject pode receber um array ou um outro ArrayObject. Quando o construtor não recebe parâmetros, ele é apenas uma instância vazia de um ArrayObject, sem implementação, porém, pronta para receber um elemento.

Pegando os exemplos da documentação do PHP:

Construtor

$array = array('1' => 'um',
'2' => 'dois',
'3' => 'três');

$arrayobject = new ArrayObject($array);

var_dump($arrayobject);

Append

Adiciona um elemento no ArrayObject

$arrayobject->append("O mundo do PHP"); // adiciona um elemento ao final

offsetUnset

Remove o elemento indicado

$arrayobject->offsetUnset(4); // retira o elemento do indice definido

getIterator

Pega um ponteiro navegável

$ponteiro = $arrayobject->getIterator(); // cria um ponteiro navegavel

getIterator()->current()/next()/key()/rewind()/seek(int $chave)/valid()

Funções navegadoras do Iterator. O valid verifica se o elemento da posição atual do ponteiro é ou não é nulo.

$ponteiro = $arrayobject->getIterator(); // cria um ponteiro navegavel

echo $ponteiro->current(); // pega a posição atual do ponteiro

echo "<hr>";

$ponteiro->next(); // manda o ponteiro para a proxima posição

echo $ponteiro->current(); //

 

Funções de ordenação/classificação

$arrayobject->asort(); // organiza por ordem dos valores

$arrayobject->ksort(); // organiza por ordem dos índices

uasort() e uksort()

Organizam por funções personalizadas de comparação, sendo “a” referente aos valores e “k” referente aos índices

// Função de Comparação

function cmp($a, $b) {

if ($a == $b) {

return 0;

}

return ($a < $b) ? -1 : 1;

}

 

// Array para classificar

$array_2 = array('a' => 4, 'b' => 8, 'c' => -1, 'd' => -9, 'e' => 2, 'f' => 5, 'g' => 3, 'h' => -4);

$arrayObject_2 = new ArrayObject($array_2);

print_r($arrayObject_2);

echo "<hr color=blue>";

 

// organiza e imprime

$arrayObject_2->uasort('cmp');

print_r($arrayObject_2);

echo "<hr color=blue>";

 

 

// Função de Comparação

function cmp2($a, $b) {

$a = preg_replace('@^(a|an|the) @', '', $a);

$b = preg_replace('@^(a|an|the) @', '', $b);

return strcasecmp($a, $b);

}

 

// Array para classificar

$array_3 = array("João" => 1, "A Terra" => 2, "Uma maçã" => 3, "Uma banana" => 4);

$arrayObject_3 = new ArrayObject($array_3);

 

// organiza e imprime

$arrayObject_3->uksort('cmp2');

foreach ($arrayObject_3 as $key => $value) {

echo "$key: $valuen";

}

echo "<hr color=blue>";

 

FLAGS

São diferentes modos de tratar o índice dentro de um ArrayObject

Por padrão as flags estão setadas para STD_PROP_LIST e ignoram as chaves como propriedades do objeto.

Para isso funcionar de uma maneira mais bacana, usamos ARRAY_AS_PROPS.

Veja o exemplo:

// FLAGS: Array e objectArray de frutas

$fruits = array("lemons" => "verde", "oranges" => "laranja", "bananas" => "amarela", "apples" => "vermelha");

$fruitsArrayObject = new ArrayObject($fruits);

 

// Tentando usar o indice como propriedade

print_r($fruitsArrayObject->lemons);    // por padrao as flags estao setadas para

// STD_PROP_LIST e ignora as chaves como propriedades

 

// Mudando a flag padrão

// ARRAY_AS_PROPS transforma chaves como propriedades

 

$fruitsArrayObject->setFlags(ArrayObject::ARRAY_AS_PROPS);

// Agora sim ele imprime o valor

print_r($fruitsArrayObject->lemons);

echo "<hr color=blue>";

Para trocar ou inserir um array do ArrayObject

exchangeArray($outroarray);

Para fazer a exportação de um ArrayObject para array sem usar o cast direto

$array = getArrayCopy($arrayObject);

Sempre que quiser testar, use esse script abaixo:

echo "<pre>";

echo htmlspecialchars( var_dump($arrayobject) );

echo "</pre>";

Existem outros métodos, como os “métodos Nat” que organizam um array pelo algoritmo de ordem natural.

Há também outros “métodos Offset”, como o offsetExists, offsetSet, offsetGet, que servem para manipular e verificar a existência de índices.

Todos eles bem bacanas.

Boa diversão!

Um abraço,

Diogo Besson

* SOARES, Walace. PHP 5 Conceitos, Programação e Integração com Banco de Dados. Segunda Edição. ISBN 85-365-0031-X. Editora Érica. São Paulo – SP. 2006

5 Comments

  1. diogobesson

    Sobre o cast de objetos, nosso colega Igor Escobar ( http://blog.igorescobar.com ) deu a seguinte dica na lista PHP Google ( http://groups.google.com.br/group/listaphp ):

    “Em determinados momentos precisamos criar objetos ou classes sem que elas existem. (sic)

    É o mesmo conceito de lambda functions, o mesmo conceito encontrado em linguagens como Ruby ou Python.

    Por exemplo, vou criar um OBJETO sem que ele exista.

    $objeto = (object) array(“nome” => “Igor Escobar”, “twitter” => “@igorescobar”);

    print_r($objeto)

    Testa este script e você verá que eu criei um objeto sem que ele fosse previamente declarado ou implementado.”

    (Igor Escobar – por email – Subject: [ PHP – Google ] stdClass – Alguem me explica? – 31/07/2009 – 10:00h)

    Creio que isso pode ser feito pois todo objeto é um Object e tem suas propriedades e comportamentos herdados de Object. Polimorfismo no PHP.

    um abraço,

    Diogo Besson

  2. Pingback: Standard PHP Library (SPL) | Diogo Matheus Blog

  3. ronaldo

    muito bom! php é animal!

  4. Sandro

    Amigo,

    Em primeiro lugar, parabéns pelo post!

    Estou tendo contato com php a pouco tempo mas prefiro fazer as coisas de modo mais arrumadinho e profissional.

    A dúvida é a seguinte:

    Tenho um consulta retornando do banco de dados.

    Inseri estes retornos num objeto.

    Ex: A consulta (Select * from carros) retornou varias linhas de carros com suas características.

    lancei cada carro num objeto carro.

    depois peguei todos os carros e lancei num array de objetos:

    $todosOsCarros = new ArrayObject();

    while($registro= mysqli_fetch_assoc($result)){

    $carro = new Carro();

    $carro->setId($registro['id']);

    $carro->setMarca($registro['marca']);

    $carro->setModelo($registro['modelo']);

    $carro->setAno($registro['ano']);

    $todosOsCarros -> append($carro); // add carro ao array de carros

    }

    if (!is_null($todosOsCarros)){

    return $todosOsCarros;

    }

    —————————————————————————-

    pronto, estou exportando para outra tela por meio de um array de carros todos os objetos carros para serem listados.

    a questão é, como eu percorro esses elementos dentro desse ArrayObject ???

    Grato pela ajuda!

    Sandro

  5. Diogo Besson (Post author)

    Oi Sandro,

    Não sei se entendi muito bem a sua dúvida, mas acho que respondi ela no post. Com um foreach simples dá pra correr o ArrayObject

    foreach ($arrayObject_3 as $key => $value) {
    echo “$key: $value n”;
    }

    Outra forma, mais interessante, seria percorre-lo usando o ponteiro que você criou usando o getIterator.
    getIterator()->current()/next()/key()/rewind()/seek(int $chave)/valid()

    Era isso?
    Abraço,
    Diogo

Leave a Comment

O seu endereço de e-mail não será publicado.