PHP方法链接和字符串

时间:2012-07-15 03:31:20

标签: php method-chaining

这是一个有趣的怪癖,我发现方法链接时,我很难绕过它。我确信有解决方案或其他方式。这很难解释,但我会尽我所能。

示例:

您有三个函数属于类的一部分,以及2个受保护的属性,如下所示。

class Chain {

  protected $_str  = '';
  protected $_part = 0;

  public function __toString() {
    return implode(' ', $this->_str);
  }

  public function AAA () {
    $this->_str[$this->_part] = 'AAA';
    $this->_part++;
    return $this;
  }

  public function BBB () {
    $this->_str[$this->_part] = 'BBB';
    $this->_part++;
    return $this;
  }

  public function wrap ($str) {
    $part = $this->_part - 1;
    $this->_str[$part] = "({$str})";
    return $this;
  }

}

现在,在链接这些方法并特别使用wrap方法时,无意中会附加以前链中的字符串。例如:

$chain = new Chain();
$chain->AAA()->BBB()->wrap($chain->AAA());
echo $chain;

您希望字符串看起来像AAA BBB (AAA)

然而,实际返回的是AAA BBB (AAA BBB AAA)

为什么wrap()采用链中调用的所有先前方法而不仅仅是实际包含它的方法?假设有一个最好的方法是什么?

3 个答案:

答案 0 :(得分:2)

$chain->AAA()->BBB()正在做前两个'AAA'和'BBB' - 显而易见 然后$chain->AAA()内的wrap($chain->AAA())执行第3个'AAA' 最后,wrap方法获取所有三个并用()包装它们并使用以下行连接到第一个'AAA'和'BBB':$this->_str[$part] = "({$str})";
哪个结算致:AAA BBB (AAA BBB AAA).

<强>更新
我相信您要做的是避免从方法thisAAA()返回BBB()的副作用 - 将通过以下更改实现:

<?php
class Chain {

  protected $_str  = '';
  protected $_part = 0;

  public function __toString() {
    return implode(' ', $this->_str);
  }

  public function AAA () {
    $this->_str[$this->_part] = 'AAA';
    $this->_part++;
    return "AAA";
  }

  public function BBB () {
    $this->_str[$this->_part] = 'BBB';
    $this->_part++;
    return "BBB";
  }

  public function wrap ($str) {
    $part = $this->_part - 1;
    $this->_str[$part] = "({$str})";
    return $str;
  }

}

$chain = new Chain();
$chain->AAA();
$chain->BBB();
$chain->wrap($chain->AAA());
echo $chain->__toString();

?>

答案 1 :(得分:1)

我称之为'竞争条件'。似乎PHP首先解释$chain->AAA()->BBB()

然后$chain->_part为2,$chain->_str为'AAA BBB'。

然后,为了能够调用wrap,参数,所以运行$chain->AAA()

然后$chain->_part为3,$chain->_str为'AAA BBB AAA'。

最后调用wrap,扭曲'AAA BBB AAA'。我会分开wrap() - 调用并将$chain->_part重置为零。

答案 2 :(得分:0)

调用队列是:

1. $chain->AAA() //this is first method not in wrap() method, you have now AAA
2. $chain->BBB() //then next method, you have now AAA BBB
3. $chain->AAA() //again AAA() method inside wrap method, so you have AAA BBB AAA

wrap()内置链(在第3步之后是AAA BBB AAA)字符串in(),所以你在_part数组末尾有AAA BBB AAA字符串。