PHP Last Object of Method Chaining

Em PHP, usando o encadeamento de methods, como se trataria de fornecer uma chamada funcional depois que o último método fosse chamado na cadeia?

Também durante a mesma instância (veja abaixo). Isso mataria a idéia de implementar um destruidor.

O resultado final é um valor de retorno e uma chamada funcional de “inserção” (“privada”) das propriedades de cadeia definidas (é claro) sem ter que chamá-lo publicamente, independentemente da ordem.

Observe, se eu ecoar (__toString) os methods em conjunto, recuperaria o código exclusivo gerado final, que é o comportamento normal de lançar uma seqüência de caracteres.

Exemplo abaixo:

class object { private $data; function __construct($name) { // ... some other code stuff } private function fc($num) { // some wicked code here } public function green($num) { $this->data .= fc($num*10); return $this; } public function red($num) { $this->data .= fc($num*25); return $this; } public function blue($num) { $this->data .= fc($num*1); return $this; } // how to get this baby to fire ? private function insert() { // inserting file_put_content('test_code.txt', $this->data); } } $tss = new object('index_elements'); $tss->blue(100)->green(200)->red(100); // chain 1 $tss->green(0)->red(100)->blue(0); // chain 2 $tss->blue(10)->red(80)->blue(10)->green(0); // chain 3 

A Cadeia 1 , 2 e 3 gerariam um código exclusivo com todos os valores dos methods e fornecem uma ação, por exemplo inserindo automaticamente em DB ou criando um arquivo (usado neste exemplo).

Como você pode ver, nenhuma configuração de string ou lançamento ou eco está acontecendo.

Você poderia manter uma lista de coisas que precisam ser inicializadas e se elas foram ou não neste caso ou não. Em seguida, verifique a lista cada vez que você usa um dos methods de boot. Algo como:

 class O { private $init = array ( 'red' => false , 'green' => false , 'blue' => false ); private function isInit() { $fin = true; foreach($this->init as $in) { $fin = $fin && $in; } return $fin; } public function green($n) { $this->init['green'] = true; if($this->isInit()) { $this->insert(); } } public function red($n) { $this->init['red'] = true; if($this->isInit()) { $this->insert(); } } public function blue($n) { $this->init['blue'] = true; if($this->isInit()) { $this->insert(); } } private function insert() { echo "whee\n"; } } 

Mas, pessoalmente, acho que isso seria mais complicado, então vale a pena. Melhor imo para expor o seu método de insert e deixar o usuário de seu código indicar quando a boot estiver concluída. Então, algo que deve ser usado como:

 $o->red(1)->green(2)->blue(0)->insert(); 

-atualizar-

Se for o caso de que é impossível prever o que as funções precisam ser chamadas, você realmente precisa ser explícito sobre isso. Não consigo ver uma maneira de contornar isso. A razão é que o php realmente não pode dizer a diferença entre

 $o1 = new A(); $o2 = $o1->stuff(); 

e

 $o2 = (new A())->stuff(); 

Em um idioma que permite a sobrecarga = eu acho que seria possível, mas realmente realmente confuso e geralmente não é uma boa idéia.

É possível mover a parte explícita para que não esteja no final da cadeia de chamadas, mas não tenho certeza se isso faria você mais feliz? Também iria contra o seu desejo de não usar outra instância. Poderia parecer algo assim:

 class O { public function __construct(InitO $ini) { // Do stuff echo "Whee\n"; } } class InitO { public function red($n) { return $this; } public function green($n) { return $this; } public function blue($n) { return $this; } } $o = new O((new InitO())->red(10)->red(9)->green(7)); 

Você pode, naturalmente, usar apenas uma instância usando alguma outra maneira de embrulhar, mas as únicas maneiras pelas quais eu posso pensar agora pareceriam muito mais feias.

Eu estou com PeeHaa, isso não faz sentido! 🙂

Apenas a chance de ter algo mágicamente acontecido após a última cadeia ser usada (sem poder olhar para o futuro) é uma function Destrutor / Desligamento OU um lançamento / binding manual para inserir ()

Você também pode decidir implementar isso de forma estática sem usar objects.

 < ?php class Object { private static $data; public static function set($name) { // ... some other code stuff } private static function fc($num) { // some wicked code here } public static function green($num) { self::$data .= self::fc($num*10); return new static; } public static function red($num) { self::$data .= self::fc($num*25); return new static; } public static function blue($num) { self::$data .= self::fc($num*1); return new static; } // how to get this baby to fire ? public static function insert() { // inserting file_put_content('test_code.txt', self::$data); } } //$tss = new object('index_elements'); $Object::set('index_elements')->blue(100)->green(200)->red(100)->insert(); // chain 1 $Object::set('index_elements')->green(0)->red(100)->blue(0)->insert(); // chain 2 $Object::set('index_elements')->blue(10)->red(80)->blue(10)->green(0)->insert(); // chain 3 ?>