Language designers, API designers, PHP and utter fails

After many years of successfully dodging doing any serious programming in PHP, I had to get my feet wet with PHP for my RL job: I was requested to develop a simple but non-trivial module for our Institute's Drupal-based webpage.

It basically meant two and a half weeks devoted to head-scratching: I had read the very good John van Dyk's Pro Drupal Development book, and knew it would be an important resource were I to face writing a module or work on a theme beyond the most basic stuff… So I checked it out of the library, and started basically writing something similar to my good and trusty Perl code. After all, PHP seems quite similar to Perl, although forcing you to write more for no gain (i.e. requiring an array() declaration whenever you want to store more than one value together) or lacking important and useful constructs (not having a sane way to prepare a SQL statement for multiple executions with different parameters — Yes, there are DB access methods that do provide it, but Drupal 6 does not use them).

Anyway, book in hand, I started understanding while implementing (which is way different than just reading the book, right?) Drupal's notions. I cannot say I like them, but it's… ahem… doable.

Now, I hit a problem twice. I chose to ignore it the first time, as it was a corner case I'd look into later on, but had to devote for hours of my attention later on. When designing the menu (which for Drupal means not only the facility which prepares/displays links to the bits of functionality, but also the access control layer and the action dispatcher — a huge yay! for responsability separation!), I had only two access levels: Public and administrator. So, this seemed like a good fit:

  1. $public = array('first/action', 'second/action',
  2. 'third/action', 'something/else');
  3.  
  4. foreach (array_keys($items) as $item) {
  5. if (array_search($item, $public)) {
  6. $items[$item]['access callback'] = TRUE
  7. } else {
  8. $items[$item]['access arguments'] = array('diradmin');
  9. }
  10. }

But... No matter what I did, the first element in $public refused to be publicly visible.

It was not until after a severe amount of head-scratching I came across this jewel in the PHP online manual:

Warning

This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "". Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.

GRAH. Using a sane language for some time had made me forget about the problems of true/false sharing space with other meaningful values. So, yes, checking for inclusion of a value in an array in PHP this way should be compared with class-bound identity (that's what === means) to FALSE, or better yet, using a function that exclusively returns a boolean (as in_array()).

Anyway… While arrays (which in PHP are any kind of list, be it keyed as a hash or consecutive as a traditional array) are such an usual construct in any language, please do take a look at PHP's array-handling API. Too long. Too complex. Too many corner cases.

I cannot but wonder what keeps PHP as a popular language. It hurts.