Why global variables are bad

This question came up yesterday when Sandy and I presented at DC Web Women, an Introduction to  PHP [slides]. I couldn’t come up with a coherent set of arguments at the time, in a way that I could explain easily. These posts do a better job, first a general programming article on the subject:

Implicit coupling — A program with many global variables often has tight couplings between some of those variables, and couplings between variables and functions. Grouping coupled items into cohesive units usually leads to better programs.

From: Global Variables Are Bad

And a PHP specific article full of excellent examples

You may have heard that globals are bad. This is often thrown around as programming gospel by people who don’t completely understand what they’re saying. These people aren’t wrong, they just don’t often program what they preach. I’ve lost track of the number of times I’ve had the “globals are bad” conversation with someone (and been in agreement) only to find their code is littered with statics and singletons. These people are confusing globals (as in the $GLOBALS array) and global state.

From: Why global state is the devil, and how to avoid using it – TomNomNom.com

Remove unapproved comments from WordPress exports

Recently, I needed to migrate some WordPress blogs to another system. WordPress provides a handy way to export content in its WXR format. However, it’ll export all comments, whether approved or not. This is good from a data backup standpoint, but I didn’t need to import these. They were also bloating the XML file and affecting how long it took my import to process.  I needed a way to remove unapproved comments, the following code will do that using PHP’s DOMDocument extension to walk an input file. The cleaned up content is sent to STDOUT so you can pipe it to another file to save.

