Envolvendo uma classe PHP para facilitar o encadeamento de métodos

O encadeamento de métodos é um recurso interessante e útil especialmente para API sequencial procedural.

O que torna possível o encadeamento é retornar a cada chamada de método a instância do objeto chamado.

A classe Chainable é um invólucro simples para fazer chamadas de proxy para métodos de classe e retornar a referência de instância que permite o encadeamento de métodos.

Por exemplo, considere a classe Test, que possui três métodos:

class Test {
function foo(){ echo "FOO"; }
function baz(){ return "BAZ"; }
function bar(){ echo "BAR"; }
}

e este exemplo usa:

$test = new Test();

$test
->foo();
$value
= $test->baz();
$test
->bar();

echo
"n",'The value was : ',$value;

/* Output:
FOOBAR

The value was : BAZ

*/

Considere agora a oportunidade de métodos de cadeia, é isso que queremos alcançar:

$test->foo()->bar();

Para fazer isso, sem modificar a classe Test, devemos envolvê-la em outra classe de proxy e redirecionar todas as chamadas para a instância embalada.

class Chainable {
private $instance = null;
public function __construct(){
$pars
= func_get_args();
$this
->instance = is_object($obj=array_shift($pars))?$obj:new $obj($pars);
}

public function __call($name,$pars){
call_user_func_array
([$this->instance,$name],$pars);
return $this;
}

}

Agora podemos encerrar o teste com chamadas de métodos Chainable e chain:

$test = new Chainable('Test');

$test
->foo()->baz()->bar();

/* Output:
FOOBAR

*/

Agradável! Mas espere … baz () retorna um valor … mas nosso proxy está perdendo-o.
Podemos corrigir a captura de valores de método retornados em um cache interno e fornecer um método encadeado para recuperá-los:

private $_returns = [];

// Retrieve the returned value from last
// chained method

public function _get_return(&$var){
$var
= count($this->_returns)?
array_pop
($this->_returns):null;
return $this;
}

// Clear the returned value cache
public function _reset(){
$this
->_returns = [];
return $this;
}

// Redefine call proxy for saving returned values
public function __call($name,$pars){
($r=call_user_func_array([$this->instance,$name],$pars))?$this->_returns[]=$r:null;
return $this;
}

Agora, podemos recuperar o valor salvo durante a cadeia de chamadas:

$test = new Chainable('Test');
$test

->foo()
->baz()->_get_return($the_value)
->bar();

echo
"nn",'The value was : ',$the_value;
/* Output:
FOOBAR

The value was : BAZ

*/

E terminamos.

Você pode encontrar a aula completa e este exemplo aqui:
https://gist.github.com/lastguest/4732993