有条件地链式方法?

时间:2016-11-29 02:52:12

标签: php oop

我们如何在PHP中有条件地链接方法?例如,这很好用:

$a->foo()->bar->baz->qux();

但是,根据条件,我想链接一些方法而不是其他方法。基本上,缩短以下代码:

if ($cond === true) {
    $a->foo()->baz();
} else {
    $a->foo()->bar();
}

理想情况下,以下内容可行:

$a->foo()
    ->bar()
    ($cond === true) ? ->baz() : ->qux()
    ->more();

此外,我们如何根据条件有条件地链接方法(或不链接)?例如:

$a->foo()
    ->bar()
    if($cond === true) ->baz()
    ->more();

4 个答案:

答案 0 :(得分:3)

下面的自我解释模拟片段(您可以Quick-Test在这里)展示了如何做到这一点

<?php   

    class Test{
        protected $prop1;
        protected $prop2;
        protected $prop3;
        protected $prop4;

        public function __construct() {
        }

        public function setProp1($prop1) {
            $this->prop1 = $prop1;
            return $this;
        }

        public function setProp2($prop2) {
            $this->prop2 = $prop2;
            return $this;
        }

        public function setProp3($prop3) {
            $this->prop3 = $prop3;
            return $this;
        }

        public function setProp4($prop4) {
            $this->prop3 = $prop4;
            return $this;
        }
    }

    $a      = 2;
    $b      = 7;
    $cond   = ($a > $b);
    $cond2  = ($b > 50);
    $test   = new Test;

    $test->setProp1(2)->{($cond  === true)  ? 'setProp4' : 'setProp3'}(11);
    $test->setProp3(3)->{($cond2 === false) ? 'setProp2' : 'setProp4'}(6);

    var_dump($test);
    //YIELDS::
    object(Test)[1]
      protected 'prop1' => int 2
      protected 'prop2' => int 6
      protected 'prop3' => int 3
      protected 'prop4' => null

答案 1 :(得分:2)

你要找的是variable methods (see example #2).他们允许你这样做:

class a {
    function foo() { echo '1'; return $this; }
    function bar() { echo '2'; return $this; }
    function baz() { echo '3'; return $this; }
}
$a = new a();

$cond = true;
$a->foo()->{($cond === true) ? 'baz' : 'bar'}();
// Prints 13
$cond = false;
$a->foo()->{($cond === true) ? 'baz' : 'bar'}();
// Prints 12

这是一种允许您为每个函数调用设置需求的方法。请注意,这与以前的解决方案一样难以维护,如果不是更难。您可能也想使用某种配置和ReflectionClass's getMethods function

class a {
    function foo() { echo '1'; return $this; }
    function bar() { echo '2'; return $this; }
    function baz() { echo '3'; return $this; }
}

function evaluateFunctionRequirements($object, $functionRequirements, $condition) {
  foreach ($functionRequirements as $function=>$requirements) {
    foreach ($requirements as $requiredVariableName=>$requiredValue) {
      if (${$requiredVariableName} !== $requiredValue) {
        continue 2;
      }
    }
    $object->{$function}();
  }
}

$a = new a();
$functionRequirements = array('foo'=>array(), 'bar'=>array(), 'baz'=>array('condition'=>true));
$condition = true;
evaluateFunctionRequirements($a, $functionRequirements, $condition);
// Prints 123
$condition = false;
evaluateFunctionRequirements($a, $functionRequirements, $condition);
// Prints 12

注意:这为$functionRequirements数组添加更难维护需要函数。此外,这个基本示例只传递了一个可能的条件var,更新到另一个设置以获得更多$ requiredVariableName变量func_get_args。您还需要验证通过$ functionRequirements传入的方法是否is_callable()安全。

答案 2 :(得分:0)

通过将链接分配给变量来尝试此操作

$a = $a->foo();

if ($cond === true) {
   $a = $a->baz();
} else {
   $a = $a->bar();
}

$a->more();

答案 3 :(得分:0)

解决此问题的另一种方法是创建一个方法 when(或将其命名为对您有意义的任何名称):

    public function when($condition, $callback)
    {
        if ($condition) {
            return $callback($this) ?: $this;
        }
        return $this;
    }

当然,如果您需要将它们传递给您的方法 foobar 等,您可以扩展它以接受其他参数...

链接的用法是:

$a->when($cond === true, function ($a) {
    return $a->foo();
})->when($cond !== true, function ($a) {
    return $a->bar();
}
)->baz(); // a regular chaining method without condition