PHP方法链接和字符串


PHP Method Chaining and Strings

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

示例:

您有三个函数,它们是一个类的一部分,还有两个受保护的属性,如下所示。

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()接受链中以前调用的所有方法,而不是只接受它实际包装的方法?假设有一个,最好的方法是什么?

$chain->AAA()->BBB()正在执行前两个"AAA"answers"BBB"-显而易见
然后进入wrap($chain->AAA())内部的$chain->AAA()进行第三次"AAA"
最后,wrap方法获取所有三个,并用()包裹它们,并使用以下行连接到第一个"AAA"answers"BBB":$this->_str[$part] = "({$str})";
,解析为:AAA BBB (AAA BBB AAA).

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

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

我称之为一种"竞赛条件"。PHP似乎首先解释了$chain->AAA()->BBB()

$chain->_part为2,$chain->_str为"AAA BBB"。

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

则CCD_ 18为3,CCD_。

最后,包裹被称为"AAA BBB AAA"。我会分离wrap()-调用,并在两者之间将$chain->_part重置回零。

调用队列为:

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()中,您将链(第三步后为AAA BBB AAA)字符串放入()中,因此在_part数组的末尾有AAA BBB AA字符串。