Подтвердить что ты не робот

Вызывать методы объектов в массиве с помощью array_map?

Предположим, что у меня есть простой класс:

class MyClass {
  private $_prop;
  public function getProp() {return $this->_prop;}
  [....]
}

Теперь то, что я хочу сделать где-то не в области MyClass, - это получить массив $_prop из массива объектов MyClass ($objs). Это, конечно, можно сделать с помощью кода:

$props = array();
foreach ($objs as $obj) {
    $props[] = $obj->getProp();
}

Однако это требует цитаты некоторых строк, esp, когда они формируются таким образом (и я должен использовать такое форматирование). Итак, вопрос: если это можно сделать с помощью array_map? Одним из способов было бы использовать функцию create, но мне это не очень нравится в php (lambdas в php, по крайней мере, неудобно, и если я правильно понимаю, его производительность похожа на производительность кода, но производительность здесь не указана). Я устал искать совсем немного и не нашел определенного ответа. Но у меня есть ощущение, что это невозможно. Я пробовал такие вещи, как array_map(array('MyClass', 'getProp'), $objs), но это не работает, поскольку метод не является статическим.

Изменить: я использую php 5.3.

4b9b3361

Ответ 1

В PHP 5.3 вы можете:

$props = array_map(function($obj){ return $obj->getProp(); }, $objs);

(см. анонимные функции)

Конечно, это все равно будет медленнее, чем использование цикла for, поскольку у вас есть один вызов функции для каждого элемента, но я думаю, что это ближе всего к тому, что вы хотите.

В качестве альтернативы, который также работает до PHP 5.3 и может соответствовать вашим правилам стиля:

function map($obj) {
    return $obj->getProp();
}

$props = array_map('map', $objs);

Или (снова вернемся к PHP 5.3), вы можете создать такую ​​оберточную функцию (но это будет самая медленная возможность, я думаю):

function callMethod($method) {
    return function($obj) use ($method) {
        return $obj->{$method}();
    };
}

$props = array_map(callMethod('getProp'), $objs);

Ответ 2

Попробуйте этот код и посмотрите, почему вы действительно хотите использовать foreach вместо структуры array_map (это очень упрощенный тест, но он показывает точку):

error_reporting(E_ALL ^ E_STRICT);
ini_set('display_errors', 'on');

class MyClass
{
    private $_prop;

    public function getProp() {
        return $this->_prop;
    }
}

$objects = array();
for ($i = 0; $i <= 1000; $i += 1) {
    $array[] = new MyClass;
}

// using foreach
$start = microtime(true);
for ($i = 0; $i <= 1000000; $i += 1) {
    $props = array();
    foreach ($objects as $object) {
        $props[] = $object->getProp();
    }
}

printf('%.5fs', microtime(true) - $start);


// using inline anonymous function
$start = microtime(true);
for ($i = 0; $i <= 1000000; $i += 1) {
    $props = array_map(function ($object) {
        return $object->getProp();
    }, $objects);
}

printf('<br />%.5fs', microtime(true) - $start);


// using stored anonymous function
$start = microtime(true);

$propGetter = function ($object) {
    return $object->getProp();
};

for ($i = 0; $i <= 1000000; $i += 1) {
    $props = array_map($propGetter, $objects);
}

printf('<br />%.5fs', microtime(true) - $start);