Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Jaime_Pinheiro

[Resolvido] ArrayAccess e arrays multidimensionais

Recommended Posts

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!

Compartilhar este post


Link para o post
Compartilhar em outros sites

o offset um deve ser um array ou no caso de OO implementada, outro ArrayObject

 

<?php

$arr = new ArrayObject();
$arr['um'] = new ArrayObject();
$arr['um']['dois'] = 'três';

echo $arr['um']['dois'];

 

 

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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"];

Compartilhar este post


Link para o post
Compartilhar em outros sites

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

Compartilhar este post


Link para o post
Compartilhar em outros sites

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?

Compartilhar este post


Link para o post
Compartilhar em outros sites

...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á...

Compartilhar este post


Link para o post
Compartilhar em outros sites

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

Compartilhar este post


Link para o post
Compartilhar em outros sites

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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)

 

;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

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!

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.