2013-12-07 2 views
0

Я хочу создать функцию сопоставления, которая принимает массив, строку ключа и строку значений. Эти две строки содержат PHP-код, который я хочу оценить по каждому элементу массива.Создание функции php mapper

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

E.g.

$assoc_list = my_mapper_function($list_of_people, 'id', 'full_name()'); 

Предполагая, что список содержит два человека, Алиса и Боб, который имеет идентификатор 4 и 5 - возвращаемое значение должно быть что-то вроде:

[ 
    '4' => 'Alice Foo', 
    '5' => 'Bob Bar' 
] 

Любые идеи о том, как обходите это ?

Для свойств достаточно просто, потому что вы можете использовать нотацию в виде скобок, но я хочу, чтобы она работала с (цепочками) вызовами функций.

Вот код, который я ассоциировалась, который работает, к сожалению, только для свойств:

public static function assoc_mapper($array, $key, $value) { 
    $results = array(); 
    foreach ($array as $element) { 
    $results[$element[$key]] = $element[$value]; 
    } 
    return $results; 
} 
+0

Как массив ввода выглядеть? – hek2mgl

+0

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

+2

http://www.php.net/manual/en/function.array-walk.php? –

ответ

0

Единственный способ, которым я был в состоянии сделать это до сих пор использует eval, которые официальные документы предостеречь против. Однако, поскольку я не использую пользовательский ввод, это не риск для безопасности.

public static function assoc_mapper($array, $key_expression, $value_expression) { 
    $results = array(); 
    foreach ($array as $element) { 
    $key = eval("return \$element->$key_expression;"); 
    $value = eval("return \$element->$value_expression;"); 
    $results[$key] = $value; 
    } 
    return $results; 
} 

Если у кого-то есть более ничтожная идея, которая по-прежнему удерживает вызов метода коротким, я буду рад принять ответ.

0

Невеста и просто быстро взломали, но я надеюсь, что вы получите эту идею. Вместо использования буквальной цифры foo()->bar() перейдите к упрощенной нотации foo.bar, которую вы можете обрабатывать по-разному.

function getPropertyFromString($obj, $string) { 
    if (is_array($obj) && array_key_exists($string, $obj)) { 
     return $obj[$string]; 
    } else if (is_object($obj)) { 
     if (isset($obj->$string)) { 
      return $obj->$string; 
     } else if (method_exists($obj, $string)) { 
      return call_user_func(array($obj, $string)); 
     } else if (method_exists($obj, 'get' . ucfirst($string))) { 
      return call_user_func(array($obj, 'get' . ucfirst($string))); 
     } 
    } 
    return null; 
} 

function getValue($obj, $getter) { 
    if (is_string($getter)) { 
     return array_reduce(explode('.', $getter), 'getPropertyFromString', $obj); 
    } else if (is_callable($getter)) { 
     return call_user_func($getter, $obj); 
    } 
    throw new InvalidArgumentException('Invalid getter'); 
} 

function mapper(array $array, $keyGetter, $valueGetter) { 
    $result = array(); 
    foreach ($array as $value) { 
     $result[getValue($value, $keyGetter)] = getValue($value, $valueGetter); 
    } 
    return $result; 
} 

Примеры:

mapper($array, 'id', 'name');  // simple properties 
mapper($array, 'foo.bar', 'baz'); // nested properties 
// super complex values 
mapper($array, 'id', function ($obj) { return strtoupper($obj->foo(42)->bar()->baz); }); 
Смежные вопросы