是否可以知道方法调用是否来自方法链接?
例如,我有下面的class
:
class Test{
protected $string = '123';
public function a($string){
$this->string .= $string;
if(method chain){
return $this;
}else{
return $this->string;
}
}
public function b($string){
$this->string .= $string;
if(method chain){
return $this;
}else{
return $this->string;
}
}
}
结果:
$test = new Test();
echo $test->a('000'); // 123000
echo $test->a('000')->b('www'); // 123000www
更新
我最终创建了一个exec()
方法来告诉不再调用方法。
public function exec(){
return $this->string;
}
答案 0 :(得分:2)
这是不可能的,因为你不知道将使用方法结果的上下文。
取而代之的是,您可以随时返回$this
只使用__toString
方法来返回$string
:
class Test{
protected $string = '123';
public function a($string){
$this->string .= $string;
return $this;
}
public function b($string){
$this->string .= $string;
return $this;
}
public function __toString() {
return $this->string;
}
}
然后,如果你要回显你的价值 - 它将把它用作一个字符串,否则你将处理一个对象。
答案 1 :(得分:0)
PHP确实提供了debug_backtrace
来检索每个已经使用文件位置和行号调用的函数。但这不会给出下一个函数调用。
通过使用文件位置和行号,我们可以解析源文件并获取链。
下面的getChains
函数将以某种编码风格工作。
<?php
$abc = new Methods;
echo($abc->minus(12)->plus(32)); // output: -12+32
echo(
$abc->plus(84)
->minus(63)
); // output: +84-63
class Methods{
private $data = '';
private $chains = false;
public function minus($val){
$this->data .= '-'.$val;
return $this->exec('minus');
}
public function plus($val){
$this->data .= '+'.$val;
return $this->exec('plus');
}
private function exec($from){
// Check if this is the first chain
if($this->chains === false){
$this->getChains();
}
// Remove the first chain as it's
// already being called
if($this->chains[0] === $from){
array_shift($this->chains);
}
else
die("Can't parse your chain");
// Check if this is the last chain
if(count($this->chains) === 0){
$copy = $this->data;
// Clear data
$this->chains = false;
$this->data = '';
return $copy;
}
// If not then continue the chain
return $this;
}
private function getChains(){
$temp = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// Find out who called the function
for ($i=0; $i < count($temp); $i++) {
if($temp[$i]['function'] === 'exec'){
$temp = $temp[$i + 1];
break;
}
}
// Prepare variable
$obtained = '';
$current = 1;
// Open that source and find the chain
$handle = fopen($temp['file'], "r");
if(!$handle) return false;
while(($text = fgets($handle)) !== false){
if($current >= $temp['line']){
$obtained .= $text;
// Find break
if(strrpos($text, ';') !== false)
break;
}
$current++;
}
fclose($handle);
preg_match_all('/>(\w.*?)\(/', $obtained, $matches);
$this->chains = $matches[1];
return true;
}
}