Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá, pessoal!
Estou com uma dúvida xarope. Como ArrayObject consegue assinalar array multimensionais através da ArrayAccess?
Tentei implementar a interface, mas quando acesso:
$arr["um"]["dois"] = "tres";
O método offsetSet não recebe valor no segundo parâmetro.
Se alguém souber como solucionar, agradeço muito!
O meu problema não é quanto ao ArrayObject, isto funciona perfeitamente:
$arr = new ArrayObject;
$arr["um"]["dois"] = "tres";
echo $arr["um"]["dois"];
O problema é quando tento implementar ArrayAccess e não consigo resultados como o acima.
class ArrayAccessImplementation implements ArrayAccess
{
private $data = array();
function offsetSet($offset, $value) $this->data[$offset] = $value;
}
function offsetGet($offset) return $this->data[$offset];
}
function offsetUnset($offset) unset($this->data[$offset]);
}
function offsetExists($offset) return isset($this->data[$offset]);
}
}
$arr = new ArrayAccessImplementation;
$arr["um"]["dois"] = "tres";
echo $arr["um"]["dois"];Jaime, o que exatamente você está tentando fazer ?
Veja só:
class ArrayAccessImplementation extends ArrayObject {
}
$arr = new ArrayAccessImplementation();
$arr["um"]['dois'] = "tres";
echo $arr["um"][ 'dois' ]; //tres>
Jaime, o que exatamente você está tentando fazer ?
Veja só:
class ArrayAccessImplementation extends ArrayObject {
}
$arr = new ArrayAccessImplementation();
$arr["um"]['dois'] = "tres";
echo $arr["um"][ 'dois' ]; //tres
João, minha dúvida é sobre a implementação da interface. ArrayObject implementa e acessa tranquilamente varias dimensões. Quando crio uma classe que implementa ArrayAccess não consigo o mesmo comportamento. É evidente que ao estender ArrayObject eu obtenha o mesmo comportamento, mas digamos que o que quero seja implementar a interface ArrayAccess (que dá a um objeto acesso como array...) e acessá-lo como array.
Alguém já conseguiu? Em versões maiores que 5.1? A interface será descontinuada?
>
...mas digamos que o que quero seja implementar a interface ArrayAccess (que dá a um objeto acesso como array...) e acessá-lo como array.
Alguém já conseguiu?
Bom, Jaime.
O fato é que a ArrayObject é um objeto SPL e é compilado, então o comportamento dele é realmente um pouco diferente.
Mas, nada que um código POG não resolva:
<?php
class MyArrayAccessImplementation implements ArrayAccess {
private $storage;
public function __construct(){
$this->storage = array();
}
public function offsetGet( $key ){
if ( $this->offsetExists( $key ) ) $ret = $this->storage[ $key ];
else {
$ret = new MyArrayAccessImplementation();
$this[ $key ] = $ret;
}
return $ret;
}
public function offsetExists( $key ){
return isset( $this->storage[ $key ] );
}
public function offsetSet( $key , $value ){
$this->storage[ $key ] = $value;
}
public function offsetUnset( $key ){
if ( $this->offsetExists( $key ) ){
unset( $this->storage[ $key ] );
}
}
}
$teste = new MyArrayAccessImplementation();
$teste[ 'um' ][ 'dois' ] = 'três';
echo $teste[ 'um' ][ 'dois' ];
Saída:
>
três
Claro que, como eu disse, é um código POG...
>
Em versões maiores que 5.1? A interface será descontinuada?
Não, pelo menos na 5.3 (que é a que eu uso) e na 6 não será descontinuada, não posso afirmar se no futuro, após o PHP 6, ela o será...
Vale ressaltar que ArrayObject não implementa apenas ArrayAccess, como também Traversable e IteratorAggregate, além de Serializable e Countable que não são interessantes para nós no momento
>
também Traversable e IteratorAggregate, além de Serializable e Countable
A Traversable é apenas para "tipar" um objeto que pode ser iterado em um foreach, o IteratorAggregate não influi no comportamento da ArrayAccess a Serializable permite que um ArrayObject seja gravado em sessão ou em disco e Countable permite que saibamos quantos itens estão armazenados no objeto.
Sim, quando se tenta implementar Traversable o PHP gera um erro dizendo que a mesma deve ser usada através de Iterator(Aggregate).
Ele deveria implementar Serializable e Countable se desejasse ter um comportamento idêntico ao de array, onde poderíamos passar um for($i = 0, $ln = sizeof($obj); $i < $ln; $i++) { ... } - Por exemplo.
>
onde poderíamos passar um for($i = 0, $ln = sizeof($obj); $i < $ln; $i++) { ... } -
Nesse caso, para uso com sizeof() ou count(), apenas o Countable resolveria. Se ele não vai serializar, Serializable é desnecessário.
<?php
class Teste implements Countable {
private $total;
public function __construct( $total ){
$this->total = $total;
}
public function count(){
return $this->total;
}
}
var_dump( count( new Teste( 10 ) ) ); //int(10)
var_dump( sizeof( new Teste( 20 ) ) ); //int(20)
;)João, agradeço muito sua atenção. Nesse meio tempo, acabei pesquisando e descobri que a interface teve a assinatura alterada de umas versões para cá:
de ArrayAccess::&offsetGet() para ArrayAccess::offsetGet(), o que por acaso acabou ocasionando problemas para arrays com mais de uma dimensão. Até quando retornara & isso não acontecia.
Agradeço muito o envolvimento de todos os que participaram. Obrigado!
o offset um deve ser um array ou no caso de OO implementada, outro ArrayObject
Indo na mão contrária, temos que "três" está armazenada em uma variável qualquer, que dentro de "um" é chamada de "dois" mas poderia se chamar "2", "two", etc
$minhavar = "três";
O construtor de ArrayObject só aceita objetos iteráveis, se lançarmos diretamente $minhavar dentro de um new ArrayObject geraríamos uma exceção.