Back-End

25 mar, 2014

SPL – menos programação orientado a Arrays

Publicidade

Orientação a objetos nada mais é que um paradigma de programação. Esse paradigma não é novo, desde a década de 60 já existiam linguagens que davam suporte a essa metodologia de desenvolvimento, e no PHP desde a versão 5.3 isso está de uma forma bem consistente. Nessa versão além de melhorar consideravelmente o suporte a OO, também foi criada a SPL, e é dela que pretendo falar nesse artigo.

Porém esse não é mais um artigo ensinando como trabalhar com essa lib. Meu objetivo aqui é tentar despertar seu interesse em conhecê-la melhor e finalmente começar a fazer uso dela no seu dia-a-dia. Não tenho a pretensão de abordar todas as possibilidades da SPL; vou apenas apresentar alguns dos recursos que tenho utilizado para um desenvolvimento mais orientado a objetos, e, portanto é importante que visite a sessão da SPL no manual do PHP.

Standard PHP Library ou SPL é uma coleção de classes e interfaces que servem para resolver problemas padrões no mundo PHP, seu principal objetivo é prover interfaces que permita os desenvolvedores fazer um uso completo das vantagens da programação orientado a objetos.

Algo que aparece muito forte na SPL é a forma como ela trabalha com a organização e a interação de dados. Ela nos fornece outras formas além de arrays para guardar coleções, fazer acesso avançado a arrays, acesso avançado a diretórios e arquivos e outros, e principalmente, otimizando o consumo de memória e de uma forma OO.

SPL Interators

Como poderá ver, interagir com Interators é basicamente o mesmo que interagir com arrays, porem o real benefícios do Interator aparece quando interamos sobre uma grande quantidade de dados. As diferenças são muito pequenas e implícitas. Enquanto usando array alocamos o mesmo inteiramente na memória, usando Iterators carregamos na memória apenas o elemento corrente, otimizando assim os recursos do servidor.

Quando estamos falando de Interators, as funcionalidades que na minha opinião se destacam são: ArrayInterator, ArrayObject, FilterInterator, DirectoryIterator, GlobIterator e LimitIterator, e são esses que gostaria de mostrar alguns exemplos de uso.

ArrayInterator

<?php

$arr = array("Banana", "Abacaxi", "Abacate", "Morango");
$iter = new ArrayIterator($arr);

// loop through the object
foreach ($iter as $key => $value) {
    echo $key . ": " . $value . "<br>";
}

$iter->rewind();
echo 'O primeiro - '. $iter->current();

ArrayObject

$db = new PDO("mysql:host=localhost; dbname=mysql; ", 'root','');

$stmt = $db->query('SELECT * FROM help_keyword');
$result = $stmt->fetchAll(PDO::FETCH_CLASS, 'stdClass');

$collection = new ArrayObject($result);
echo 'Total - '. $collection->count() . '<br>';
echo "Posição 10 - " .$collection->offsetGet(10)->name . '<br>';

foreach ($collection->getIterator() as $member) {
    echo $member->name . "<br>";
}

DirectoryIterator

$dir = new DirectoryIterator(__DIR__);
foreach ($dir as $file) {
    echo $file->getFilename().'<br>';
}

GlobIterator

//todos os arquivos q comecem com a letra a
$dir = dirname(__FILE__).'/files/a*.*';
$files = new GlobIterator($dir);
foreach ($files as $file) {
    echo $file->getPathname() . '<br>';
}

FilterInterator

//retirando as pastas ./ e ../ da listagem
class DirectoryFilterDots extends FilterIterator
{
    public function __construct($path)
    {
        parent::__construct(new RecursiveDirectoryIterator($path));
    }
    public function accept()
    {
        return !$this->getInnerIterator()->isDot();
    }
}

$path = new DirectoryFilterDots(dirname(__FILE__));

foreach ($path as $file) {
    if($file->isDir()){
        echo '<b>diretorio</b> - ';
    }
    echo $file->getFilename() . '</br>';
}

LimitIterator

$path = new DirectoryIterator(dirname(__FILE__).'/files');
foreach (new LimitIterator($path, 2, 1) as $file) {
    $file->getFilename() .'<br>';
}

Estrutura de dados

