Skip navigation

Ivories *

Well, that was fun. I have pussyfooted around the idea long enough, and have finally decided to take the plunge. I’m changing my career to yet another male-dominated field (because I’m secretly a dude), composing, and putting the coding on indefinite hold. I’m sure the PHP world will survive.

The main purpose of this post is to let peeps know that I am not currently looking for work, and no, I don’t know of anyone who does. If you have a film scoring project, however, do get in touch with me (phpdiva at gmail) ;)

* Photo by ViaMoi

Abacus

Abacus *

Recently I ran into an interesting problem, while using an aggregate function in a SELECT SQL statement. Initially the behavior seems to defy common sense, so I thought I’d share.

Consider this hypothetical database table called “items”:

id | category_id | amount | title
-----------------------------------
1  | 1           | 1      | Item 1
2  | 1           | 2      | Item 2

My goal was to retrieve all items with the maximum amount in each category.  Naturally, I wrote the following SQL statement:

SELECT id, MAX(amount) AS amount, title FROM items GROUP BY category_id;

The result was definitely unexpected. What I got was:

id | amount | title
--------------------
1  | 2      | Item 1

So I did get the maximum amount, but no matching data from the corresponding row. It appears that MySQL just grabbed the first row in the group and returned it along with the maximum amount. After some searching, this behavior actually makes sense. Just consider what would have to be the result if we had more than one row with the same maximum amount, or if we had both MAX() and MIN() functions in our statement.

There are a couple ways to still accomplish this in a single query:

Option 1:

SELECT id, amount, title
FROM items AS items1
WHERE amount = (
    SELECT MAX( amount )
    FROM items AS items2
    WHERE items2.category_id = items1.category_id
)

Option 2:

SELECT items1.id, items1.amount, items1.title
FROM items AS items1, (
    SELECT category_id, MAX( amount ) AS amount
    FROM items
    GROUP BY category_id
) AS items2
WHERE items1.category_id = items2.category_id
AND items1.amount = items2.amount

I’m not sure which approach is better. Option 1 seems to be a bit faster and appears to perform less sub-queries, according to EXPLAIN, but that might entirely depend on your database structure and indexes (MySQL calls them that). I would be happy to hear an explanation of which way is better and why.

In my own application, for the sake of scalability, I decided to keep an additional table with only the highest amounts in each category. I’m planning to update that “tally” table every time an item is added or edited.

Photo by cyberdees

Awhile back I was working on a Drupal project, and needed to disable the default RSS feed of the site. I was slightly surprised to find that there is no admin setting to do this, nor a module to perform this functionality. However I found this issue in Drupal project issue queue, which apparently was opened in 2005, and, gasp, still wasn’t implemented into the Drupal core. Now, I’m not the one to bash Drupal, because to me it’s still the best PHP open source CMS out there; but even I thought this was a little out of control. Anyway, make of it what you will.

After consulting the Drupal API, I quicky came up with a solution for my site, and posted it as a comment to the issue. That was almost a year ago.

Recently I was checking on my Drupal discussions, and found out that the issue was still open, the fix didn’t make it into the core for Drupal 6 (update: apparently it didn’t make it into Drupal 7 either), and people were requesting a one click solution to fix this in the mean time. Long story short, I decided this was my opportunity to give back and contribute this as a small module to the Drupal modules collection.

Since I wanted to make the module available on drupal.org, I had to go through the CVS application process. In case you’re curious how to go about it, the steps are:

  1. Make sure your module is not a duplicate of anything else out there. If in doubt, post to the Contributed module ideas group (my posting here).
  2. Create your module, and validate it against the Drupal coding standards.
  3. Submit a CVS application. Make sure to read the instructions thoroughly. My application is not a very good example of doing this, since admittedly I was lazy and wanted to get away with the smallest feature set possible, anticipating that people will request new features through the issue queue. That didn’t go over so well, and I had to rewrite my module to be more full-featured.
  4. Rinse and repeat!

