Archive for December 2009

PHP Iterators

If you’ve spent any significant amount of time coding in PHP you’re most likely familiar with PHP’s foreach loop syntax. In simple terms, a foreach loop is an easy way to iterate over the elements of an array. Chances are if you’re reading this you already know that. What you may not know, however, is that it is possible to iterate objects with a foreach loop. Assuming you have some collection class (an object that stores some number of elements in an organized manner) you can iterate over its elements just like you can the elements of an array.

$myCollection = new Collection(); //arbitrary collection class

foreach($myCollection as $element)
{
	//do something with $element
}

In order to do this however, you must design your class in such a way as to let PHP know that it supports iteration. As is the case with many other languages, you do this by implementing an interface. An interface is basically a class containing only abstract methods (constants are allowed as well). A class implementing a certain interface must provide the definitions for those abstract methods. The interface we need in this case is called Iterator and has 5 methods that must be implemented:

class MyIterator implements Iterator
{
	//Returns the current element
	function current()
	{

	}

	//Returns the current key (position in the iterator)
	function key()
	{

	}

	//Moves to the next element (returns void)
	function next()
	{

	}

	//Resets the iterator
	function rewind()
	{

	}

	/*Returns true of the current position in the
	   iterator exists. False otherwise */
	function valid()
	{

	}
}

From these methods you can derive that the underlying implementation of a PHP foreach loop is something like this:

$i = new MyIterator();

//make sure the iterator is in the starting position
$i->rewind();
while($i->valid())
{
	//get the current element and key
	$value = $i->current();
	$key = $i->key();

	//iterator to the next element
	$i->next();
}

//equivalent foreach loop
foreach($i as $key => $value)
{

}

Now that we know what the methods do it is time to implement them. The class we’ll implement will be a stripped down version of a linked list that supports only an add method (plus the iterator methods):

class LinkedList implements Iterator
{
	private $head;
	private $last;
	private $count;
	private $curr; //iterator counter
	private $currNode; //iterator position

	function __construct()
	{
		$this->head = null;
		$this->last = null;
		$this->count = 0;
		$this->curr = 0;
		$this->currNode = $this->head;
	}

	function add($v)
	{
		$newNode = new Node();
		$newNode->value = $v;

		if($this->head == null)
		{
			$this->head = $newNode;
			$this->last = $this->head;
		}
		else
		{
			$this->last->next = $newNode;
			$this->last = $this->last->next;
		}
		$this->count++;
	}

	function current()
	{
		echo "LinkedList::current \n";
		return $this->currNode->value;
	}

	function key()
	{
		echo "LinkedList::key \n";
		return $this->curr;
	}

	function next()
	{
		echo "LinkedList::next \n";
		$this->currNode = $this->currNode->next;
		$this->curr++;
	}

	function rewind()
	{
		echo "LinkedList::rewind \n";
		$this->currNode = $this->head;
	}

	function valid()
	{
		echo "LinkedList::valid \n";
		if($this->curr >= $this->count)
			return false;

		return true;
	}
}

class Node
{
	public $value;
	public $next;

	function __construct()
	{
		$this->value = null;
		$this->next = null;
	}
}

Notice that I’ve added an echo to each iterator method in the LinkedList class; I’ll explain why later. In case you’re unaware, a linked list is just a series of ‘nodes’. Each node contains a value and a reference to the next node in the list. This pseudo code demonstrates how to traverse a linked list, outputting the values as we go:

Node current := head;

while current != null
	print current->value
	current := current->next
endwhile

Since, however, our linked list class implements Iterator we can traverse it using a foreach loop:

$list = new LinkedList();
$list->add('a');
$list->add('b');
$list->add('c');

foreach($list as $key => $value)
{
	echo $key . ' : ' . $value . "\n";
}

Here is the output for the above code:

LinkedList::rewind
LinkedList::valid
LinkedList::current
LinkedList::key
0 : a
LinkedList::next
LinkedList::valid
LinkedList::current
LinkedList::key
1 : b
LinkedList::next
LinkedList::valid
LinkedList::current
LinkedList::key
2 : c
LinkedList::next
LinkedList::valid

The above shows the position and value of each element in our list, as well as the order each iterator method is called.

