Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 哄骗式_Php_Design Patterns_Chaining_Object Oriented Analysis - Fatal编程技术网

Php 哄骗式

Php 哄骗式,php,design-patterns,chaining,object-oriented-analysis,Php,Design Patterns,Chaining,Object Oriented Analysis,我在php中有一个类,它与chaining方法一起工作,但问题是我想以某种顺序链接这些方法 class Chain { public function foo () { return $this; } public function bar () { return $this; } public function some () { return $this; } } 因此,如果我使用这个类,那么我可以用9种不同的方式链接这个方法(3个元素的所有

我在php中有一个类,它与chaining方法一起工作,但问题是我想以某种顺序链接这些方法

class Chain {
  public function foo () {
    return $this;
  }
  public function bar () {
    return $this;
  }
  public function some () {
    return $this;
  }
}
因此,如果我使用这个类,那么我可以用9种不同的方式链接这个方法(3个元素的所有可能组合)

但是,如果我确定方法
some
总是必须在
foo
bar
之后链接,而不是以其他方式链接,会发生什么

$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
我想我可以设置布尔值,比如:当调用方法
foo
bar
时,我将某个变量的值设置为
true
,当开发人员调用
some
函数时,如果该变量是
false
,则抛出异常,否则允许继续

但我需要一些更优雅的东西,比如模式或内置解决方案


还有另一种方法吗?

强制呼叫者按照特定的呼叫顺序进行呼叫,就像结束本身一样,几乎没有任何用处。假设您真正感兴趣的是在调用
some()
时确保对象的状态是有效的,如果不是,则抛出异常。在这种情况下,是的,您将检查对象状态的某些指示器,并在该状态不满足可调用的
some()
要求时引发异常。作为一个具体例子:

$api = new SomeAPI;
$api->setUserID($id);
$api->setSecretKey($secret);
$api->call('something');
这里的
call()
将检查用户id和访问密钥是否已设置,否则它将无法完成其工作。这些调用是否链接是不相关的,只是一个语法细节

或者,您可以从方法中返回其他(子)类的某些对象,如果某些条件尚未满足,则在物理上无法对这些对象调用某些方法:

public function bar() {
    if ($this->foo) {
        return new SubFoo($this->foo);
    } else {
        return new SubBar;
    }
}

不过,这可能过于复杂。

我想象的这个非常粗糙的示例在每个方法中仍然会有一些代码行

<?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;
  }
}
致命错误:未捕获异常“exception”,消息为“Some” “例外”在

没关系

这里的问题是我们建立了一个“公约”。您需要将
\uuuu方法\uuuu
传递给register函数,这样在它替换类名之后,它将只在数组中添加方法名。因此,稍后,在需要验证在此之前是否调用了一个或多个函数的函数中,需要使用方法名称作为字符串,即
$this->verify('foo')

当然,如果您正在验证某个方法或smth其他方法,您可以在不使用
strpos()
剥离和测试的情况下播放不同的场景,或者在方法名称后添加
()
,以便于识别

但至少它会让你不用为每种方法制作不同的变量来填充

function foo() {
    $this->_foo = true;
    return $this;
}
function bar() {
    $this->_bar = true;
    return $this;
}

如果您不想调用
bar()
如果以前没有调用
foo()
,那么除了检查返回值之外没有其他方法。您可以创建一个代理方法(包装器),该方法可以完成所有工作,只需在
bar()
中调用它,并指向param
foo()
$chain = new Chain();
$chain->foo()->some()->foo(); // ok
function foo() {
    $this->_foo = true;
    return $this;
}
function bar() {
    $this->_bar = true;
    return $this;
}