【问题标题】:Check if call is method chaining检查调用是否是方法链
【发布时间】:2015-01-30 13:09:57
【问题描述】:

是否可以知道方法调用是否来自方法链接?
比如我有下面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;
}

【问题讨论】:

    标签: php method-chaining


    【解决方案1】:

    这是不可能的,因为您不知道将使用该方法的结果的上下文。

    您可以随时返回 $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;
        }
    }
    

    然后,如果您回显您的值 - 它会将其用作字符串,否则您将处理一个对象。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-12
        • 2014-02-02
        • 1970-01-01
        • 1970-01-01
        • 2019-06-06
        • 1970-01-01
        • 2016-09-16
        相关资源
        最近更新 更多