Login

Developing a Recursive Loading Class for Loader Applications in PHP

Welcome to the third part of an eight-part series on building loader applications in PHP. In the tutorials that comprise this series you’ll find numerous examples aimed at demonstrating how to create small, yet efficient, resource loader classes, not only by taking advantage of PHP includes, but the handy “__autoload()” magic function and the Standard PHP Library (SPL) as well.

Developing PHP programs whose main task is to dynamically include files required by a specific application isn’t as difficult as it may seem at first sight. In these cases, the logic that drives those programs is implemented around the set of “include()/include_once()/require()/require_once()” native PHP functions, which are pretty familiar to many developers having an average background on this language.

So, if you’re searching for an approachable guide that shows you how to build file loading applications in PHP 5, without having to pull your hair desperately, then hopefully this group of articles will give you the material you’re looking for.

By this time, you’re well aware of the goal of this article series, so I’d like to spend a few moments refreshing the concepts I explained in the previous part. In that article, I developed a basic loader class which was capable of including a specified file without having to create any instances of the class. This capacity was implemented by defining a static loading method, which was in reality the class’s workhorse, since it acted like a wrapper for the “require_once()” PHP function.

While this file loading class in its current incarnation does a pretty good job, it lacks an important feature that could be added with relative ease. It cannot perform a recursive search through the web server’s file system, and afterward include a specified file within a given application.

Essentially, the class would be passed a starting path to look for, and from that point onward it would recursively traverse the subfolders, until finding the targeted file. That’s an ability found in many popular PHP applications available nowadays, and in the next few lines I’m going to explain how to implement it, based mostly on the structure of the loader class created in previous chapter of the series.

Now, let’s start learning how to build a loading class that will have recursive file searching capabilities. Let’s get going!

At this point, I’m sure you want to learn how to build a file loading class with recursive searching capabilities. However, before we do that, it would be helpful to quickly recall the definition and usage of the “Loader” class developed in the preceding part of the series, so you can compare it with the one that I plan to create.

Below I listed the full source code of the previous loader class, accompanied by a short example that shows how to work with it. First, here’s the signature of the “Loader” class:

// define the loader class (the ‘load()’ method is declared static)

class Loader

{

// constructor (not implemented)

public function __construct(){}

// load specified file

public static function load($filepath)

{

if (!file_exists($filepath))

{

throw new Exception(‘The specified file cannot be found!’);

}

require_once($filepath);

}

}

Next, we’ll reintroduce the two sample files that will be included by the class. Here they are:

(‘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 finally, here’s a small code snippet that shows the “Loader” class in action, using its static “load()” method:

<?php

try

{

// call ‘load()’ method statically and load specified files

Loader::load(‘sample_file1.php’);

Loader::load(‘sample_file2.php’);

/* displays the following

This file has been loaded with the Loader class.

This file has been loaded at the following time 11:37:09

*/

}

catch (Exception $e)

{

echo $e->getMessage();

exit();

}

?>

From the code sample shown above, it’s clear to see how simple the logic is that is implemented by the pertinent “Loader()” class. All it does is include a specified file via its static “load()” method, which is merely a proxy for the native “require_once()” PHP function.

In general terms, due to its basic structure, this class could be considered a file loader helper, rather than a core library of a fictional framework. Of course, as you might have imagined, it’s perfectly feasible to use the skeleton of the class and construct a more advanced and complex version of it, capable of searching recursively targeted files and including them inside a PHP application.

That’s exactly what I’m going to do in the course of the following section: build a recursive file loader class. So, if you want to learn the full details of this process, click on the link that appears below and keep reading.

As I stated in the previous segment, it’s possible to build a file loading class that has the ability to look for a targeted file recursively. To create a class with this capability, first I’m going to define its basic structure along with a few setter and getter methods, which will be responsible for setting and getting the file for which to search, and for performing the same tasks with the starting file path.

If this brief description sounds a bit confusing to you, the following code sample should help to dissipate your doubts. Take a look at it:

// 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;

}

}

As you can see, the above “Loader()” class has some simple methods, apart from the constructor, for setting and getting the file that needs to be included, and for establishing and retrieving the path from which to start searching the file.

These setters and getters are very easy to understand, so I’m not going to spend more time discussing how they work. But wait a minute! Didn’t I say at the beginning of this section that my purpose here was building a file loader class that is capable of including a specified file through a recursive search? Yes, I did.

But this functionality needs to be implemented by means of a separate method, which not surprisingly will be called “load().”

Therefore, to see how this whole new method will be properly defined, read the next section.

{mospagebreak title=Defining the recursive load() method}

In reality, building a method that recursively traverses the file system and includes a specified file doesn’t differ too much from defining other common recursive search methods that you’ve probably coded many times before.

This concept will be better understood if you look at the “load()” method below, which performs the aforementioned recursive search in a straightforward manner:

// 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);

}

}

}

As usual, coding recursive methods and functions is a pretty tricky process, and the “load()” method isn’t an exception. However, its flow of execution is quite simple to follow. If the targeted file is found, then it’s included directly via the “require_once()” function. Otherwise, a recursive search is performed through the web server’s file system, starting from the specified path.

Having explained how the “load()” method functions, it’s time to show the full source code of the “Loader()” class, this time including the signature of the method in question. Here it is:

<?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);

}

}

}

}

So far, so good, right? At this stage, you’ve learned how to build a loader class that’s capable of recursively searching a determined file based on a supplied path and including it if it’s found.

Logically, the last thing that remains undone is developing a example application that shows how to use the class in a concrete case. But this will be done in the next article of the series. Meanwhile, feel free to tweak the “Loader” class’ source code, and try to introduce into it your own enhancements.

Final thoughts

That’s all for now. In this third installment of the series, I discussed the progressive development a file loading class, which had the ability to include a specified file through a recursive search.

Naturally, the class can be improved, particularly when it comes to refactoring its “load()” core method, but this topic will be covered in more detail in upcoming articles of the series.

In the forthcoming tutorial, I’m going to set up some illustrative examples, so you’ll be able to see how the previous “Loader” class does its business.