SPL ArrayAccess
Eae! Hoje vou continuar falando sobre SPL!
Se você ainda não conhece a SPL, dê uma lida no post anterior e conheça também a interface Countable da SPL.
Bom, o assunto de hoje é a interface ArrayAccess, que apesar de simples, possibilita que uma classe seja manipulada como um array.
A ArrayAccess, obriga que a classe implemente 4 métodos, são eles:
public boolean offsetExists(mixed $offset) public mixed offsetGet (mixed $offset) public void offsetSet(mixed $offset, mixed $value) public void offsetUnset(mixed $offset)
Através desses métodos, você conseguirá acessar a sua classe como se fosse um array, com algumas restrições é claro
Para demonstrar o uso da ArrayAccess, usarei as mesmas classes usadas do post anteriror, só adicionei a classe CarrinhoCompras onde será posteriormente implementada a ArrayAccess.
class Produto
{
private $nome;
private $preco;
public function __construct($nome, $preco)
{
$this->nome = $nome;
$this->preco = $preco;
}
/** GETTERS AND SETTERS **/
}
class Item implements Countable
{
private $produto;
private $quantidade;
public function __construct(Produto $produto, $quantidade)
{
$this->produto = $produto;
$this->quantidade = $quantidade;
}
public function count()
{
return $this->quantidade;
}
}
class CarrinhoCompras
{
private $itens;
private $data;
public function __construct($data)
{
$this->itens = array();
$this->data = $data;
}
}
Nesse exemplo, continuamos com nosso contexto de e-commerce, a classe Item possui um Produto e a quantidade desejada desse produto, e a classe CarrinhoCompras possui todos os Itens que estão sendo vendidos. Bem simples, apenas para demonstração
Agora sim, vamos ao que interessa! O atributo $itens, é um array de Itens, para acessar ele poderíamos criar um método getItens(), ou qualquer outro método que acesse esse atributo, mas aqui vou demonstrar como acessar ele através da ArrayAccess.
A classe CarrinhoCompras deve implementar a interface ArrayAccess, e implementar todos os métodos acima citados, como no exemplo abaixo.
class CarrinhoCompras implements ArrayAccess
{
private $itens;
private $data;
public function __construct($data)
{
$this->itens = array();
$this->data = $data;
}
public function offsetSet($offset, $value)
{
var_dump(__METHOD__);
$this->itens[$offset] = $value;
}
public function offsetExists($offset)
{
var_dump(__METHOD__);
return isset($this->itens[$offset]);
}
public function offsetUnset($offset)
{
var_dump(__METHOD__);
unset($this->itens[$offset]);
}
public function offsetGet($offset)
{
var_dump(__METHOD__);
return isset($this->itens[$offset]) ? $this->itens[$offset] : null;
}
}
No exemplo eu coloquei var_dump(__METHOD__) dentro de cada método para que você possa ver quando cada método é chamado. Agora vamos executar alguns testes para que você possa ver a utilização da ArrayAccess.
$produto = new Produto('Livro PHP', 78.50);
$item = new Item($produto, 5);
$produto1 = new Produto('Livro Java', 88.50);
$item1 = new Item($produto1, 1);
$carrinho = new CarrinhoCompras(new DateTime());
$carrinho[0] = $item;
$carrinho[1] = $item1;
var_dump($carrinho[0]);
Fácil não? Agora a sua classe é acessível como um array! Mas agora vamos as restrições
// Isso não funciona! // Apesar de a classe ser acessível como um array, ela não é um array... // Fazendo isso, você terá como resultado um foreach de todos os atributos public foreach ($carrinho as $c) var_dump($c); // Isso também não! array_push($carrinho, 'teste'); // Isso funciona! // Mas não como de costume... // O indice vazio, no caso de um array, teria o mesmo comportamento // Que array_push(), mas no caso de um objeto // O indice é covertido para NULL $carrinho[] = 'teste';
Você pode continuar chamando os métodos normalmente, ou seja.
// Isso funciona! $carrinho->offsetExists(0);
Abaixo uma breve explicação de cada método.
// Chamado quando usamos isset() ou empty() public boolean offsetExists(mixed $offset) // Chamado quando usamos empty() // NOTA: Só é chamado quando ArrayAccess::offsetExists() retorna true public mixed offsetGet (mixed $offset) // Chamado quando usamos $obj['index'] = 'teste' public void offsetSet(mixed $offset, mixed $value) // Chamado quando usamos unset() // NOTA: Fazendo casting para (unset) não chama esse método public void offsetUnset(mixed $offset)
É isso, espero que tenham gostado!
Não esqueçam de comentar e de ler a documentação, RTFM.


