lexomatic lexomatic - 4 months ago 6
PHP Question

Apply PHP function to specific keys in an array

I am working on a script that processes data that is submitted from a third party web service that I don't control. I need to clean up some of the user-submitted data. Specifically, I need to go through each array and reformat all of the first names and last names to be sure they are properly capitalized (Ernest Hemingway instead of ERnest HEMINGWAY).

I have been using ucwords(strtolower()) to fix the capitalization, but I need to apply that method to all of the values stored in the first_name and last_name keys in each array. There are other strings that I don't want to change, only the first_name and last_name values. Here's an example of the array:

Array
(
[authors] => Array
(
[0] => Array
(
[first_name] => Ernest
[last_name] => HEMINGWAY
[book] => Too many to mention, but I like the Sun Also Rises
[1] => Array
(
[first_name] => john
[last_name] => steinbeck
[book] => East of Eden
)

[actors] => Array
(
[0] => Array
(
[first_name] => jOhn
[last_name] => WAYNE
[occupation] => Just generally a bad dude.
[1] => Array
(
[first_name] => clint
[last_name] => eastwood
[occupation] => Go ahead. Make my day.
)
)


Any thoughts on how I can loop through each array and apply ucwords(strtolower()) to only the first_name and last_name values? There are a lot of arrays that need this, so I am hoping to be able to programatically find and format the first_name and last_name values. The array format needs to be the same post-processing, with only the values changed.

EDIT: I am sure that, as suggested below, array_walk_recursive is the way to go. I wasn't able to get it to work, but I did create a new method that does the job. Here it is for reference:

protected function _fixCase(array $data)
{
$newData = $data;
foreach ($newData as $key => $value) {
switch (true) {
case stristr($key, 'first_name') || stristr($key, 'last_name');
$newData[$key] = ucwords(strtolower($value));
break;
default:
'';
}
}
return $newData;
}

Answer

Recursively walk the array with a callback:

array_walk_recursive($array, function(&$item, $key) {
        if ($key === 'first_name' || $key === 'last_name') {
            $item = ucwords(strtolower($item));
        }
    }
);

This will alter the items in place (&$item) if the $key matches what you want to change.

Comments