Login

Working Out of the Object Context to Build Loader Apps in PHP

Welcome to the fifth part of an eight-part article series that teaches you how to build loader applications with PHP. In this installment of the series, I explain how to create a small, efficient file loader class, with a difference: no instance of it needs to be spawned to include a targeted file, thanks to the implementation of a static recursive loading method.

Building small programs with PHP that can load a specified file or resource is an easily-tackled process for many developers with only average experience in the language. However, things can get more complex when trying to add some useful characteristics to these programs, such as recursive file search capabilities and exception handling. This requires a more intimate knowledge of the object paradigm and mastering some features that are only present in PHP 5.

Not all is lost, though, if you’re trying to build this kind of file loading application, since this group of articles will guide you through the entire development process in a truly friendly way, using a strong hands-on approach.

Of course, if you’ve been a patient reader who already went through all of the preceding articles of this series, then you probably have a solid background in how to create some handy file loading programs with PHP 5. In the aforementioned tutorials I discussed their construction, and once the basic concepts were properly covered, I proceeded to implement a few useful features, such as the capacity for including a specified file by means of recursive searches, using a starting file path.

The file loader class developed in the last chapter had a "load()" method that implemented this recursive ability in a truly straightforward fashion. Nevertheless, it’s valid to stress here that it’s necessary to create an instance of this class to include a determined file, except in those cases where its loading method is called statically.

However, to avoid an eventual (and unnecessary) instantiation of the loader class, it would be helpful to declare the mentioned "load()" method static. Thus, bearing in mind this important concept, in this fifth part of the series I’m going to enhance the signature of the "Loader" class created previously by turning its loading method into a static one.

Want to learn the full details of how this will be accomplished in a few simple steps? Then don’t waste more time; start reading now!

{mospagebreak title=Review: recursive file loading program}

In case you still haven’t had opportunity to read the last article of the series, where I explained how to build a file loading class with recursive search capabilities, below I’ve included the class’s full source code. Pay close attention to its definition, please:

<?php

// define a recursive loader class

class Loader

{

private $file = ”;

private $path = ”;

// constructor (not implemented)

public function __construct(){}

// set file to load

public function set_file($file)

{

$this->file = $file;

}

// get file to load

public function get_file()

{

return $this->file;

}

// set path to load file

public function set_path($path)

{

$this->path = $path;

}

// get path to load file

public function get_path()

{

return $this->path;

}

// load recursively specified file

public function load($file, $path)

{

if (file_exists($file))

{

require_once($file);

return;

}

else

{

if (is_dir($path))

{

if (FALSE !== ($handle = opendir($path)))

{

// search recursively the specified file

while (FAlSE !== ($dir = readdir($handle)))

{

if (strpos($dir, ‘.’) === FALSE)

{

$path .= ‘/’ . $dir;

$file = $path . ‘/’ . $this->file;

$this->load($file, $path);

}

}

}

closedir($handle);

}

}

}

}

If you look closely at the above "Loader" class, then you’ll realize that apart from its setters and getters, its actual workhorse is its "load()" method. This method is not only is responsible for including a specified file via the "require_once()" PHP function, but performs this task by using a simple recursive algorithm that traverses the proper directories on the web server.

So far, so good. Having quickly reviewed the definition of the file loader class, below I included a couple of examples that show how to include two basic PHP files. That being said, here are the two files to be included:

(‘sample_file1.php’)

<?php

echo ‘ This file has been loaded with the Loader class.’ . ‘<br />';

?>

(‘sample_file2.php’)

<?php

echo ‘This file has been loaded at the following time: ‘ . date(‘H:i:s’);

?>

And here are two examples that demonstrate a concrete usage of the previous "Loader" class, using in each case a different path to look for the targeted files. Here’s the first example:

// create instance of Loader class

$loader = new Loader();

// set file to load

$loader->set_file(‘sample_file1.php’);

// set path of specified file

$loader->set_path($_SERVER['DOCUMENT_ROOT'] . ‘/folder1);

// try to load specified file

$loader->load($loader->get_file(), $loader->get_path());

// set another file to load

$loader->set_file(‘sample_file2.php’);

// try to load specified file

$loader->load($loader->get_file(), $loader->get_path());

/* displays the following

This file has been loaded with the Loader class.

This file has been loaded at the following time 10:32:51

*/

