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?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
robertwbradford
  • 6,181
  • 9
  • 36
  • 61

3 Answers3

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);
hakre
  • 193,403
  • 52
  • 435
  • 836
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.

user187291
  • 53,363
  • 19
  • 95
  • 127
  • Thank you, @stereofrog. Definitely not worth it for now, but I may switch to this when I find myself using it among multiple classes. – robertwbradford Aug 08 '11 at 17:16
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.

DonSeba
  • 2,098
  • 2
  • 16
  • 25