Tag Archives: style

php autoload

As of version 5.0, PHP has had the ability to dynamically include required classes as needed – without requiring the developer to manually include all possible dependencies beforehand. This means that in cases where your code execution never touches 39 of the 40 classes in the project, it loads, parses, and runs that much faster.

There is a performance hit for actually having to call the __autoload() method, but if you’re in a situation where the hit for executing a few extra comparison calls is unacceptable… you probably aren’t developing in PHP in the first place 😉

Almost all of the php I’ve written in the last 2-3 years uses autoloading, and it has probably saved me hundreds of hours of aggravation.

In most of my projects, the first line of any script or class usually looks something like this:

Then lib.php usually reads something like this:

And that is all that is strictly required to make the magic happen. It is fast, it is easy to understand, it is easy to use. You can use require_once() or include_once() and there is very little meaningful difference.

I’ve looked around the net and found several other attempts at improving on this simple mechanism. But they invariably overcomplicate things. They attempt to recurse source directories, cache filename->class differences to the filesystem, and otherwise turn what should be a simple filesystem operation that the php environment supports natively into a mess of exception handling and wheel reinvention.

There are obviously theoretical instances where you might want to have more than the one require_once/include_once line… but I’ve honestly never encountered one myself.

I mean, you could try to throw an exception if the file didn’t exist or otherwise failed to load… but nothing will happen. Failure to instantiate a nonexistant class is a fatal error in PHP, and will be handled as such with or without you – preempting any attempt at throwing an exception.

The only thing you can add is a bit of extra diagnostics or maybe logging to a separate location.

Assume that we have a file ‘test.php’:

If autoload.php contains a simple simple autoload function that uses require_once(), and Frog.php doesn’t exist anywhere in your include path, the results will look something like this:
[code]
ammon@kif:~$ php test.php

Warning: require_once(Frog.php): failed to open stream: No such file or directory in /home/ammon/autoload.php on line 3

Fatal error: require_once(): Failed opening required ‘Frog.php’ (include_path=’.:/usr/share/php:/usr/share/pear’) in /home/ammon/autoload.php on line 3
[/code]
If we had used an include_once() call, the output is similar, but slightly more informative:
[code]
ammon@kif:~$ php test.php

Warning: include_once(Frog.php): failed to open stream: No such file or directory in /home/ammon/autoload.php on line 3

Warning: include_once(): Failed opening ‘Frog.php’ for inclusion (include_path=’.:/usr/share/php:/usr/share/pear’) in /home/ammon/autoload.php on line 3

Fatal error: Class ‘Frog’ not found in /home/ammon/test.php on line 4
[/code]
So that’s probably a bit more useful in tracking down the error. Require calls don’t return anything – they throw a fatal error on failure. Include calls, however, return FALSE on failure and TRUE if the file is (or, in the case of include_once, has already been) successfully included. So you can include_once() and write to a separate logfile (or to the output stream…) if you need more information than the fatal error already provides you.

<rant>

To those who insist on giving your classes and their containing files different names… umm. Wow.

If I have a class called DatabaseConnection, I’m going to put it in a file called DatabaseConnection.php. If I’m working with strange people who somehow don’t think that is explicit enough, I might call it DatabaseConnection.class.php and tweak the autoload method ever so slightly to compensate. There’s no good reason to put it in a file called projx-database_connection.incl or something. No. There isn’t.

If you want to organize your classes into a meaningful directory structure… good for you. Use PHP’s built-in include_path ini option. Don’t waste time trying to cascade down a directory structure searching for the classes – just make sure your includes are all in a set of reliable locations. You don’t actually have to edit the php.ini file and bounce Apache or your php-cgi processes, just define the additional include paths in the same file where you define your autoloader:

Naturally, you could turn that into some function calls to dynamically register and unregister directories, etc… but at that point, you’re probably hurting yourself again. If your codebase is being reorganized enough to make maintenance of the list of include dirs onerous without full time intervention, something else has probably already gone very wrong. At best, the code probably doesn’t work anyway, so any brief delay in updating the list can’t hurt any more than whatever else is happening.

</rant>

But seriously. __autoload() is your friend. It will help clean up your code if you let it. It can help enforce naming conventions. It can even improve performance… so long as you refrain from using it to shoot yourself in the foot. 😉

flexunit basics

The following is adapted from a brief tutorial I wrote for our company‘s internal conventions wiki.

And yes, I know the syntax hiliting could be better. I’m looking into switching over to WordPress and a new stylesheet, so hopefully this sort of thing will all be resolved in the nearish future.


FlexUnit

FlexUnit is a powerful unit testing framework for as3/flex2 projects. There are two API’s out there called FlexUnit, one is a SourceForge project and one is official from Adobe. The SF project is ancient and unmaintained, I will be referring to the official API.