Finally, here’s the second example, which utilizes a distinct starting path to look for the specified files:

// create instance of Loader class

$loader = new Loader();

// set file to load

$loader->set_file(‘sample_file1.php’);

// set path of specified file

$loader->set_path($_SERVER['DOCUMENT_ROOT']);

// try to load specified file

$loader->load($loader->get_file(), $loader->get_path());

// set another file to load

$loader->set_file(‘sample_file2.php’);

// try to load specified file

$loader->load($loader->get_file(), $loader->get_path());

/* displays the following

This file has been loaded with the Loader class.

This file has been loaded at the following time 10:45:02

*/

Well, I think that the above code samples should give you a clear idea of how the file loader class does its thing. However, as I mentioned in the introduction, it’s necessary to spawn an instance of the class to include a targeted file, which in truth can be completely avoided simply by declaring its "load()" method static.

So, based on this concept, in the section to come I’m going to improve the definition of the "Loader()" class by modifying the method discussed before, and incorporating into it a basic error handling mechanism as well.

Now, click on the link below and proceed to read the following segment.

{mospagebreak title=Improving the definition of the Loader class}

As I explained in the segment that you just read, it would be really useful to declare the "load()" method of the previous file loading class static, to make it callable only out of the object’s context. To do so, I’m simply going to refine the signature of the class in question, which now will look as follows:

class Loader

{

// constructor (not implemented)

public function __construct(){}

// load recursively a specified file

public static function load($file, $path)

{

$filepath = $path . ‘/’ . $file;

if (file_exists($filepath))

{

require_once($filepath);

}

else

{

if (!is_dir($path))

{

throw new Exception(‘The supplied path is invalid!.’);

}

if (FALSE !== ($handle = opendir($path)))

{

// search recursively the specified file

while (FAlSE !== ($dir = readdir($handle)))

{

if (strpos($dir, ‘.’) === FALSE)

{

$path .= ‘/’ . $dir;

self::load($file, $path);

}

}

closedir($handle);

}

}

throw new Exception(‘The specified file was not found!.’);

}

}

As you can see, not only have setters and getters been removed from the "Loader" class, but as I mentioned before, its "load()" method has been declared static for the reasons given previously. Besides, it’s valid to notice another subtle enhancement that has been also introduced in this method: it now will throw a regular exception if the file to be included isn’t found across the supplied path.

Definitely, the loader class is now a bit more functional and, best of all, it can be used for including files dynamically without having to deal with an instance of it. So, what’s the next step to take? Well, if you’re like me, then you’ll surely want to see it in action, right?

Therefore, in the final section of this article I’m going to develop another example, which will be aimed at demonstrating how to use the loader class out of the object scope.

To learn the full details of how this concluding example will be created, click on the link below and read the next few lines.

{mospagebreak title=The Loader class in action}

Certainly, the best way to demonstrate how the enhanced version of the "Loader" class works is through a concrete example. Therefore, bearing that concept in mind, below I included an easy-to-grasp code snippet, which uses the static "load()" method of the class to include the two sample PHP files that you saw at the beginning of the article.

Here’s the example:

// example of usage of the recursive loader class

// prepare path to search for the specified file

$path = $_SERVER['DOCUMENT_ROOT'] . ‘/path';

// try to load the first specified file

Loader::load(‘sample_file1.php’, $path);

// try to load the second specified file

Loader::load(‘sample_file2.php’, $path);

/* displays the following

This file has been loaded with the Loader class.

This file has been loaded at the following time 22:18:21

*/

That was pretty simple to code and read, wasn’t it? As you can see, now the sample files have been successfully included by the above script, without having to spawn an unnecessary instance of the "Loader()" class.

In this particular case, I decided to feed the method with a fictional starting path to look for those files, but as homework for you, I suggest you try using different paths and changing their locations to see how the class behaves in each case. The experience will be pretty instructive, and also fun.

Final thoughts

That’s all for the moment. In this fifth installment of the series I explained how to create a small — yet efficient — file loader class, but in this particular case, no instances of it need to be spawned to include a targeted file, thanks to the implementation of a static recursive loading method.

Also, as you may have noticed, the loader class developed so far doesn’t use the "__autoload()" magic function included with PHP 5. So, it’s time to take advantage of it, don’t you think? Therefore, in the upcoming article I’m going to discuss how to build a file loading program using this handy function.