PHP Notice: Undefined variable: _SERVER in ..

I upgraded Linux on this server a while back and in the course of that upgrade PHP was upgraded too, to version 5.5.9.

Since I had a modified php.ini it asked me to check over any new options. There were a few but I fixed anything that looked like it might break things. I saved the php.ini and let the upgrade go on.

Clearing up bugs

Some time later I saw odd notices in the PHP error log. Usually it referred to wp-comments-post.php but files outside of WordPress raised the warning too:

PHP Notice: Undefined variable: _SERVER in ..

It turns out the fix is rather easy. Jacques Marneweck on his blog posted a solution. Simply switch off “auto_globals_jit” in your php.ini and restart Apache (if required).

From the PHP manual entry for auto_globals_jit:

When enabled, the SERVER and ENV variables are created when they’re first used (Just In Time) instead of when the script starts. If these variables are not used within a script, having this directive on will result in a performance gain.

The PHP directives register_globals, register_long_arrays, and register_argc_argv must be disabled for this directive to have any affect. Since PHP 5.1.3 it is not necessary to have register_argc_argv disabled.

A bug

It looks like the bug is ancient although I’m not using APC, and the JIT compiler can be fooled if you access the super globals like _SERVER through variable variables. Sneaky!

The default for auto_globals_jit is “On” so next time you upgrade PHP keep an eye on the error log.

cSprites for PHP 5.3.1/2

Joost posted a great article on reducing http requests on WordPress sites recently and one comment caught my attention. Nabil mentioned cSprites. It’s a WordPress plugin that merges the images in your posts into one file and uses CSS to position the single merged file in place of the original images. Here’s a good post explaining how this technique works.

Unfortunately it hasn’t been updated in over a year, and the current version doesn’t work if you have PHP 5.3.2 (and probably 5.3.1) as it trips over this PHP bug. The fix is simple, get rid of call_user_func_array() and call the functions directly.

I had it installed here and it worked well enough but not perfectly. Here’s the post I made on the plugin’s support forum if anyone’s interested.

I don’t think the author will update the plugin again and in fact he’s looking for someone else to take over. Anyone?

The plugin has been running on my photoblog for the last hour ago and I haven’t noticed any problems yet. As a bonus, it also stops people right clicking and stealing saving my photos for their own use. I’ve since removed it as visitors were only seeing blank images. Oh well.

So, want to give a “fixed version” a go? Grab csprites-for-wordpress.zip and install it in the usual way. Support queries should be directed towards the plugin support forum. 😉

Oh yeah, there’s also the SpriteMe bookmarklet if you don’t want to go fiddling with WordPress plugins!

PHP is_numeric() vs is_int()

Some lessons you don’t forget, but this one I did because it doesn’t come up very often.

Don’t use is_int() because, as Jeremy says, it’ll lie to you. Use is_numeric() instead.

Copy the following chunk of code into a php file and run it. You’ll be surprised at the outcome:

$t = "12345";
if( is_int($t ) ) {
    echo $t . " is an int!";
} else {
    echo $t . " is not an int!";
}

The problem is that is_int() thinks a string of numbers is a string, not an integer. The is_int() man page has an example illustrating that but it’s easy to miss. That function should carry a public health warning!

There’s also the ctype_digit() function too but it has it’s own gotcha:

Note: This function require a string to be useful, so for example passing in an integer will always return FALSE. However, also note that HTML Forms will result in numeric strings and not integers. See also the types section of the manual.

No activity within 1800 seconds; please log in again

1800 seconds is such a long time, right?

  1. It’s 30 minutes.
  2. It’s 0.5 hours.
  3. It’s 0.0208333333 days.
  4. It’s also 5.70397764 × 10-5 years.

And it’s not long enough for me. phpMyAdmin logs you out after 1800 seconds, obviously for security reasons. That’s fine if there are other people about, if I was in an office with people coming and going, but I work from home. All I see for most of the day is my family, the radio, my messy desk, computers, and the view out the window. Time to figure out how to make that 1800 second limit a little longer or remove it altogether.

After a little digging, I discovered that extending the time limit to a day is actually quite easy. Open your phpMyAdmin’s config.inc.php and search for or add the following line:

$cfg['LoginCookieValidity'] = 86400;

Refresh your logged out phpMyAdmin and presuming you haven’t left it idle for 24 hours, you’ll be logged in again!

If the time limit really bugs you, you need http authentication. Look for the “auth_type” line in the config.inc.php and change that to “http”. phpMyAdmin won’t log you out as long as your browser is open. Perfect!

If you’re concerned about sending your MySQL username and password in the clear each time you make a request to phpMyAdmin you can either use SSL or try the “config” auth_type. Make sure you fill in the username and password fields in the config file, and secure the phpMyAdmin directory with a htpasswd file.

Ping. The ping heard across the world

If you’re wondering why trackbacks and pings aren’t working on your blog then you might want to do what I did earlier today: allow your blog to talk to other servers.

WordPress needs either allow_url_fopen to be set On or to have the Curl extension loaded. If you’re having problems receiving pings from other blogs then both of these are probably turned off or missing. Wouldn’t it be nice if Options->Discussion warned that pings wouldn’t work?

Look in your php.ini, or the output of phpinfo() to check for both. If you want to enable fopen, then the entry in php.ini should look like this:

;;;;;;;;;;;;;;;;;;
; Fopen wrappers ;
;;;;;;;;;;;;;;;;;;

; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
allow_url_fopen = On

I switched to Litespeed web server a while back and by default allow_url_fopen is set to Off and the curl library isn’t included. Check /opt/lsws/php/php.ini and make sure remote fopens are allowed!

Thanks Barry for helping me fix that.

PS. if you linked to this blog recently, feel free to save your post again. WordPress will ping my site again and this time the ping will get through.

Donncha's Thursday Links

I have to admit, I preferred how WP 2.2 displayed lots of draft posts on the edit and post pages. Having to go to the Write page and click on the “54 more” link is annoying. For some reason, this post didn’t show up as the newest draft. Now it does, maybe because I deleted another (newer) draft post of the same name. When I created another “Donncha’s Thursday Links” post it didn’t show in the drafts list either. I had to search the drafts posts for “donncha” and it appeared at the bottom of that list. Strange.

I should get used to having my photos ripped off, but I don’t think I ever will. It’s as upsetting now as it ever was.

PS. Ray D’Arcy appears on the Restaurant tonight on RTE 1 at 8.30pm!

Is your eAccelerator cache dir still there?

While looking through this WordPress performance post I realised that eAccelerator might not be running properly on this blog. For some time I’ve noticed this site hasn’t been as quick off the mark as it used to be. Dare I say it, but it was even a little sluggish!

If you’re not familiar with it, eAccelerator is a PHP accelerator. It caches PHP bytecode and performs optimizations to make your PHP site run a lot faster.

I verified that eAccelerator was loaded and then checked my php.ini configuration. Sure enough, the eaccelerator.cache_dir directive was set to “/tmp/eacc/” and that directory was deleted the last time my server rebooted.

A permanent fix is to change the location of the cache dir. Put it anywhere the webserver can read, but don’t put it in /tmp/.

While you’re looking at eAccelerator, upgrade to the latest version, especially if you’re running PHP5.

Notes when upgrading to PHP5

I upgraded one of my servers to PHP5 this morning. Two things to watch out for:

  • The location of your php.ini may have changed. It’s probably now in /etc/php5/apache2/. You need to copy over any changes from your old one.
  • Update your libraries too such as the mysql client and the gd library. Don’t forget you can delete the old ones. apt-get install php5-mysql php5-gd will do the job of installing, the old packages have a php4 prefix.
  • WP-Cache doesn’t like PHP5 much. If you see a blank page after upgrading to PHP5, then hit reload and it loads, then WP-Cache needs to be modified. Leroy has the fix, open wp-cache-phase2.php in your wp-cache folder and change ob_end_clean() to ob_end_flush(). SImple as that!

The reason for the upgrade? I wanted to install the gd extension, but after lots of fun upgrading everything my browser tried to download every page, complaining that it was a phtml file. I chose the upgrade to PHP5 to fix it!

And finally, the reason for gd, was to get the heatmap in this wordpress click tracking plugin working. It’s like Crazy Egg and it works well, but I couldn’t get it to display a heatmap for any page other than the front page. Some of the comments on Daily Blog Tips where I found it are hilarious. They completely miss the point of using a heatmap!

Cannot load mysql extension. Please check your PHP configuration.

A friend recently had a problem configuring a new server. He installed PHP, Apache, MySQL and phpMyAdmin but when he launched it he got the following error:

phpMyAdmin – Error
Cannot load mysql extension. Please check your PHP configuration.

If you’ve installed all of the above more than once you’ll know what is more than likely wrong. The MySQL PHP module isn’t loaded. First of all, you must find your php.ini. It could be anywhere but if you create a small php file with the phpinfo(); command it will tell you where it is. Common places include /etc/apache/, /etc/php4/apache2/php.ini, /etc/php5/apache2/php.ini or even /usr/local/lib/php.ini

Edit your server’s php.ini and look for the following line. Remove the ‘;’ from the start of the line and restart Apache. Things should work fine now!

;extension=mysql.so

should become

extension=mysql.so

Killing off PHP

Do you know why Apache processes get stuck and stop responding when serving pages on a WordPress site?

I’ve seen this happen here and on my previous host on a regular basis. I don’t know what happens. It can’t be a PHP script gone into an infinite loop because the normal Apache timeout should kill it. It’s not MySQL as a quick inspection of the process list usually shows it’s empty.

It could be plugins, some of them haven’t been written to the high standards that is expected in WordPress core. It could be some strange interaction between plugins and core code and memory limits and PHP extensions.

Whatever causes it, this will fix it. It’s brutal, it’s crude, but it’ll stop the load average going up on your box and it will ensure that every Apache child process is listening and responding. Add this to the crontab of your nobody or www-data user. Pick whichever user runs the webserver because you want to limit the damage in case something bad happens and the command malfunctions!
*/10 * * * * ps auxw|grep apache2| awk '$10 !~ /0:00/ {print $2":"$10}'|awk -F ':' '$2 !~ 0 {print $1}'|xargs kill -9 2> /dev/null
What this does is it uses the ps, grep, and awk tools to find processes that are using anything more than the minimum CPU time. It is very crude, but it works.

If you use Litespeed, then replace “apache2″ with “lsphp”. I have found that this is very necessary as those processes get stuck quite often, especially in low memory situations.