After almost two months of rinsing, my application finally got approved, and it was time to give back to the peoples.

Oh, how I love CVS!

Again, Drupal, being what it is, is still using CVS for version control. After reading through tons of documentation on using CVS, and tagging and branching conventions in Drupal, I was ready to commit. The only problem: "which cvs" on my Mac was staring back at me with a blank command prompt. I was able to install a pretty nice GUI for Mac OS X, SmartCVS, but really wanted to stick to the command line, since the documentation was very particular on setting the appropriate flags when running CVS commands.

In my search I have found this very helpful video on Lullabot on installing the command-line CVS on Mac OS X. All I had to do was download the Apple XCode Tools, and install a small subset of it to get the CVS. To my dismay, I found that the in the 3.x version of the XCode, the “small subset” is close to 2Gb, which was a no go.

Installing command-line CVS on Max OS X

And finally the solution. In fact, it was very simple. Just download and install Pacifist, which is a sort of installation package browser. Browse the XTools installer with it, search for “CVS”, and install the parent package which contains the CVS. I think it was called “DeveloperToolsCLI”. Bam, you have command-line CVS!

And without further ado…

…lo and behold: my first contributed Drupal module: RSS Permissions.

Blank Screen

Blank Screen *

This may seem obvious for experienced developers, but I’ll say it anyway: turn on your errors during development. 99% of the time, the notorious “blank screen” means that you have an error, and it’s not being displayed. (In the other 1% of the cases, you are not actually outputting anything to screen and I have no remorse for you.)

There are several ways to set error reporting in PHP, but before I get to that…

DISCLAIMER: While you should display errors on your development sites, you should NEVER display errors on production server, but log them instead. It’s a huge security issue, since sensitive data IS displayed in the errors, which makes your site vulnerable to attacks.

OK, not that that’s out of the way, here’s how you can set PHP error reporting:

1. PHP Configuration file: php.ini

Just modify the lines in your php.ini like so:

error_reporting  =  E_ALL & ~E_NOTICE
display_errors = On

The code above will show all errors, except for notices about potential issues and coding standards warnings, on screen. Those funny squiggly things are Bitwise Operators, and you can read the error reporting level above as “E_ALL and not E_NOTICE”.

This is one of the most commonly used error reporting levels, but if you really want to follow the best practices, I suggest setting error_reporting level to E_ALL | E_STRICT, which will display all errors, plus make your code “future-proof” by pointing out soon-to-be-deprecated items.

2. Apache: .htaccess & httpd.conf

If you don’t have access to your php.ini file, you can create an .htaccess file and place it in the root of your document, or edit the one already there. Just adding these lines to .htaccess will have the same effect as the php.ini method above:

php_value error_reporting 6135
php_flag display_errors true

If you are wondering where the 6135 came from, it’s the integer representation of E_ALL & ~E_NOTICE. Each of the predefined PHP error level constants has an integer value. And since .htaccess is not processed by PHP, we don’t have access to constants yet, so we must use integers.

Basically, 6135 is 6143 (E_ALL) – 8 (E_NOTICE). Check out the rest of Predefined Constants and their integer values. You can also quickly figure out the number you need by echoing the desired expression in your PHP script, like so:

echo E_ALL & ~E_NOTICE;

One gotcha to this is that integer value of E_ALL has been changing from version to version (with new error levels being included into E_ALL). Incidentally the line of code above will return 30711 in PHP 5.3, as opposed to 6135 in PHP 5.2. So if you want to display all errors and notices possible, just use

php_value error_reporting -1

You also have an option to set these values in httpd.conf, however I am yet to encounter a situation where it would be the best place to set error reporting.

3. PHP file

I personally prefer this method to the other two. There are several advantages to it:

  • Sometimes it can be the only way to set error reporting. You don’t have access to tweaking php.ini or restarting the server, or .htaccess may be disabled on the host.
  • If you are using some sort of framework with a common front controller or bootstrap, it’s the best place to put error reporting. It lets you turn errors on and off depending on the environment. As a matter of fact, most MVC frameworks will have this built in already.
  • You can place the code anywhere in your PHP document, in case you need to quickly debug a single file or area.

