PHP方法链接的最后一个对象


PHP Last Object of Method Chaining

在使用方法链的PHP中,在链中调用最后一个方法之后,如何提供函数调用?

同时使用相同的实例(请参见下文)。这将扼杀实现析构函数的想法。

最终结果是从定义的链属性(当然)中返回值并调用私有"insert()",而不必公开调用它,无论顺序如何。

注意,如果我一起回显(__toString)这些方法,它将检索最终生成的唯一代码,这是强制转换字符串的正常行为。

以下示例:

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

123将生成一个唯一的代码,给定方法中的所有值,并提供一个操作,例如自动插入数据库或创建文件(在本例中使用)。

正如您所看到的,没有发生字符串设置、铸造或回显。

您可以保留一个需要初始化的东西的列表,以及它们是否在这种情况下是否如此。然后在每次使用时检查列表初始化方法之一。类似于:

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";
    }
}

但就我个人而言,我认为这会比它的价值更麻烦。更好的imo公开您的insert方法,并让您的代码用户告诉初始化完成。所以应该使用的东西是:

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

-更新-

如果是无法预测需要调用什么函数的情况你真的需要明确一点。我看不出有什么办法。原因php真的分不清

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

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

在一种允许重载=的语言中,我想这是可能的,但实际上真的很令人困惑,通常不是一个好主意。

可以移动显式部分,使其不在调用的末尾链条,但我不确定这是否会让你更快乐?这也会违背你不想使用其他实例的愿望。它可能看起来像这样:

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));

当然,您可以通过使用其他包装方式仅使用一个实例但我现在唯一能想到的办法就是看起来更丑。

我和PeeHaa在一起,这毫无意义!:)

在使用最后一个链后(无法展望未来),唯一有可能神奇地发生的事情是Destructor/Shutdown函数或手动强制转换/调用insert()

您还可以决定在不使用对象的情况下静态实现此功能。

<?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
?>

好的,让我们看看的代码示例

<?php
// map dummy class
class map
{
// __call magic method
public function __call($name, $args)
{
return $this;
}
}
// now we chain
$map = new map;
// let's find me
$map->start('here')
->go('right')
->then()
->turn('left')
->and('get water')
->dontEat()
->keep('going')
->youShouldSeeMe('smiling');

在这里,我们不知道最后一个方法是什么,我们需要在到达末尾时触发某种操作或事件。

根据数据结构,我们可以称之为后进先出堆栈。(后进先出)

那么我是如何在PHP上解决这个问题的呢?

//我做了一些回溯

返回__call函数

function __call($name, $args)
{
$trace = debug_backtrace()[0];
$line = $trace['line'];
$file = $trace['file'];
$trace = null;
$getFile = file($file);
$file = null;
$getLine = trim($getFile[$line-1]);
$line = null;
$getFile = null;
$split = preg_split("/(->)($name)/", $getLine);
$getLine = null;
if (!preg_match('/[)](->)('S)/', $split[1]) && preg_match('/[;]$/', $split[1]))
{
// last method called.
var_dump($name); // outputs: youShouldSeeMe
}
$split = null;
return $this;
}

一旦我们触底,我们可以称之为wholla。*(注意,一旦我处理完一个变量,我就使用null,我来自C家族,我们自己管理内存)

希望它能以某种方式帮助你。