Late static binding….sorta :/

The good news is late static binding has been introduced into head and looks like it will be merged into 5.3 before it is released. The horrible news is I really don’t think the patch went as far as it needs to.

If you look at the original posts that cropped up about a year and a half ago the whole purpose of late static binding was to allow the same kind of flexibility provided by inheritance of standard class methods for static methods, properties, and constants. This wouldn’t really open the door for any grandios, new kind of applications, it would just allow a new way to code libraries the most prominant example being an Active Record Library.

This is now possible, however I think there is a very unfortunate limitation that I brought up a few times on the Internals mailing list to apparently no avail. The problem is with the fact that static will ALWAYS return the ‘resolved’ name of the class used to call the current function. So, imagine the following method:

If you call test using Foo::test() then static:: will resolve to the ‘Foo’ class. If you call it using Bar::test() then static:: will resolve to ‘Bar’. This is correct and works well for simple inheritance. However things start taking a downward turn the more you use inheritance. Consider the following change to Bar and the addition of a new class Bar_Child:

Now, calling Foo::test() will again result in static:: being bound to ‘Foo’. However, due to the fact that parent:: will resolve to Foo:: that means the call Bar::test() will now result in static:: being bound to ‘Foo’. Bar_Child::test() will do exactly the same thing, static:: will again be bound to ‘Foo’. This is incredibly inflexible and in my opinion this is the exact problem that ‘late static binding’ is SUPPOSED to fix.

There are a couple of ways to fix this that I can think of right now, unfortunately nobody on list seems very motivated to explore any compromises. The two ways that come to mind immediately are either setting the behavior of parent:: such that it forwards the calling class through the next function call. So in the example above, calling Bar::test() will still result in calling Foo::test() however it will not ‘reset’ the calling class so that static:: will still resolve to ‘Bar::’, likewise Bar_Child::test() will result in static:: being bound to ‘Bar_Child’.

The second alternative is introducing another scope. I have no clue what this scope would be called, but it would basically implement the functionality I just described for parent:: above but would do it using a new keyword so parent:: could remain the same.

Dmitry Stogov mentioned my first alternative on the list however he also included this functionality for the self:: scope which I could see causing some serious problems. In either case, I am thankful that the functionality has started to make its way in, but I can’t help but think that myself and some other early proponents of the functionality are getting completely shafted.

Adding Database Tests to Existing PHPUnit Test Cases

When I was first creating the Database Extension for PHPUnit I realized that there was a very high likelihood that several people would have tests that were already written that they would like to add additional database tests too. To accomplish this I actually wrote the PHPUnit_Extensions_Database_DefaultTester class. In fact, if you were to look at the source of the database test case you will see that all of it’s operations are actually forwarded to this class which does all of the work.

Please continue reading to see how you can use composition to add database tests to your existing test cases.

Continue reading Adding Database Tests to Existing PHPUnit Test Cases

PHPUnit Database Extension (DBUnit Port)

I have completed the initial feature set for the Database extension to PHPUnit. This is a essentially a port of DBUnit to PHP.

For those that may not have read any of my previous postings on the subject the goal of this software is to extend the functionality of PHPUnit to allow using seed data to put a given database into a known state prior to executing each test. It also provides an easy mechanism to compare database contents with an expected dataset.

The database extension has recently been merged into the PHPUnit 3.2 branch and is scheduled to be released in that version. Sebastian Bergmann will be introducing the extension in his Advanced Testing with PHPUnit talk at PHP|Works 2007 in Atlanta September 13 – 14. If you would like to tinker around with the database extension prior to it’s release you can always download the latest copy of PHPUnit 3.2 from svn: svn://svn.phpunit.de/phpunit/phpunit/branches/3.2. The source can also be browsed at http://www.phpunit.de/browser/phpunit/branches/3.2/PHPUnit/Extensions/Database.

Please continue reading for an example of how you can now use PHPUnit to even more effectively test data-centric applications.

Continue reading PHPUnit Database Extension (DBUnit Port)

PHPDBUnit – Testing DB interaction with PHPUnit

It’s been a while since I have put anything in the heavily neglected little site of mine so I thought I would start posting some updates on a few little projects I have been working on. I have been spending a considerable amount of time traveling for work so I am not quite as far along in these projects as I would like to be, but I have been making some major head way.

The project I would like to talk about right now is a port of Java’s DBUnit for php that will compliment the PHPUnit test suite. For those of you not familiar with DBUnit, it is a framework that allows you to easily and quickly test php code that modifies and works with database data. The whole idea behind unit testing is testing functions using well defined input and then comparing the output of that function with the values that you expect the function to produce. With database code this is somewhat difficult because you have to ensure that your database is in a known state prior to running your tests. Currenty, in order to do this properly you would find yourself adding significant amounts of code to your test to simply enter data into your database and then you will add even more code to compare the resulting database values with what your expected output. Ending up with something like this:

This is a fairly simple example and they really only get more complicated from this point forward. In order to the equivelant test using PHPDBUnit you would create a test class as follows:

