【问题标题】:Run method chain from a string value从字符串值运行方法链
【发布时间】:2017-02-22 18:52:33
【问题描述】:

我有一个关于从字符串运行方法获取价值的问题。虽然我能够处理来自字符串的单个方法调用,但我很好奇如何从字符串调用方法链。

例如。 $project 是一个对象。

$method1 = "name";
$project->$method1;  // It shows the valid results 

$method2 = "get()->first()->name";
$project->get()->first()-name; // It shows the valid results
$project->$method2; // get a null result

请帮助找到使 $method2 工作的方法。如果我在这些方法中有参数会发生什么?

这里的原因是我做了一系列自定义方法。它可以逐行运行,但我正在考虑一种将它们变成循环的方法,这样效率更高。将方法放入文件中,然后通过循环获取值。

Array = ["getvalue1()", "getvalue2()",...."getValuen()->anotherMethod()->value"]

谢谢,

【问题讨论】:

标签: php laravel laravel-5


【解决方案1】:

如果你想嵌套试试这样的:

private function callMethodChain($model, $methodChain)
{
    return array_reduce(explode('->', $methodChain), function($model, $method) {
        return $model->$method;
    }, $model);
}

这将通过您所描述的一系列方法调用。如果某些链条(最后一块)是一个属性,我想我曾经操纵以下内容来处理它:

protected function callMethodChain($model, $methodChain)
{
    return array_reduce(explode('->', $methodChain), function($model, $method) {
        try {
            return $model->$method;
        } catch (Exception $e) {
            return $model->$method();
        }
    }, $model);
}

如果您想添加参数,请尝试将 $model->method 替换为:

call_user_func_array(
        array($project, 'your_method'),
        $params
    );

【讨论】:

  • 谢谢@chasenyc。它似乎适用于像“getMethod1()->getMethod2()”这样的字符串。但不是“getMethod1()->getMethod2()->name”。它显示错误名称()是“调用未定义的方法”
  • 我添加了一个后续操作,可以帮助我处理属性和方法。我还会确保 name 是来自getMethod2() 的返回属性
  • 当我尝试这个时很奇怪。它显示“试图获取非对象的属性。”。
  • 尝试从字符串中删除 ()?
  • 你好,chasnyc。当我更改 try and catch 方法时,它会起作用。尝试 { 返回 $model->$method(); } catch (Exception $e) { return $model->$method; }
【解决方案2】:

试试这个方法:

$method1 = 'name';
$project->{$method1}();

【讨论】:

  • 感谢@LBA。有用。但是,使用 $method2 = "get()->first()->name"。用这种方式很难做到。有什么想法吗?
【解决方案3】:

从字符串值运行方法

使用call_user_func()call_user_func_array()

call_user_func_array() 适合传递参数

call_user_func_array(
        array($project, 'your_method'),
        $params
    );

链式函数

function chain_fun($chain,$object)
{
  return array_reduce(explode('->', $chain), function ($obj, $method) { 
   if(preg_match('/[()]/',$method)){
         $method=trim($method,'()');
         return $obj->$method();
   }    
   return $obj->$method;
  }, $object);
 }

这里是测试

akshay@db-3325:/tmp$ cat test.php 
<?php
class Testclass
{
    private $str;
    function __construct()
    {
        $this->str = new StdClass;
    }
    function addA()
    {
        $this->str->a='A';
        return $this;
    }
    function addB()
    {
        $this->str->b='B';
        return $this;
    }
    function get()
    {
        return $this->str;
    }   
}

function chain_fun($chain,$object)
{
  return array_reduce(explode('->', $chain), function ($obj, $method) { 
   if(preg_match('/[()]/',$method)){
    $method=trim($method,'()');
    return $obj->$method();
   }    
   return $obj->$method;
 }, $object);
}


$object = new Testclass();

// Output 1
print_r(chain_fun("addA()->addB()->get()", $object));

// Output 2
echo chain_fun("addA()->addB()->get()->a", $object);


?>

输出

akshay@db-3325:/tmp$ php test.php 
stdClass Object
(
    [a] => A
    [b] => B
)
A

【讨论】:

  • 谢谢@Akshay。我还没试过你的方法。上面的建议对我有用。我稍后会检查你的。
猜你喜欢
  • 2013-03-13
  • 2011-12-28
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多