P.S.

This is the first part in a three part series. The next part will be published soon.

A Supplement

I’ve just added a section about session management to Creating a Secure Login System the Right Way.

Check it out

Do Not Reply

Anyone who has ever had an email account is probably very familiar with the “Do not reply” email. They can take the form of notifications from your bank, reminders to pay a bill, a newsletter, or just plain spam. Generally the read a little something like:

Please do not reply to this email. This mailbox is not monitored and you will not
receive a response.

Usually this is followed by some instructions to follow if you have a question or concern. I imagine at some point in the history of automated emailers someone decided that they did not want to receive any reply from their users via email, or at least from email directed to the address in question, and everyone blindly proceeded to follow this example. That is what contact forms and support email addresses are for correct? To a certain degree this is true. Having to monitor another email account (or more) for support questions would only exacerbate things in the nightmare that is customer support. So the solution is to toss out any incoming email to these accounts and direct users to ask their questions via support form or an alternate email address.
In my mind this is a cop-out. Consider what you lose by doing this. In most cases if I suddenly have a question after receiving an email from my bank, this question is with regard to the message I just received. If I were able to just hit the reply button the original message would be right there on the bottom of my message. If I am to use some other means to ask my question I might forget to include it or decided that it is of no importance.

In addition to this there is the hassle of the alternative process. I have to go to my bank’s website, find the support form, fill out all the necessary information which in my case means first and last name, date of birth, account number, social, and email address (twice). Believe it or not this is the case even if I’m logged into my account. This is a minor inconvenience, but the process introduces the chance for user error. If I put the wrong account number or some other typo occurs my question might never get answered or I might be asked to do it all over again. If I were able to just hit reply all of this information could be derived (automatically) from my email address.

The problems don’t stop there. Often it is the case that support forms ask you to choose the department or type that your question falls under (i.e. is it a billing question, a technical question, etc.). Sometimes the lines between question categories can easily be blurred and submitting a question to the wrong department could potentially increase the response time. It takes x time for person A to get to your question, if A is not the right person to answer the question then it is redirected to person B. Your wait time is now x + y. If you were able to just reply to the email the type of question would be determined automatically and directed to person B. Your wait time is now just y.

Obviously the ubiquitous “do not reply” emails are no the result of someone failing to realize that it may be convenient for the user. The problem is that it complicates things for the support team. Or it least it appears this way at first glance.

Wouldn’t this mean monitor additional email accounts? There is no reason why any person working in support should have to monitor an email account; there are better ways. A properly implemented support system would make the source of the message, whether it be an email or a form, transparent.

It is important the users be directed to the website so that they can find answers in our FAQ or knowledge base before inundating the support system. The solution here is to replace your “do not reply” messages with links to places where the user can find answers. Additionally this gives you the opportunity to serve specialized questions and answers based on the content of the message. Ultimately, users asking obvious questions or questions that have been answered many times in the past is unavoidable.

What about emails containing sensitive information? A user may inadvertently expose their private information to the support team by hitting reply. The solution here is to be careful about what information you put in an email. I am not suggesting that Do not reply emails should be done away with entirely. If it is absolutely necessary to put sensitive information into an email (password resetting for example) then it is appropriate to use a Do not reply address.

I’d like to conclude this entry by imaging a support system with Do not reply (almost) eliminated. Image the support system for a web hosting company. There are three support departments: Billing, accounts, and technical, each of which has an email address. There is also a Do not reply address used exclusively for password resetting. There is a support form which asks the user to select the appropriate department. Finally, there is a knowledge base containing common and previously answered questions. The knowledge base also has a feature that allows it, given a question or some other block of text, to attempt to find similar questions that have already been answered.

When a member of the technical support team accesses the support system, they see only questions for their department, both from the support form and from the technical department email account. The same is true for the other departments.

If one of the departments sends out a notification, whether it be automatic (bill is due, a change to your account, etc.) or manual (planned downtime, a new feature, or some other announcement), before the message is sent, its content is passed to the knowledge base which determines common questions and answers relating to the content of the message. It selects a few and appends them to the message. The message is then sent. If the user has a question regarding the message they have the option of hitting reply and having their message (original message and all) sent to the correct department.