Uma estrutura de dados é um modelo lógico para organizar informações de forma eficiente. Com a SPL temos implementado várias estruturas de dados, como pilha, fila, arrays de tamanho fixo etc. Uma estrutura de dados se faz mais útil quando estamos usando um array apenas para organizar dados sem estar usando recursos provido pelo array, e a adoção delas pode melhorar muito o desempenho de sua aplicação.

As mais simples de usar são: SplObjetStorage, SplFixeArray,SplStack e SPLQueue

SplStack

$stack = new SplStack();
$stack->push('b');
$stack->push('a');
echo $stack->pop()."<br>";
echo $stack->pop()."<br>";

SplQueue

$q = new SplQueue();
$q->push(new stdClass);
$q->push(2);
$q->pop();
print_r($q);

SplObjectStorage

$s = new SplObjectStorage();

$o1 = new StdClass;
$o2 = new StdClass;

$s->attach($o1);
$s[$o2] = array(1,2,3);

var_dump($s->contains($o1));//true
var_dump($s->contains($o3));//false

$s->detach($o2);

SplFixedArray

$array = new SplFixedArray(5);

$array[1] = 2;
$array[4] = "foo";
var_dump($array[0]); // NULL
var_dump($array[1]); // int(2)
var_dump($array["4"]); // string(3) "foo"
// Increase the size of the array to 10
$array->setSize(10);

File Handle

A SPL oferece acesso avançado a arquivos e diretórios, dando aos programadores uma abordagem totalmente OO para trabalhar com “files system”.

<?php
$file = new SplFileObject("fwrite.txt", "w");
$written = $file->fwrite("12345");
echo "Wrote $written bytes to file";

$file = new SplFileObject("file.txt");
while (!$file->eof()) {
    echo $file->fgets();
}

$fileinfo = new SplFileInfo('/tmp/foo.txt');
if ($fileinfo->isWritable()) {
    $fileobj = $fileinfo->openFile('a');
    $fileobj->fwrite("appended this sample text");
}

$path = new DirectoryIterator(dirname(__FILE__).'/files');
foreach (new LimitIterator($path, 2, 1) as $file) {
    $file->openFile('w')->fwrite('writed 1');
}

Para aplicar o Observer Pattern

Quando estamos implementando o Observer Pattern, precisamos de duas interfaces, subject que deve ser implementado pela classe que vai ser observado e Observer que deve ser implementado pela classe que vai observar. Não precisamos criar essas interfaces, pois a SPL já as trouxe com os nomes SPLSubject e SplObserver, bastando somente implementá-las nas suas respectivas classes. Abaixo um exemplo retirado do manual do PHP.

class Newspaper implements \SplSubject{
private $name;
private $observers = array();
private $content;

public function __construct($name) {
    $this->name = $name;
}
//add observer
public function attach(\SplObserver $observer) {
    $this->observers[] = $observer;
}

//remove observer
public function detach(\SplObserver $observer) {

$key = array_search($observer,$this->observers, true);
    if($key){
         unset($this->observers[$key]);
    }
}

//set breakouts news
public function breakOutNews($content) {
    $this->content = $content;
    $this->notify();
}

public function getContent() {
    return $this->content." ({$this->name})";
}

//notify observers(or some of them)
public function notify() {
    foreach ($this->observers as $value) {
        $value->update($this);
    }
}
}
/**
* Observer,that who recieves news
*/
class Reader implements SplObserver{
    private $name;

    public function __construct($name) {
         $this->name = $name;
    }

     public function update(\SplSubject $subject) {
         echo $this->name.' is reading breakout news <b>'.$subject->getContent().'</b><br>';
     }
}

$newspaper = new Newspaper('Newyork Times');
$allen = new Reader('Allen');
$jim = new Reader('Jim');
$linda = new Reader('Linda');

//add reader
$newspaper->attach($allen);
$newspaper->attach($jim);
$newspaper->attach($linda);

//remove reader
$newspaper->detach($linda);

//set break outs
$newspaper->breakOutNews('USA break down!');

Conclusão

A SPL não é mais nenhuma novidade e já está disponível desde o PHP 5.3, mas a maioria dos seus recursos continua sendo muito importante no desenvolvimento de software com PHP. Nas novas versões do PHP surgiram novas funcionalidades que vão de encontro às encontradas na SPL, mas nenhuma delas substitui a importância da SPL. Tiveram vários recursos da SPL que não foram mencionados aqui e que merecem sua atenção, por isso não deixem de visitar a sessão da SPL na documentação do PHP.

Referências