At Confoo I had an interesting conversation with Guilherme Blanco regarding the fact that in Doctrine 2 they had a performance issue due to usage of array_key_exists() and how it was significantly slower than isset(). His anecdotal example was that doing isset() took 0.5 seconds, while array_key_exists() for the same operation took 5 seconds!
That seemed wrong, given that array_key_exists() simply does a hash table look-up, to determine if the array key exists and the only speed difference would be due to the fact that isset() is a language construct and does not have the overhead of function & parameter processing. So, I've decided to do a quick benchmark using a 5,000 element array.
PHP:
<?php
$arr = array();
$fp = fopen("/usr/share/dict/words", "r");
while ($i < 5000 && ($w = fgets($fp))) {
$arr[trim($w)] = ++$i;
}
$s = microtime(1);
for ($i = 0; $i < 100000; $i++) {
isset($arr['abracadabra']);
}
$e = microtime(1);
echo "Isset: ".($e - $s)."\n";
$s = microtime(1);
for ($i = 0; $i < 100000; $i++) {
array_key_exists('abracadabra', $arr);
}
$e = microtime(1);
echo "array_key_exists: ".($e - $s)."\n";
?>
The above benchmark executed on PHP 5.4 shows that while isset() is 2.5 times faster taking a mere 0.0219 seconds vs 0.0549 seconds taken by array_key_exists(), both operations are extremely quick and take a fraction of a second even when doing 100k operations. Any "optimization" between the calls is purely within the super-micro-micro optimization realm and is not going to make any application measurably faster.
The bottom line is that if your application does not need to distinguish between an array key that does not exist and one whose value happens to be NULL you should use isset() because it happens to be a little faster. However, if a NULL array key value and a non-existant array key are something you need to differentiate between, use array_key_exists() and you don't need to worry about the performance, the function is extremely fast, even in the case of Doctrine 2 that apparently may do as many as 50,000 calls to the function per-request in some cases.