As you can see, you will use the same constants as in php.ini file.

if (/... some kind of in development flag .../) {
	ini_set('display_errors', TRUE);
}
else {
	ini_set('display_errors', FALSE);
}
error_reporting(E_ALL & ~E_NOTICE);

The “in development” flag may be something you set in a configuration file, based on the environment.

If you must turn the errors on on production server temporarily, there are a couple ways you can do it without displaying them to the whole world. These are to be used only when stuff hits the fan.

  • You can limit them to only your own IP address, using the little trick below. Replace [ my IP ] with your real IP address, which you can get from a site like http://www.whatismyip.com/. Just keep in mind that both of these values can be spoofed.

if  ($_SERVER['REMOTE_ADDR'] == '[ my IP ]' || $_SERVER['HTTP_X_FORWARDED_FOR'] == '[ my IP ]')  {
	// Turn on error reporting here.
}

  • You could also create a page that sets a specific session value, and only display errors based on that session value. In other words, get creative, but don’t get carried away.

There’s a gotcha here as well. This will NOT report any syntax errors, like a missing semicolon or comma. That’s because syntax errors happen during the compilation of your file, so it “breaks” before it’s told to report errors, and you will get a blank screen.

The best way around that is to have a single error-free bootstrap file, which will turn on error display and then  include other files (this is the case in most MVC frameworks). Sometimes that’s not an option, and you have a single file with a syntax error that you are unable to find.  In that case, if you have access to command-line, just run your file from there:

$ php myfile.php

Even though the logic in the file won’t work, the compiler will report syntax errors. Another option is to copy the file to a server that has error reporting enabled and find your syntax errors that way.

So, which one to use!?

So many options… Like a lot of things in programming, it’s largely a matter of taste. But here’s my preference.

  • If you have a dedicated development server, you should use php.ini. Set it and forget it, so to speak.
  • If your application has a common file, like a front controller or bootstrap, use the PHP method. That way you can easily control error display on the application level, based on environment and other factors.
  • .htaccess is best if you don’t have access to php.ini, and you don’t have a front-controller application.

* Photo by toasty

** This post is part of Debugging PHP, Guerilla Style series.

A Nasty Bug

A Nasty Bug *

Arguably, one of the most valuable skills in web development is the ability to debug quickly and efficiently. Bugs are an inseparable part of software development, no matter how great the developer is. There are best practices and tools that can bring the number of bugs to a minimum; and if you are writing a project from scratch, you have great leverage to control the environment, and implement those best practices. PHP coders these days have a great selection of debugging tools available, such as Xdebug, and even full-featured IDEs, like Zend Studio. I think tools like these are fantastic, and everyone should use them!

However, we don’t always have access to these tools, or ability to control the environment. Sometimes, depending on the nature of the project, we take over someone else’s code, don’t have access to servers, or have to use someone else’s computer with a plain text editor.

So what is debugging guerilla style? I’m talking about the covert and creative ways of finding the error fast, when you don’t have many tools to work with. Sometimes the stuff just hits the fan, and you need to dive in and get it fixed. These tactics may not be the Holy Grail of efficient development, but they may be the only ones available in some situations. They have certainly saved my behind on many occasions. Some of them are PHP-centric, while others can help with pretty much any language.

Once I started writing this, I realized it might be too much information for a single post, so I will break this into a series. This collection is as much for my personal reference, as for public use, therefore I welcome any comments, questions or suggestions. The last thing I want to do is put out false information out there.

Part I: “OMG, I’m Getting A Blank Screen!” or how to set error reporting in PHP.

* Photo by cibergaita

Check out this awesome holiday card from Threshold Interactive.

Follow

Get every new post delivered to your Inbox.