Filter By Date Of Birth Easily with a FilterIterator

If you have a list of people and want to find only the people with a date of birth in a set year or greater, there’s nothing easier than a FilterIterator. Find out how today.


After a previous post on FilterIterators, a great discussion ensued on the point of FilterIterators. The last comment from Elvis really got me thinking. He said:

maltblue without changing the data in the example, what about a FilterIterator that accepts a parameter (like the DateOfBirth interval) ? In that case you can show code reusage by printing people born in the 70s, in the 80s and 90s by constructing the same iterator with different parameters (could be the timestamp range)

On reading that, I thought that it was an excellent idea for writing a more instructive and real-world case example of using FilterIterators. So, for your reading pleasure, here it is.

The Setup

We’ll start with the data source array from the previous post.

$dataList = array(
    array(
        'name' => 'John Citizen',
        'email' => 'johnc@citizen.org',
        'dob' => '1960-01-21',
        'location' => 'Brisbane, Qld, Australia',
        'active' => true
    ),
    array(
        'name' => 'Jane Citizen',
        'email' => 'janec@citizen.org',
        'dob' => '1970-10-21',
        'location' => 'Townsville, Qld, Australia',
        'active' => false
    ),
    array(
        'name' => 'Peter Walker',
        'email' => 'peterw@citizen.org',
        'dob' => '1975-04-21',
        'location' => 'Sydney, Nsw, Australia',
        'active' => false
    ),
    array(
        'name' => 'Wendy Hardworker',
        'email' => 'wendyh@citizen.org',
        'dob' => '1990-11-21',
        'location' => 'Melbourne, Vic, Australia',
        'active' => true
    ),
);

What I’ve done here is change the dob element in each array from a UNIX timestamp to a standard year string. However, this example should work equally as well with a timestamp. I’ve kept the rest of the data array the same otherwise.

$dataIterator = new MaltBlue_Iterator_Filter_DateOfBirth(
    new ArrayIterator($dataList)
);
$dataIterator->setYearOfBirth("1976");

foreach ($dataIterator as $userDetail) {
    printf(
        "Name: %s | Email: %s | Date Of Birth: %s | Location: %s<br />",
        $userDetail["name"],
        $userDetail["email"],
        $userDetail["dob"],
        $userDetail["location"]
    );
}

I’ve then changed the iterator used to MaltBlue_Iterator_Filter_DateOfBirth which I’ll cover shortly. I then call a function on the iterator: setYearOfBirth. This function sets the year that we will be searching from. It internally creates a date from the first of January of that year.

It’s rather simple and does no checking that it’s a valid year. If you’re interested, you could update the code to do this. [hint]. Then the rest of the code is as before, iterating over the results available.

The Date Of Birth Filter Iterator

<?php

class MaltBlue_Iterator_Filter_DateOfBirth extends FilterIterator
{
    protected $_yearOfBirth;
    protected $_comparisonDate;

    public function setYearOfBirth($yearOfBirth = null)
    {
        if (!empty($yearOfBirth)) {
            $this->_yearOfBirth = $yearOfBirth;
            try {
                $this->_comparisonDate = new DateTime($yearOfBirth . "-01-01");
            } catch(Exception $e) {
                // log error
            }
        }
    }

    public function accept()
    {
        $value = $this->current();
        if (array_key_exists('dob', $value) && !empty($value['dob'])) {
            try {
                $dob = new DateTime($value['dob']);
                if ($this->_comparisonDate
                    && $this->_comparisonDate instanceof DateTime)
                {
                    $dateInterval = $this->_comparisonDate->diff($dob);
                    return ($dateInterval->format('%R%a') >= 0) ? true : false;
                }
            } catch (Exception $e) {
                // log error
            }
        }
        return false;
    }
}

Now here’s where it’s really different. Firstly, the revised class has two protected variables: $*yearOfBirth and $*comparisonDate. These store the year that the record has to be older than and a DateTime object with which to compare the user against.

We then have a setYearOfBirth function, which allows us to specify the year of birth. If it’s a valid value, then we create a DateTime object, which is the first of January of that year. I’ve wrapped it in a try/catch block for a bit of error checking.

Then we have the accept function, required in all implementations of the FilterIterator. Similar to before, if the dob field exists in the current record, then we attempt to create another DateTime object from the value of the field.

We then use the diff method of the DateTime class to return a DateInterval object. We can then call the format method on that object. The reason that this is done and in this way, is to see if the date of birth of the user, is equal with or greater than the date of the $_comparisonDate object, by at least one day.

If so, then the person has a valid date of birth and we return true so they will be shown.

Fork the Code on Github

If you want to play with the code, then fork or clone a copy of it - it’s available on our github account now.

Parting Thoughts

Now, is this the most efficient code? I don’t know to be honest as I’ve not done any performance tests on it. So, don’t assume that this will be the best performing code.

However, as it’s not aimed at that, I’m not too concerned. This goes also for the tests on the year value entered by the user and the date of birth value stored in the user record. The aim here is to provide a more real world use of the FilterIterator, which I believe this post has provided.

So, do you see that the FilterIterator really helps make code more flexible and elegant, by allowing us to apply custom logic over the existing lexicographical constructs of PHP? What possibilities do you see for using it in your code? Let me know in the comments.


You might also be interested in these tutorials too...

Mon, Jan 9, 2012

Beginning cloud development with cloudControl – Part 4 – Memcache

Here we are at part four of the Beginning Cloud Development with cloudControl series and in this part, we’re adding Memcached support. In part one of the series, we laid the foundation for the application and got up to speed with what cloudControl is, why it works and how to get started using it.

Then in part two, we started to flesh out the application that we started building in part one and added MySQL support to it. We showed how to work with cloudControl to manage the key requirements, such as enabling MySQL support, connecting to the MySQL database and keeping the database up to date from a maintenance perspective (creating the database schema and loading data in to the database).

Then in the third part of the series, we replaced MySQL with mongoDB support. Now, in this, the third part of the series, we’re going to finish up with adding Memcached support. As the core of the work’s already been done in the application, this tutorial will be shorter and simpler than the previous three. So, get out the code that you worked through from part 2, or download a copy of it from the github repository and let’s get started.

Fri, Dec 16, 2011

Beginning cloud development with cloudControl - Part 2 - MySQL

In part one of the series we got a birds eye view of a great cloud development solution for PHP - cloudControl. We looked at the concept of what it is, what you can do with it and ran through a basic deployment with a rather basic application. If you missed the first part, I strongly encourage you to read it before continuing on with part two. When you’re done, come on back and work through it here.

In this, part two of the series, things start to get more serious. In this part, we’re going to start to flesh out the application started in part one, adding in MySQL support - showing just how simple cloudControl makes this for us.

Tue, May 22, 2012

Zend Form Mastery with Zend Config – Part 3 Standard Form &amp; Element Options

– Part 3 Standard Form & Element Options This is a Multi Part Series. Check out the other parts: Part 1 - Custom Filter Paths Part 2 - Core Form Configuration Part 4 - Configuring Zend Validators Options We’ve looked at custom form filters and we’ve looked at the core form configuration. But what about the other form properties? What about: setting an element as readonly an element as required ignoring an element and love them or hate them, what about decorators Element Options Outside of the options that we’ve looked at previously, there are a number of other options that we can consider implementing when configuring a Zend Form.


Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus