8

I'm trying to get something like this working:

function posts_formatter (&$posts){
    foreach ($posts as $k => $v){

        if (is_array($v)){

            posts_formatter($v);

        }else{

            switch (strtolower($k)){

                # make email addresses lowercase
                case (strpos($k, 'email') !== FALSE):
                    $posts[$k] = strtolower($v);
                    break;

                # make postcodes uppercase
                case (strpos($k, 'postcode') !== FALSE):
                    $posts[$k] = strtoupper($v);
                    break;

                # capitalize certain things
                case (strpos($k, 'line1') !== FALSE):
                case (strpos($k, 'line2') !== FALSE):
                case (strpos($k, 'line3') !== FALSE):
                case (strpos($k, 'forename') !== FALSE):
                case (strpos($k, 'surname') !== FALSE):
                    $posts[$k] = capitalize($v);
                    break;
            }

        }
    }
}

It will correctly go through the array and format the values but I can't get it to return them. I've played around with removing the & from the function declaration and adding a return at the end but it won't do anything.

Additionally, I'm thinking perhaps using a RecursiveArrayIterator might be the way to go. However, despite the presence of a book right in front of me with a chapter on SPL Iterators its examples are useless towards being able to achieve what I'm trying to. How would I go about implementing one?

Edit:

array (
  'user' => 
  array (
    'title' => 'Mr.',
    'forename' => 'lowercase',
    'surname' => 'name',
    'businessName' => 'some dude',
    'telephone' => '07545464646',
    'postcode' => 'wa1 6nj',
    'line1' => 'blergh road',
    'line2' => 'randomLY cApitaLIzed wOrds',
    'line3' => '',
  ),
  'email' => '[email protected]',
  'address' => 
  array (
    'postcode' => 'ab1 1ba',
    'line1' => 'test road',
    'line2' => 'testville',
    'line3' => 'testshire',
  ),
  'date' => '2010-09-30'
)
10
  • care to provide a var_export example array? Commented Sep 30, 2010 at 9:50
  • Well, the array can be any multidimensional (or basic) array, which is the whole point. All the function needs to do is look for those specific keys, which may or may not exist within the array and format their values. The question is getting it to output them back to the script. Commented Sep 30, 2010 at 10:03
  • I am asking because in order to write up an example, I'd like to use your actual data instead of coming up with a dummy array. It's just to make it less tedious to code things up for you. Commented Sep 30, 2010 at 10:06
  • Your switch/case construct doesn't work the way you probably intent it to do. What you have is like if ( strtolower($k) == (strpos($k, 'email')!==FALSE) ). Commented Sep 30, 2010 at 10:11
  • Fair enough! I was thinking you needed it to better understand the problem. Commented Sep 30, 2010 at 10:11

1 Answer 1

19

Ok, here is a quick something for you to figure out:

$data = array(
    'title'    => 'how to work with iterators',
    'posts' => array(
        array(
        'title'  => 'introduction to iterators',
        'email'  => '[email protected]'
     ), array(
        'title'  => 'extending iterators',
        'email'  => '[email protected]'
     )
));

The main idea is to influence how the Iterator returns the current element. Iterators are stackable, so you should use a RecursiveArrayIterator and wrap it into a RecursiveIteratorIterator. To achieve custom functionality, you can either subclass the RecursiveIteratorIterator (as shown below) or use additional iterators to decorate the RecursiveIteratorIterator:

class PostFormatter extends RecursiveIteratorIterator
{
    public function current()
    {
        $current = parent::current();
        switch($this->key()) {
            case 'email':
                $current = strtolower($current);
                break;
            case 'title':
                $current = ucwords($current);
                break;
            default:
                break;
        }
        return $current;
    }
}

Then you simply foreach over the iterator

$it = new PostFormatter(new RecursiveArrayIterator($data));
foreach($it as $key => $post) {
    echo "$key: $post", PHP_EOL;
}

and get

title: How To Work With Iterators
title: Introduction To Iterators
email: [email protected]
title: Extending Iterators
email: [email protected]

You can try to get the array back from the with iterator_to_array or iterator_apply functions. However, to get the values reapplied to the original array structure, you dont need an iterator:

array_walk_recursive($data, function(&$val, $key) {
    switch($key) {
        case 'title': $val = ucwords($val); break;
        case 'email': $val = strtolower($val); break;
        default: break;
    }
});
print_r($data);

Note: exchange Lambda with Function name when using PHP<5.3

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your help Gordon. Just one more quick Q- how do I amend it return the processed array with the original array structure intact?
@bcmcfc You're welcome. I had to remove the iterator_to_array code because it wouldnt apply the changes to the inner arrays. I am sure you can do it somehow, but right now I cant fiddle with it (time constraints). Sorry.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.