if (!isset($_SERVER['argv'][1])) {
    echo "\nSpecify input file \n";

$infile = $_SERVER['argv'][1];

$doc = new DOMDocument();
$doc->recover = TRUE;

$comments = $doc->getElementsByTagName('comment');
$to_remove = array();

foreach ($comments as $comment) {
    if ($approved = $comment->getElementsByTagName('comment_approved')) {
        if ($approved->length > 0) {
            $app = $approved->item(0);

            // can't remove nodes while looping
            if (0 == $app->nodeValue) {
                $to_remove[] = $comment;

if (count($to_remove)) {
    foreach ($to_remove as $elt) {

$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;
echo $doc->saveXML();

Extract images from an HTML snippet

The function here will take an HTML fragment and return an array of useful images it finds.

 * extractImages
 * @param $text
 * @return array|bool
function extractImages($text)
    $header = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
    $text = $header . $text;
    $dom = new DOMDocument();
    if (@$dom-&gt;loadHTML($text)) {
        $xpath = new DOMXpath($dom);
        if ($images = $xpath-&gt;evaluate("//img")) {
            $result = array();
            foreach ($images as $i =&gt; $img) {
                $ht = $img-&gt;getAttribute('height');
                $wd = $img-&gt;getAttribute('width');
                // if height &amp; width are 1 its a bug, ignore
                if (1 === (int)$ht &amp;&amp; 1 === (int)$wd) {
                // if it doesn't end in an image file extension
                // then ignore
                $src = $img-&gt;getAttribute('src');
                if (!preg_match('/.(png|jpg|gif)$/i', $src)) {
                // do we need to figure out the full url to the image?
                if (!preg_match('/^https?:///', $src)) {
                $alt = $img-&gt;getAttribute('alt');
                $result[$i] = array('src' =&gt; $src, 'alt' =&gt; $alt, 'height' =&gt; $ht, 'width' =&gt; $wd);
            if (!empty($result)) {
                return $result;
    return false;

Fix SSL timeouts with the Facebook PHP-SDK

I ran into SSL timeouts on in local development setup when I was re-factoring some integration code with facebook and using their SDK. It was tricky to diagnose, I was sure that my changes couldn’t be the cause, and I finally confirmed it by running our production codebase. Since it was having the same timeout error, I knew the bug had to be in an underlying layer.

For the record, I’m running this version of curl on my Archlinux box:

<code>curl 7.25.0 (x86_64-unknown-linux-gnu) libcurl/7.25.0<br /> OpenSSL/1.0.1 zlib/1.2.6 libssh2/1.4.0

I also got the error from the command line with

<code>curl "https://graph.facebook.com/oauth/access_token"

But it is fixed with

<code>curl --sslv3 "https://graph.facebook.com/oauth/access_token"

Debian Server

On a debian squeeze server, with the latest (4/3/2011) version of curl:

<code>curl 7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0<br /> OpenSSL/0.9.8o zlib/ libidn/1.15 libssh2/1.2.6

The timeout does not happen with either of the following commands:

<code>curl "https://graph.facebook.com/oauth/access_token"
curl --sslv3 "https://graph.facebook.com/oauth/access_token"


The time out does not happen on OS X which runs curl 7.21.4


So, this timeout only seems to affect users with very new version of curl. Fixing it requires adding a line to the Facebook PHP SDK, which while minor, you have to remember if you ever upgrade it. At the same time, this bug could come back and bite you down the road if your operating system sneaks in a newer version of curl. You can see a fork of the PHP SDK with this fix on github.

Other references:

  1. Facebook bug ticket
  2. Maybe related PHP bug

Drupal: Invoke blocks and views from code

While Panels is great for controlling the layout of drupal pages, there are times when you can’t use the module to theme a page.  For uncached content, it does introduce some performance overhead into the drupal request change.  It can also be tedious to migrate changes from one environment to the other if you don’t export pages and variants to version control.

When you’re working in the stock theme layer, the following functions can come in handy.

Render a Block

   * Convenience function to easily call a block from a module
   * @param string module name
   * @param string delta
   * @return array block
  public function invoke_block($module, $delta) {
    if ('block' == $module) {
      global $theme_key;

      // the block_block view is pretty useless
      $block = db_fetch_object(db_query("SELECT b.*, bl.title, bl.*
                   FROM {boxes} b
                   INNER JOIN {blocks} bl ON (bl.module='block'
                       AND bl.delta=b.bid AND bl.theme='%s')
                   WHERE b.bid = %d", $theme_key, $delta));
     $data['subject'] = $block-&gt;title;
     $data['content'] = check_markup($block-&gt;body, $block-&gt;format, FALSE);

      if ('n/a' !== $data['content']) {
        return ($object) $data;
    } else {
      if (module_exists($module)) {
        $block =  module_invoke($module, 'block', 'view', $delta);
        $block['delta'] = $delta;
        $block['module'] = $module;
        return (object) $block;
      else {
        trigger_error("Module $module is not enabled.", E_USER_ERROR);

To show block with delta 1 defined by module foo:

$block = invoke_block('foo', 1);
$output = theme('block', $block);

Render a View

   * Convenience function to easily get the output of a view
   * A note about the display id, this is NOT the identifier
   * that you can set in the Views UI. To see the display id, look
   * at the theme information for the display.  For blocks it will
   * be something like block_1 or block_X where X is a number.
   * If the display_id doesn't match then Views automatically
   * uses the default display which can make themeing a pain.
   * modeled on view_embed_view().
   * @param string view name
   * @param string display name (see theme info for the display name)
   * @param array additional options
   * @return string
  static public function invoke_view($name, $display_id = 'default') {
    $args = func_get_args();
    array_shift($args); // remove $name

    if (count($args)) {
      array_shift($args); // remove $display_id

    $view = views_get_view($name);
    if (!$view) {
      trigger_error('Unknown view invoked: ' . $name, E_USER_WARNING);

    // validate the $display_id is valid
    // generate an error to prevent wasted time debugging.
    $defined = array_keys($view-&gt;display);

    if (!in_array($display_id, $defined)) {
      trigger_error('In view "' . $name . '" unknown display invoked "'
                  . $display_id . '"', E_USER_WARNING);

      // lets not render, chances are we don't want
      // the default display if we invoke a specific view

    // if a view is empty, dont return anything
    $r = $view-&gt;preview($display_id, $args);
    if (false !== strpos($r, '
‘)) { return $r; } else { return null; } }

To render display page_1 from view foo. You can even pass arguments to the view.

$output = invoke_view('foo', 'display1');
$output2 = invoke_view('foo', 'display1', 2010, 111); // with args!

Feature module example to bundle WYSIWYG Configuration

This is a concise example showing how you can use the Features module to bundle configurations in Drupal into a module.  It's great to see the Drupal community moving towards using code to capture, reuse, and deploy configuration settings.  It's been the biggest pain point in working with Drupal for me.

One of the things Drupal core does not do well at all is provide an easy way to switch on a WYSIWYG editor. There is no editor out of the box and setting it up requires some custom configuration of several Drupal core settings, installing and configuring several contributed modules, and also installing one or more external libraries, like the TinyMCE library.

WYSIWYG as a Feature 

TekX – Introduction to Testing with Selenium

Arne Blankerts – part of thePHP.cc, premium PHP consulting and training.

  • Selenium is a java based portable testing framework.
    • Seleniumm RC runs any browser supported by the framework, firefox, opera, etc
      • Can operate/execute ANY browser available on the host machine
      • On Linux, have to tweak how process is shutdown.
    • Selenium IDE – extension for Firefox to Create and Edit Tests.  Can record clicks instead of writign code.
  • Where to use it?
    • Acceptance/Integration Tests – test behaviors in the browser.
    • Compatibility Tests – test that new functions work across browsers/versions
    • Monitoring – you can record behavior and trigger events.
      • Can test that, for example, your registration form actually works not just makes the page available.
    • Test case recording for Bugreports.
      • Provide more detailed, reproduceable bug reports.
    • Development – automate filling out forms during development.
  • Selenium does not replace unit testing or other forms of testing.
  • Useful RC options
    • -port alternate listening port
    • -log save console output to logfile
    • -debug more trace output
    • -timeout seconds to wait before giving up on a test
    • -html run a single standalone test
  • Selenium Tests
    • Written in browser independent JavaScript based DSL
    • Same test can run on any OS with Java runtime and many browsers
      • Firefox 2+, Internet Explorer 6+, Opera 8+, Webkit from Safari 2+
    • Can write tests using PHP as well.
    • Can test for presence of elements – seems to use XPath to select elements, but you can use other notations.
    • Pretty powerful selectors for finding elements.

Talk derailed a bigt by technical difficulties, but provided a good introduction into selenium.