O Zen e a arte cavalheiresca da programação orientada a objeto (Parte 26)
Para ver os artigos anteriores desta série, clique aqui.
Ah, as olimpíadas. Atletas abnegados que se dedicaram durante anos para tentar a glória. Toda uma vida de treinos e sacrifícios é colocada à prova em frações de segundos. Um mísero erro, e toda a preparação vai por água abaixo.
A vida destes atletas, meus caros, guardadas as devidas proporções de massa muscular e gordura corporal, é parecida com a vida dos programadores. Um mísero erro, e todo o banco de dados vai pro saco. Um segundo a mais de performance perdida, e o servidor não aguenta o tranco. Portanto, meus atléticos leitores, ao celebrar as olimpíadas e virar a noite para ver aquele jogaço de hóquei na grama feminino não se esqueça: parte do solo sagrado do olimpo também é sua!
Ruminâncias sem nexo à parte, hoje quero mostrar mais uma jogada da biblioteca SPL pra vocês. Lembram-se do nosso carrinho de compras? Bem, respeitáveis atletas, preciso dizer que ele não aguentou a pressão na final e se enrolou todo. Explico: do jeito que construímos este carregador de objetos, ele falha miseravelmente se a gente simplesmente incluir o mesmo objeto mais de uma vez. Experimente. Duplique a linha abaixo e veja o carrinho se comportar de forma muito estranha, listando o mesmo item duas vezes. Cartão vermelho.
Pra dizer a verdade, já existe um cara na SPL que faz essa função de carrinho de compras (e, claro, de qualquer outro conteiner de objetos que você quiser) de forma muito mais esperta. É a classe SplObjectStorage.
Uma coisa que essa classe faz é exatamente controlar os objetos que nela são guardados para evitar que o mesmo objeto seja incluído duas vezes. Mais do que isso, ela controla também updates; se você alterar o objeto e adicionar novamente à coleção a classe automaticamente atualiza os dados pra você. Ippon!
Veja só que beleza:
class CarrinhoDeCompras extends SplObjectStorage {
// nosso carrinho de compras é, no fundo, um array de objetos da classe Item...
private $carrinho = array();
//coloca um Item no carrinho
//usando type hinting, viu o Item antes da variavel? Isso diz que essa função só aceita objetos da classe Item...
public function adicionaItem(Item $item){
$this->attach($item);
}
//detona tudo no carrinho
public function esvaziaCarrinho(){
unset ($this->storage);
}
// ué cade o resto todo? Não precisa cara. A classe SplObjectStorage já traz tudo de brinde: ArrayAccess, Iterator e muito mais!
// uma inclusão boa pra nos aqui: que tal colocar a logica de impressao do carrinho logo aqui?
public function __toString(){
foreach($this as $item) { // <- $meucarrinho é um array? é um objeto? como???
$string .= "
" . "Código: " . $item->getCodigo() . " Descrição: " . $item->getDescricao() ." Preço: " . $item->getPreco() . " Quantidade: ". $item->getQuantidade();
$total += $item->getPreco() * $item->getQuantidade();
}
$string = $string . "
" . "O total da sua compra é: " . $total;
return "
" . $string . "
";
}
}
class Item {
private $codigo;
private $descricao;
private $preco;
private $quantidade;
public function __construct($codigo,$descricao,$preco,$quantidade){
$this->codigo = $codigo;
$this->descricao = $descricao;
$this->preco = $preco;
$this->quantidade = $quantidade;
}
public function getCodigo(){
return $this->codigo;
}
public function getDescricao(){
return $this->descricao;
}
public function getPreco(){
return $this->preco;
}
public function getQuantidade(){
return $this->quantidade;
}
public function setQuantidade($quantidade){
$this->quantidade = $quantidade;
}
}
//Muito bem, agora vamos la!
$meucarrinho = new CarrinhoDeCompras();
//aqui, pra provar nosso ponto, vamos ter que instanciar os objetos em variaveis pra poder tentar adicionar novamente o mesmo objeto
$item1 = new Item('1','Caneta Bic Azul','1.00','10');
$item2 = new Item('2','Caneta Bic Vermelha','1.50','5');
$item3 = new Item('3','Caneta Bic Quatro Cores','3.50','15');
$meucarrinho->adicionaItem($item1);
$meucarrinho->adicionaItem($item2);
$meucarrinho->adicionaItem($item3);
print $meucarrinho;
// agora a prova!
$item1->setQuantidade(30);
$meucarrinho->adicionaItem($item1);
print $meucarrinho;
?>
É isso aí pessoal! Até a próxima!
