从字符串值运行方法链

I have a question about getting value from running a method from a string. While I am able to handle a single method call from a string I am curious how to call a chain of methods from a string.

For example. $project is an Object.

$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

Please help to find a way to make the $method2 work. And what happen if I have params inside those methods?

The reason here is I have made an array of customized methods. It can be run line by line, but I am thinking of a way to turn them into a loop, so it's more efficient. Put the methods in to a file then get values by looping to them.

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

Thanks,

If you want nested try something like this:

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

This will go through a chain of method calls as your described. If some of the chain (the last piece) is a property I think I once rigged up the following to handle it:

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

If you want to add params try replacing $model->method with:

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

Try this approach:

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

Run method from a string value

Use call_user_func() and call_user_func_array().

call_user_func_array() suits good if you are passing parameters

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

Chain function

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);
 }

Here is test

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);


?>

Output

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