How to check is timezone identifier valid from code?

Why not use @ operator? This code works pretty well, and you don't change default timezone:

function isValidTimezoneId($timezoneId) {
    @$tz=timezone_open($timezoneId);
    return $tz!==FALSE;
}

If you don't want @, you can do:

function isValidTimezoneId($timezoneId) {
    try{
        new DateTimeZone($timezoneId);
    }catch(Exception $e){
        return FALSE;
    }
    return TRUE;
} 

You solution works fine, so if it's speed you're looking for I would look more closely at what you're doing with your arrays. I've timed a few thousand trials to get reasonable average times, and these are the results:

createTZlist  : 20,713 microseconds per run
createTZlist2 : 13,848 microseconds per run

Here's the faster function:

function createTZList2()
{
 $out = array();
 $tza = timezone_abbreviations_list();
 foreach ($tza as $zone)
 {
  foreach ($zone as $item)
  {
   $out[$item['timezone_id']] = 1;
  }
 }
 unset($out['']);
 ksort($out);
 return array_keys($out);
}

The if test is faster if you reduce it to just if ($item['timezone_id']), but rather than running it 489 times to catch a single case, it's quicker to unset the empty key afterwards.

Setting hash keys allows us the skip the array_unique() call which is more expensive. Sorting the keys and then extracting them is a tiny bit faster than extracting them and then sorting the extracted list.

If you drop the sorting (which is not needed unless you're comparing the list), it gets down to 12,339 microseconds.

But really, you don't need to return the keys anyway. Looking at the holistic isValidTimezoneId(), you'd be better off doing this:

function isValidTimezoneId2($tzid)
{
 $valid = array();
 $tza = timezone_abbreviations_list();
 foreach ($tza as $zone)
 {
  foreach ($zone as $item)
  {
   $valid[$item['timezone_id']] = true;
  }
 }
 unset($valid['']);
 return !!$valid[$tzid];
}

That is, assuming you only need to test once per execution, otherwise you'd want to save $valid after the first run. This approach avoids having to do a sort or converting the keys to values, key lookups are faster than in_array() searches and there's no extra function call. Setting the array values to true instead of 1 also removes a single cast when the result is true.

This brings it reliably down to under 12ms on my test machine, almost half the time of your example. A fun experiment in micro-optimizations!