You will also have to provide two xml files for the above code. This first xml file (dataset.xml) is used to seed the database before every test. The second xml file (expected.xml) is used to compare your database after the test is ran. These two files allow to get the code seeding your database out of your test cases and into their own xml files. There are also other options for generating data sets, I will discuss these options as well as the xml formats for datasets in a future post.

The database connection functionality is built overtop of PDO and support is planned for all standard pdo drivers. The big question mark for me right now is the ODBC driver. The PDO connection is wrapped by a PHPDBUnit_Database class that provides the functionality to generate datasets from the database to test your data and ensure it is correct.

The seeding is controlled by two functions that I did not choose to override in my example: getSetUpOperation() and getTearDownOperation(). These functions simply return a database ‘operation’ that is to be performed on the database connection using the data set returned by getDataSet. The default setUp operation is a clean insert. This is a truncate operation immediately followed by an insert of all data in the dataset. The default tear down operation is a null operation. You have several built-in possibilities for these operations such as Truncate, refresh, and update. You can also create your own operations if necesary.

My plan is to keep the interface of PHPDBUnit as close as possible to DBUnit while maintaining a more phpish way of doing things. I am planning on the first beta release of PHPDBUnit in July. Of course I welcome feedback on any features you would like to see. In the coming days and weeks I will continue to post more information and examples of how to use DBUnit in your tests.

81.4 is evil

I know many of you all know pretty well that floating point precision and computers don’t play nicely with each other. I think I learned about it in the first book on ‘C’ I ever read, but I had never really been bitten by it until today. I was working with a piece of code today at the office that was throwing an error saying two values weren’t zeroing out when they clearly should have been. I narrowed down the problem and after a bit of time decided that 81.4 is a terrible, terrible number. For example:

So, let that be a lesson to us all. No matter how simple the calculation, don’t blindly trust floats.

Come Work With Me!

I have recently been very encouraged by the number of job opportunities available to PHP developers lately. In light of this I thought I would make everyone aware of yet another excellent opportunity for a highly motivated, well-versed PHP programmer. The company I recently started working for (The Selling Source) is still hiring PHP Developers. I can say without a doubt that it’s a great company to work for and they take very good care of their programmers. Read on for details.
Continue reading Come Work With Me!

A New Direction

It’s been quite some time since my last blogging. Most of the reason for this is that I have been extremely busy with my current job as well as a few other responsibilities. However, the time has now come for me to move on and try something new. Early this month I accepted an offer to work for The Selling Source in Las Vegas. It is a hard move since I have been employed by my current employer, FT11 Interactive, for my entire professional career. I am looking forward to the change and the new people I will meet. Since I will be moving away from a smaller startup type atmosphere I am hoping I will have a little more time to work on some of the little projects I have been chipping away at for the last year.

Late Static Binding

I haven’t been able to touch this in what seems like ages and have (unfortunately) completely missed the boat for PHP 5.2. But I am hoping to take a look at the current patch, come up with some solid use cases and tests, and submit the whole package to PHP Internals for review.

Scriptable Browser for PHP 5.1+

This is actually a fairly new project and one that I haven’t put alot of time into yet. The goal behind this is to create the scriptable browser and then soon thereafter create a binding for it so it can be easily used with PHPUnit 3. I am sure there are at least 3 or 4 people wondering why I don’t just work with SimpleBrowser or Selenium, and the simple answer to that is: Cause that’s no fun.

Refactoring Tools

This little project is actually one that I haven’t even talked about yet. I am finding that there is a real lack of tools to assist in refactoring php scripts. What tools we do have (aside from testing tools) are not at all php specific. With the advent of Greg Beaver’s PHP lexer it has all of a sudden became fairly trivial to do in-depth source code analysis. I have almost completed a small code metrics suite and will (hopefully) be releasing it to the public soon.

A Bigger, Badder Looking Site

I promised myself around 2 years ago that I would create a site that wasn’t a s9y stock theme, I have yet to do that, so that’s also going to be on my agenda for the very near future.

So, I have to thank FT11 Interactive and it’s management for 5 excellent years, and while I am sad to be leaving I would be lying to say I am not excited about this new opportunity. Hopefully now I can hit some of those conferences :P.

Finally used PHPUnit and I like it

I have been working quite a bit lately with the cvs version PHPUnit3. I have spent alot of time in testing using SimpleTest and I have also given some time to test-more.php. However, up until just recently I had honestly never used PHPUnit before. The big motivational factor for me (other than to try something new) was to see how the code coverage feature was coming along.

I would have to say that after a few weeks of tinkering with it I am impressed. Now, keep in mind that I am talking about software that is still in development, so a degree of lattitude is required. The featureset of PHPUnit 3 is great. Here are a few notable features (in my mind):

  • Mock objects
  • Code Coverage Analysis
  • Multitude of test logging options
  • Built well for testing >php5 applications

