PHP使用一个字符串调用多个方法

PHP使用一个字符串调用多个方法,php,reflection,Php,Reflection,我有以下字符串: $str = "methodA()->methodB()->methodC" 我想称之为物体上的“链” $obj->$str 我目前正在使用()->进行拆分并逐个调用,但肯定有更好的方法 我怎么能在一条线上叫它?谢谢 编辑:更多上下文信息: 我为symfony 1.4创建了一个条令行为,以便能够使用Zend Lucene从模式中搜索某些表 简而言之,我需要一种方法来说明这种行为“要获得可搜索字段,必须调用methodA()->methodB()->meth

我有以下字符串:

$str = "methodA()->methodB()->methodC"
我想称之为物体上的“链”

$obj->$str
我目前正在使用()->进行拆分并逐个调用,但肯定有更好的方法

我怎么能在一条线上叫它?谢谢

编辑:更多上下文信息:


我为symfony 1.4创建了一个条令行为,以便能够使用Zend Lucene从模式中搜索某些表

简而言之,我需要一种方法来说明这种行为“要获得可搜索字段,必须调用methodA()->methodB()->methodC()”

编辑2: 也许我不够清楚$obj和$str是在运行时确定的,因此您的一些建议不适用

编辑3: 如果你想知道,我目前正在做:

  <?php
  $chain = explode("()->",$str);
  $method = array_shift($chain);
  $value = $obj->$method();
  foreach($chain as $method){
    $value = $value->$method();
  }

我一般不建议使用,但是


不过,我会重新评估您的案例,可能会按照预期一个接一个地直接调用每个函数。

您的方法已经很好了,但是。。。试一试

$str = "{$obj->methodA()->methodB()->methodC()}";

这是一种邪恶的做法

你能提供(我很好奇)一个用例吗


您可以连续使用,为此您可以编写一个帮助器方法,该方法能够解析您的符号并调用链。

下面的方法行吗

$str = $methodA()->$methodB()->$methodC();

我的回答假设您有权访问这些方法(methodA、methodB和methodC),可以编辑它们,并且每个方法都属于$obj是其实例的类

更新每个方法以返回该类的实例,这将在假定它们不返回任何基本数据类型(如int、bool、string或其他)的情况下起作用:

<?php
class Example {
    public function methodA() {
        echo "method a\n";
        return $this;
    }
    public function methodB() {
        echo "method b\n";
        return $this;
    }
    public function methodC() {
        echo "method c\n";
        return $this;
    }
}
?>

在写下我对主要问题的评论后,我想到了一个可能的解决方案,尽管有点冗长和手工(你必须做出尽可能多的案例陈述,因为你合理地期望链式方法的数量)

用途如下:

$result = chain_execute($obj, "methodA->methodB->methodC");

那么字符串中的值是动态创建的吗?您可以实现一个助手函数来逐个创建它。在那之后,你将在一行中完成它。这通常就是编程的工作方式。@Javieh我认为在不知道会有固定数量的方法的情况下,你可以做一些事情,比如
$obj->{$method[0]}()->{$method[1]}()->{$method[2]}()
,假设你不想使用
eval()
,您当前的方法实际上是合适的。我认为PHP在默认情况下有一个方法可以做到这一点,我想我会像您指出的那样创建自己的方法。您的代码使它看起来像是在两次调用链中的第一个方法。看起来第3行应该是$value=$obj;我为symfony 1.4创建了一个条令行为,以便能够使用Zend Lucene从模式中搜索某些表。简言之,我需要一种方法来说明行为“要获得可搜索字段,必须调用methodA()->methodB()->methodC()”$obj是在运行时确定的。那又怎样?将$obj更改为您当前的运行时对象我想我不明白的是“{}”的作用是什么。它有什么作用?感谢这些方法不属于同一个类。相反,在返回“methodA()”时调用方法“methodB()”,如下所示。执行$obj->$chain[0]()和$obj->{$chain[0]}(),两者之间有什么区别?@javieh这只是围绕变量的括号符号,我认为在这种情况下,它更具可读性。我还想说,在某些情况下,我尝试过不使用括号,但遇到了问题,但我使用括号这么长时间了,我不知道是否仍然是这样。注意,我刚刚更改了分解位,因为以前的格式在最后一个数组成员的名称中会有一个额外的“()”。你可以做任何你喜欢的爆炸。或者保留旧的字符串格式并去掉“()”。
<?php
$obj = new Example();
$obj->methodA()->methodB()->methodC();
?>
method a
method b
method c
function chain_execute($obj, $str) {
    $chain = explode("->",$str);
    $chain = array_map('trim', $chain);
    $chain_count = count($chain);
    switch($chain_count) {
        case 1:
            return $obj->{$chain[0]}();
            break;
        case 2:
            return $obj->{$chain[0]}()->{$chain[0]}();
            break;
        case 3:
            return $obj->{$chain[0]}()->{$chain[1]}()->{$chain[2]}();
            break;
        // etc.
        default:
            // not a value you were expecting
            throw new Exception('Invalid number of methods chained: ' . $chain_count);
            break;
    }
}
$result = chain_execute($obj, "methodA->methodB->methodC");