October 15th, 2007

In PHP, to successively filter data in one array based on some data in each row of another, array_filter() can be combined with create_function().

The function array_filter() takes the array to be filtered as its first argument, and a callback function as its second. The callback function is a function with one parameter, which is also the array to be filtered; it is applied to each element, and if it returns false for a particular element, that element is filtered out of the result set.

The function create_function() creates an anonymous function and returns a unique function name as a string. As its first parameter, create_function() takes a string which is a comma-separated list of arguments (in our case, a single parameter $a). The second parameter is the body of the function, as a string.

In the example below, we have an array $people (a list of people) and an array $hobbies (a list of hobbies). There is a one to many relationship from $people to $hobbies on ($people['id'], $hobbies['person_id']). We want to filter the $hobbies array for each person, and display those results along with the data for each person.


$people = array();
$hobbies = array();

array_push($people, array('id' => 1, 'name' => 'Ryan', 'gender' => 'male'));
array_push($people, array('id' => 2, 'name' => 'Helen', 'gender' => 'female'));
array_push($people, array('id' => 3, 'name' => 'Riley', 'gender' => 'male'));

array_push($hobbies, array('person_id' => '1', 'hobby' => 'guitar'));
array_push($hobbies, array('person_id' => '1', 'hobby' => 'programming'));
array_push($hobbies, array('person_id' => '1', 'hobby' => 'bad jokes'));
array_push($hobbies, array('person_id' => '2', 'hobby' => 'painting'));
array_push($hobbies, array('person_id' => '2', 'hobby' => 'singing'));
array_push($hobbies, array('person_id' => '2', 'hobby' => 'complaining'));
array_push($hobbies, array('person_id' => '3', 'hobby' => 'babbling'));
array_push($hobbies, array('person_id' => '3', 'hobby' => 'drooling'));
array_push($hobbies, array('person_id' => '3', 'hobby' => 'laughing'));
array_push($hobbies, array('person_id' => '3', 'hobby' => 'crying'));

foreach ($people as $person) {

	// Build the function body, which evaluates if $a['person_id'] == $person['id'],
	// where $person['id'] is a value replaced for each iteration of people
	$fxBody = 'return $a[\'person_id\'] == '. $person['id'] . ';';

	// Create the anonymous function
	$filter = create_function('$a', $fxBody);

	// Apply the filter
	$filteredHobbies = array_filter($hobbies, $filter);

	// Show our results
	echo "<h2>{$person['name']}, a {$person['gender']}, enjoys:</h2>";
	foreach ($filteredHobbies as $hobby) {
		echo "{$hobby['hobby']}<br />";
	}
}

And of course, a working example.

Leave a Reply