tags:

views:

47

answers:

2

I want to pass an array to a function and iterate through it in this function. But I would like to be able to change the way the single entries are displayed.

Suppose I have an array of complicated objects:

$items = array($one, $two, $three);

Right now I do:

$entries = array();
foreach($items as $item) {
    $entries[] = create_li($item["title"], pretty_print($item["date"]));
}
$list = wrap_in_ul($entries);

I would like to do the above in one line:

$list = create_ul($items, $item["title"], pretty_print($item["date"]));

Any chance of doing that as of PHP4? Be creative!

+2  A: 

You could use callbacks:

function item_title($item) {
    return $item['title'];
}
function item_date($item) {
    return $item['date'];
}
function prettyprint_item_date($item) {
    return pretty_print($item['date']);
}

function create_ul($items, $contentf='item_date', $titlef='item_title') {
    $entries = array();
    foreach($items as $item) {
        $title = call_user_func($titlef, $item);
        $content = call_user_func($contentf, $item);
        $entries[] = create_li($title, $content);
    }
    return wrap_in_ul($entries);
}
...
$list = create_ul($items, 'prettyprint_item_date');

PHP 5.3 would be a big win here, with its support for anonymous functions.

outis
This solution is not flexible enough, it requires big changes when I want to add a field.
blinry
Add a field where? If your requirements are broader, edit your question to reflect this.
outis
+2  A: 

from my understanding, you're looking for an "inject" type iterator with a functional parameter. In php, inject iterator is array_reduce, unfortunately it's broken, so you have to write your own, for example

function array_inject($ary, $func, $acc) {
 foreach($ary as $item)
  $acc = $func($acc, $item);
 return $acc;
}

define a callback function that processes each item and returns accumulator value:

function boldify($list, $item) {
 return $list .= "<strong>$item</strong>";
}

the rest is easy:

$items = array('foo', 'bar', 'baz');
$res = array_inject($items, 'boldify', '');
print_r($res);
stereofrog
Thank you for your answer! This solves my problem, but creates so much overhead I would rather stick to my foreach loop. I would have to create different callback functions for every place I want to have a list. Other than that, the inject-function would have to be in a different file/class/namespace to keep it reusable. How would I access my callback functions from there?
blinry
theoretically, you could use create_function or some other eval-based approach (e.g. http://stereofrog.com/blok/on/061208), but i won't recommend that. You're right - foreach is the "php way" of doing things.
stereofrog