0

how call this in PHP:

$a = new Person();
$b = "method1()->method2()->method3()->methodn()";

$s->$b // doesn't work; 

I don't want to explode by "->" and then call each method separately.

3
  • 6
    You would have to resort to eval(), but every time I see this coming up, it's sign of bad design. What are you trying to do? Commented Sep 29, 2010 at 13:27
  • 1
    Extremely bad design, +1 Commented Sep 29, 2010 at 13:29
  • 2
    Is the format fixed or do you simply want to store a chain of actions somehow in a variable? Might be a good idea to explain what you're trying to achieve. Commented Sep 29, 2010 at 14:02

3 Answers 3

2

As long as they don't have any arguments, you COULD do this (Not that robust since it could be broken pretty easily by a malformed string. But you could add a lot more error checking and support for arguments if you really tried)...:

$methods = explode('->', $b);

$ref = &$a;
foreach ($methods as $method) {
    $method = preg_replace('#\\(.*?\\)#', '', $method);
    $ref = &$ref->$method();
}

But I agree with NullUserException that it's typically a sign of bad design... (I think chaining in general is a sign of bad design, but that's just my personal opinion)...

But either way, it's a lot safer than eval, so if you must, you may want to try something like this...

Edit: Based on your updated answer (wanting to map a function to an array of objects):

Using php 5.3:

$newArray = array_map(
    function($value) { 
        return $value->parent()->name;
    },
    $array
);

Or with PHP <= 5.2:

$func = create_function('$value', 'return $value->parent()->name;');
$newArray = array_map($func, $array);

So, your final map method becomes:

public function map($string) {
    $func = create_function('$value', 'return $value' . $string . ';');
    $return = array();
    foreach ($this as $key => $value) {
        $return[$key] = $func($value);
    }
}

Since it's not an array, array_map won't work directly... But you can iterate over the object itself.

But beware, this is no safer than eval, so you really should look at a different solution (such as mapping a callback):

public function map($callback) {
    $return = array();
    foreach ($this as $key => $value) {
        $return[$key] = $callback($value);
    }
}

Usage:

$array = $collection->map(function($value) { return $value->parent()->name; });
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for avoiding eval. Actually, very close to what I was going to suggest, only I have an addiction to recursive functions.
0

You might have to check into "eval":

eval('$a' . $b);

But beware: Unless you control $b yourself, you might be opening yourself up for bad things to happen. This can be a major security hole if $b comes from any source the user can change or leak changes to!

Comments

0

I'm trying to do sth like ruby map for my own collection object (build on arrayobject). If I have array of objects I wont to do sth like this:

$people->map('name') //which should return array of names

or

$people->map('parent()->name') //which should return array of names of parents

1 Comment

@ircmaxell: your last tip (with callback) is closest to my thoughts. Unfortunately i cant vote up (low reputation)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.