4

Say I have the following:

class Thing {
   function __construct($id) {
     // some functionality to look up the record and initialize the object.

     return $this;
   }
}

Now given an array of IDs, I want to end up with an array of instantiated Things. Something like the following:

$ids = array(1, 2, 3, 4, 5);
$things = array_map(array('Thing', 'new'), $ids); // Doesn't work

Of course there is no "new" method for the Thing class, and "__construct" was off limits as well. I know this could be accomplished with extra steps looping through $ids, but is there a slick way of calling "new Thing($id)" on each using array_map?

3 Answers 3

9

It can not work, because there is no static method Thing::new. You can either add it or just provide the function as the array_map callback:

$ids = array(1, 2, 3, 4, 5);
$things = array_map(function($id){return new Thing($id);}, $ids);
Sign up to request clarification or add additional context in comments.

Comments

2
$things = array();
foreach($ids as $id)
   $things[] = new Thing($id);

this is the php way of doing things. This is how php language works. If you like functional programming, iterators, comprehensions and other smartxxx tricks, consider other languages.

To answer your question literally, you're going to need two little functions

// replacement for "new"
function init($klass /* , param, param */) {
    $c = new ReflectionClass($klass);
    return $c->newInstanceArgs(
        array_slice(func_get_args(), 1));
}

// generic currying
function curry($fn /* , param, param */) {
    $_ = array_slice(func_get_args(), 1);
    return function() use($fn, $_) {
        return call_user_func_array($fn, 
            array_merge($_, func_get_args()));
    };
}

and then

class Thing
{
    function __construct($x, $y) {
        $this->x = $x;
        $this->y = $y;
    }
}

// curry one param
print_r(array_map(
    curry("init", "Thing"),
    array("x1", "x2", "x3"),
    array("y1", "y2", "y3")
));

// curry two params
print_r(array_map(
    curry("init", "Thing", "x"),
    array("y1", "y2", "y3")
));

was it worth it? I don't think so.

1 Comment

Thank you, @stereofrog. Definitely not worth it for now, but I may switch to this when I find myself using it among multiple classes.
0

To the looks of it you are trying to check if an object/class has been initiated already.

You could try the get_declared_classes() function. if will return an array with all classes instantiated.

with this array you could check if an class of yours is known in the system, if not you can initiate it in the fly.

Comments

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.