Skip to content

Instantly share code, notes, and snippets.

@morrisonlevi
Last active December 14, 2015 23:15
Show Gist options
  • Save morrisonlevi/7d716f67789d42115eb8 to your computer and use it in GitHub Desktop.
Save morrisonlevi/7d716f67789d42115eb8 to your computer and use it in GitHub Desktop.
The If-Loop-Else pattern in PHP

PHP is aimed at writing web content. It is an incredibly common task to transform data into an HTML representation. Here is a snippet of code that is quite similar to one I wrote earlier this week:

if (!empty($list)) {
	echo "<ol>\n";
	foreach ($list as $value) {
		$escaped = htmlentities($value, ENT_HTML5);
		echo "\t<li>{$escaped}</li>\n";
	}
	echo "</ol>\n";
} else {
	echo "<p>No items</p>";
}

This type of if-loop-else structure turns up everywhere in HTML transformations (and other places too). It works well if the variable you are using is an array, but what the data we want is an object, perhaps one that implements Traversable?

It turns out that empty($var) is pretty much defined as isset($var) && $var == false. Note that is a double equal, not a triple. Objects are considered truthy values so empty($object) will always be false no matter what the object is or what values it has. So if we replace our $list with an object the else case will never trigger. Bummer.

So is there some other way we can write the structure? What if we use count() which has a hook?

if (count($countable_traversable) > 0) {
	echo "<ol>\n";
	foreach ($countable_traversable as $value) {
		$escaped = htmlentities($value, ENT_HTML5);
		echo "\t<li>{$escaped}</li>\n";
	}
	echo "</ol>\n";
} else {
	echo "<p>No items</p>";
}

This will definitely work on arrays and it turns out that it will also correctly work with objects that implement Traversable and Countable. So all is well, right?

Not quite. That code would work for many cases but there are cases where the object can't know its count but it can know if it is empty or not (such as data that is read in increments such as streams). If you think about it we don't need to know the count anway – we just need to know if there are any values.

So what do we do? Unfortunately there is no simple way to do this using only language-provided tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment