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

时间:2014-04-17 17:01:59

标签: php oop methods chaining 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

1 2 3 会根据方法中的所有值生成唯一代码并提供操作,例如自动插入DB或创建文件(在本例中使用)。

正如您所看到的,没有发生任何字符串设置或转换或回显。

4 个答案:

答案 0 :(得分:3)

您可以保留需要初始化的事项列表以及是否 在这种情况下是这样的。然后在每次使用时检查列表 一种初始化方法。类似的东西:

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

-update -

如果情况不可能预测需要调用哪些功能 你真的需要明确它。我无法看到解决方法。原因 是的,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));

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

答案 1 :(得分:1)

我和PeeHaa,这没有任何意义! :)

在使用最后一个链(无法展望未来)之后,只有神奇地发生某些事情的机会是Destructor / Shutdown函数或者手动转换/调用insert()

答案 2 :(得分:0)

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

belongsToMany

答案 3 :(得分:0)

好,让我们看一个代码示例

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

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

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

那我如何在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;
}

当我们触底时,whoolla我们可以叫任何东西。 *(请注意,一旦我完成了变量操作,我就会使用null,我来自我们自己管理内存的C系列)

希望这对您有帮助。