douyong1850 2014-01-06 11:09
浏览 7
已采纳

链式模式

I have a class in php that works with the chainning method, but the problem is that I want to chain the methods in some order.

class Chain {
  public function foo () {
    return $this;
  }
  public function bar () {
    return $this;
  }
  public function some () {
    return $this;
  }
}

So, if I use this class, then I can chain this methods in 9 different ways (all the possible combinations of 3 elements)

But what happen if I determine that the method some always must to be chained after foo or bar and not in other way?

$chain = new Chain();
$chain->foo->bar(); //works; i.e: the method some is optional
$chain->foo()->bar()->some(); //works
$chain->bar()->foo()->some(); //works
$chain->some()->bar()->foo(); //throws an exception

I think that I can do this setting boolean values, something like: when the method foo or bar are called, then I set the value to some var to true, and when the developer calls the some function, if that var is false, then throws an exception, otherwise is allowed to continue.

But I need something more elegant, such as pattern or a built-in solution.

There is another way to do it?

  • 写回答

2条回答 默认 最新

  • drmcm84800 2014-01-06 11:49
    关注

    The very rough example I imagine will still have some lines of code in each method

    <?php
    class Chain {
    
      private $_register = array();
    
      public function foo () {
        $this->register(__METHOD__);
        return $this;
      }
      public function bar () {
        $this->register(__METHOD__);
        return $this;
      }
      public function some () {;
        $this->verify('foo'); // foo() should be called before some();
        $this->register(__METHOD__);
        echo 'it\'s ok';
        return $this;
      }
      public function verify($method) {
          if(array_key_exists($method, $this->_register) && $this->_register[$method] == true) {
              return true;
          }
          else {
              throw new Exception('Some exception');
          }
      }
      public function register($method) {
          $method = str_replace(__CLASS__.'::', '', $method);
          $this->_register[$method] = true;
      }
    }
    

    What do we do here - we have a register() and verify() methods. (they can be helpers, but for the current purpose I added them in the class.

    Each method should have before it's returning value a register to itself. Calling $this->register(__METHOD__) from foo() will add in the private array 'foo' => true. The verify() method checks if foo exist as array key and if its value is true. If it is - the script will continue. Otherwise - throws exception.

    In this case:

    $chain = new Chain();
    $chain->bar()->some()->foo(); //throws an exception
    

    Fatal error: Uncaught exception 'Exception' with message 'Some exception' in ...

    $chain = new Chain();
    $chain->foo()->some()->foo(); // ok
    

    it's ok

    The problem here is that we establish a "convention". You need to pass __METHOD__ to the register function so after it replace the classname it will add only the method name in the array. So later, in the function where you need to verify if one or more functions are called before this, you need to use the method name as string i.e. $this->verify('foo');

    Ofcourse you can play different scenarios without stripping and testing with strpos() or adding () after the methodname for easier recognition if you are verifying a method or smth else.

    But at least it will save you from making for each method, different variable to fill i.e.

    function foo() {
        $this->_foo = true;
        return $this;
    }
    function bar() {
        $this->_bar = true;
        return $this;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 python忆阻器数字识别
  • ¥15 无法输出helloworld
  • ¥15 高通uboot 打印ubi init err 22
  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真