FlexUnit also has some competition from the AsUnit project, but seems to be slightly less well suiteded for our needs when testing AS3 projects. It does, however, seem to offer fairly good support for AS2 projects. The two frameworks are generally very similar and switching between them should be fairly painless if necessary as they both evolved from and are modeled after JUnit, the industry standard for unit testing in Java.

FlexUnit is available for download from Adobe Labs. You want the zip file.

The official API documentation for FlexUnit is at http://weblogs.macromedia.com/as_libraries/docs/flexunit.

Warning: If your default run target in Flex doesn’t use the right flash player version/options, it is entirely possible that your failures might not be documented. Run the swf again in the standalone debugging player and you should get the information you missed. I’m not entirely certain why this is happening but I don’t much care at the moment.

Using FlexUnit

To make use of FlexUnit in a Flex 2 project only two bits of prep work need to be done:

  • Add the flexunit.swc file (found in the zip on Adobe’s site) to your project’s library path.
  • Create a test runner application in the project. This is Flex, so remember that applications have to be in the root of the project tree.

An example simple test runner (adapted very slightly from Darron Schall’s howto post):

Test Cases

The way the framework functions is by running a series of test cases. Each test case is an instance of the TestCase class which may or may not do any number of things. Test cases may also be organized into TestSuites which are little more than a list of test cases which will be run in order if desired. TestSuite.add() may accept either individual TestCase instances or TestSuites.

The constructor for a test case accepts one argument, the name of the method to be called when the test is run. Thus it is possible and advisable to create a single class for each group of related tests and instantiate multiple copies, each instructed to run a different test.

When a test runs it counts the results of all assertion methods called. These methods are:

  • AssertEquals()
  • AssertFalse()
  • AssertNotNull()
  • AssertNotUndefined()
  • AssertNull()
  • AssertStrictlyEquals()
  • AssertTrue()
  • AssertUndefined()
  • fail()

Each of the assertX() methods takes two parameters, a string describing the error to describe if the test fails and a value to be tested.

Fail may be used to throw error messages if you want to perform more complex tests than the prefab asserts provide.

A sample test case class:
[as3]
package test {
import flexunit.framework.TestCase;
import flexunit.framework.TestSuite;

public class SomeTest extends TestCase {

// declaring the redundant constructor saves you from having to cast when you construct
public function SomeTest( methodName:String ) {
super( methodName );
}// end: constructor

// this method returns a suite containing all of the tests provided by this class in
// the order they should be run
public static function suite() : TestSuite {
var ts:TestSuite = new TestSuite();

ts.addTest( new SomeTest( "testA" ) );
ts.addTest( new SomeTest( "testB" ) );
return ts;
}// end: suite

public function testA() : void {
AssertTrue( "True does not equal true?!", true );

var tmp:Object;
AssertNull( "Tmp should be null here.", tmp );
tmp = {};
AssertNotNull( "Tmp shouldn’t be null any more.", tmp );
}// end: testA

public function testB() : void {
fail( "This test always fails" );
}// end: testB

}// end: class
}// end: package
[/as3]

Asynchronous Tests

FlexUnit offers good support for asynchronous event-driven test cases. AsUnit apparently has also recently (ie, as of early-mid October, 2006) added this support for AS3 projects.

There are a number of asynchronous methods that tests can call but the actual 1st-party documentation on how to use them is a bit thin. In stead, Adobe refers us to hunt down and comprehend the test cases written for the Mappr API. I’ve attempted a bit of this comprehension. The only one of their test suites to use asynchronous calls is the MapprServiceTest class.

Even in this case, they’re only using one aspect of the functionality. That is the TestCase.addAsync() call. This function looks like it might be enough for what we need, it adds a checkpoint to the queue (and pauses it?) and then returns a proxy function that looks like it should clear the checkpoint and then execute the next function in your list.

The framework looks like it has more robust options than this for writing asynchronous tests, but I believe this is all we need for now.

A sample class that tests loading data from an external source might look something like this:
[as3]
package test
{
import flexunit.framework.TestCase;
import flexunit.framework.TestSuite;
import flash.net.URLLoader;
import flash.net.URLRequest;

public class RemoteXMLTest extends TestCase {
private static var TIMEOUT:int= 10000; // 10 seconds
private var loader:URLLoader;

public function RemoteXMLTest( methodName:String ) {
super( methodName );
}

public static function suite() : TestSuite {
var ts:TestSuite = new TestSuite();
ts.addTest( new RemoteXMLTest("doIt") );
return ts;
}

public function doIt() : void {
var request:URLRequest = new URLRequest("http://somewhere.com");
assertNotNull( "request is null", request );

loader = new URLLoader();
assertNotNull( "loader is null", loader );

loader.addEventListener( "complete", addAsync( onLoaded, TIMEOUT ) );
loader.load( request );
}

public function onLoaded( result:Object ) : void {
// don’t actually have to do anything here, but eh, why not?
assertNotUndefined( "we got no result?", result );
}
}
}
[/as3]