我们如何在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();
答案 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;
}
当然,如果您需要将它们传递给您的方法 foo、bar 等,您可以扩展它以接受其他参数...
链接的用法是:
$a->when($cond === true, function ($a) {
return $a->foo();
})->when($cond !== true, function ($a) {
return $a->bar();
}
)->baz(); // a regular chaining method without condition