Using the framework is an absolute breeze and there is excellent documentation in the form of a free book (draft version) written by Sebastian Bergmann and published by O’Reilly called "PHPUnit Pocket Guide." The API is also documented quite nicely and serves as a good second-source for learning how to do specific things.

The most impressive part of this experience in my mind was how runnable the software is straight out of CVS. Most of the time when I am crazy enough to use CVS version I always seem to get my copy of the source at a point where it is very unstable and requires tweaking just to get the software to fulfill its basic requirements. PHPUnit 3 on the other hand was able to run in it’s standard mode without a flaw. The only thing that was missing that I felt I needed was html reports for the pass/fail status of the unit tests. The report templates and code was already to a point however that it was actually fairly trivial for me to make the changes to it that I thought would be needed to make it work. I have since passed those changes along to Sebastian and they have been added to CVS, so html reports are now in the cvs version as well. It felt good to be able to contribute a little bit to a very worthwhile project.

Sebastian has posted about the new reporting features on his blog that include some screenshots so I won’t bother to rehash over all of that. You can just go check them out on his site.

I

I was toying around with regexs this morning and learned a few things I had just never taken the time to learn before. In any case, I came up with this:

#((?:(?<!\)"(?:(?:(?:[x20x09]*[rn])?[x20x09]+)?(?:[x01-x08x0b-x0cx0
e-x1fx7fx21x23-x5bx5d-x7e]|\[x01-x09x0b-x0cx0e-x7f]))*(?:(?:[x20
x09]*[rn])?[x20x09]+)?"|[^"(]+|\["(]|^)+)(?:(?:(?:(?:(?:[x20x09]*[rn])
?[x20x09]+)?(?P<comment>((?:(?:(?:[x20x09]*[rn])?[x20x09]+)?(?:[x01-x
08x0b-x0cx0e-x1fx7fx21-x27x2a-x5bx5d-x7e]|\[x01-x09x0b-x0cx0e-
x7f]|(?P>comment)))*(?:(?:[x20x09]*[rn])?[x20x09]+)?)))+(?:(?:[x20x09]*
[rn])?[x20x09]+)?|(?:[x20x09]*[rn])?[x20x09]+))#

(of course ignoring line breaks.) An ‘atta boy’ (or girl as the case may be) to anybody that can tell me what this would be used for :P.

Intercepting php mail() spam with sendmail and formail

I have noticed alot of people talking about mail header inections this past week. I have actually had a run in with this on one of my servers this last week too. On one of our servers where we host around 50 clients I have recieved in the neighboorhood of 7000 delivery failure notices to the server’s postmaster account. Almost all of them being failed spam messages. I was told that sendmail client on the server was for sure configured such that it couldn’t be used directly via smtp as an open relay, which means the e-mails were most likely coming from a compromised mail form script. So I spend an entire day tracking all of them down and patching them. I was pretty sure I got them all, but then the next day I got a bunch more failures which dated the original e-mail about 26 hours after the holes were all patched.

So, I was trying to think of a way to be able to monitor the php mail() so I can have it flag me when it detects possible spam being sent with it. Then I was reminded of an article fom the November 2005 php|architect by Ben Ramsey title mail() hacks. The article basically looks at various ways to intercept the mail() function for site testing purposes. So I am now using a variant of the same technique to catch spam being sent through php.

Php allows you to specify the path of your sendmail program via the sendmail_path ini option. Whatever program this points to is then passed a formatted e-mail message (with headers) via its STDIN whenever the php mail() program is called. So simply put you can swap out any program/script for sendmail to allow you to log e-mails, redirect it, or even modify it’s headers.

A while ago I wrote a script that I use with my servers’ postmaster accounts to notify me whenever there are any serious problems. This lets me know when there are any abnormalities (a large number of delivery failures, missing accounts, server errors, reports etc.) without me ever actually having to sift through each an every e-mail. So I figured it would be fairly trivial to just add some logic in there to sift through mail submitted via the mail() functions. The only problem was to find a way to intercept the messages.

Unix has a handy little program called formail (yes with one ‘m’) that makes it extremely easy to edit an email’s headers via the command line. So using this program I am now able to add a Bcc line with my address to any function sent with mail. In order to make it easy for my script to determine which e-mails come from php I am also adding a custom header: "x-php-formmail: yes." Also since I amp having a severe problem with injections I have taken the extra, temporary step of removing all other Bcc Addresses but my own and moving them to a different custom header.

The script looks like this:

Eventually, once I am sure that I have all the holes patched I will remove the ‘-R bcc x-original-bcc’ and at that point usage of this script will be completely transparent from a programming perspective.

Curse the spammers.

For those of you who would like more information about mail header injections I found this site. It has some pretty decent information: What they are, how they happen, how you fix them, it’s all covered.

Chris Shiflett also did a podcast with Marcus Whitney recently about mail header injections.

Then of course there is always the good ‘ole php manual. The comments have quite a bit to say about mail header injections. However, I recommend caution when reading through them, as always there of some good recommendations and some very, very bad recommendations.