Auto Loading Classes in PHP 5

Undoubtedly, the release of PHP 5 has had a remarkable impact on the way that object-oriented applications are developed nowadays. This highly-improved model has provided PHP programmers with features that were only present in mature object-based languages, like Java and C++, but now, fortunately for you and me, they are generously offered by this powerful server-side scripting language.

Of course, if you’ve been using PHP 5 for a while to build your object-oriented applications, then it’s likely that you’re already familiar with creating classes, defining their corresponding methods and properties, working with exceptions and interfaces, and so forth.

However, even when all of the features that I highlighted actually comprise the foundations of the so-called object-based paradigm, it’d be rather unfair not to mention other useful characteristics that come packaged with PHP 5, which can help facilitate the development of object-oriented projects.

Destructors and object deferencing are good examples of certain characteristics available in PHP 5, which can be extremely helpful when working with objects that need to be called when they no longer exist in the context of a given web application, or when a certain number of these objects must be chained with each other through their corresponding APIs.

Nevertheless, among the improvements introduced into the object model provided by PHP 5, there’s one in particular that can be considered a programmer’s best friend when using objects, due to its remarkable functionality. Do you think that I’m being too verbose here? Well, maybe, but this won’t stop me from telling you loud and clear the name of the improvement in question. Yes! You guessed right! In this case, I’m talking about the useful “__autoload()” PHP 5 magic function, which can be really magical when it comes to automatically loading all the class files required by a determined PHP application.

As you might know, the “__autoload()” function, when used in a clever way, can eliminate almost completely the need to use the “require()/require_once()” and “include()/include_once()” PHP native functions to load your nicely-crafted classes automatically during the execution of an object-oriented application. This certainly speaks for itself about the powerful capabilities offered through this function.

Personally, when I started “auto loading” all of my PHP 5 classes with this magic function, I realized that it was one of those things one can’t live without. Hopefully after you go through this series of articles, you’ll feel the same way.

Actually I’m getting ahead of myself, so now is the perfect time to move forward and start learning how to put the “__autoload()” magic function to work for you, and load your classes without having to include them manually into your PHP 5 object-oriented applications. It’s going to be an educational experience. Believe me!

{mospagebreak title=Traditional Approach}

Loading PHP 5 classes using a traditional approach: developing an illustrative example

An adequate place to start demonstrating how the “__autoload()” PHP 5 magic function works is by developing a simple database-driven application, where all of the classes required by the application in question are loaded into client code by using a couple of “require_once()” functions.

By creating this “conventional” sample application, you’ll have at your disposal an excellent point of reference for comparing the pros and cons of using this approach with utilizing one that implements the mentioned “__autoload()” function.

Having clarified this point, suppose that there’s a MySQL database table that has been populated with some basic data about a few fictional users, which needs to be displayed on the browser. To perform this process as easily as possible, I’ll use two different MySQL handling classes that will reside in different files.

In this case, the first class, called “MySQL,” was previously stored on a “mysql.php” file. It has the following signature:


class MySQL{

private $host;

private $user;

private $password;

private $database;

private $connId;

// constructor

function __construct($options=array()){

if(!is_array($options)){

throw new Exception(‘Connection options must be an array’);

}

foreach($options as $option=>$value){

if(empty($option)){

throw new Exception(‘Connection parameter cannot be empty’);

}

$this->{$option}=$value;

}

$this->connectDb();

}

// private ‘connectDb()’ method

private function connectDb(){

if(!$this->connId=mysql_connect($this->host,$this->user,$this->password)){

throw new Exception(‘Error connecting to MySQL’);

}

if(!mysql_select_db($this->database,$this->connId)){

throw new Exception(‘Error selecting database’);

}

}

// public ‘query()’ method

public function query($sql){

if(!$result=mysql_query($sql)){

throw new Exception(‘Error running query ‘.$sql.’ ‘.mysql_error());

}

return new Result($this,$result);

}

}


You might find the definition of the above “MySQL” class quite familiar, since I used it in some of my previous articles on PHP development. As you can see, this class defines a group of methods for connecting to the pertinent database server, as well as for performing queries against one or more tables. So far, the signature of this class is not rocket science at all.

{mospagebreak title=Traditional Approach continued}

However, the point to stress in this case is that the prior class resides in a separate file, called “mysql.php,” which should be included manually into this sample application via a "require_once()" PHP function. Also, to make the application work as expected, I’m going to define an additional class, called “Result,” which will reside in a different file called “result.php.” It will look like this:


class Result{

private $mysql;

private $result;

// constructor

public function __construct($mysql,$result){

$this->mysql=$mysql;

$this->result=$result;

}

// public ‘fetch()’ method

public function fetch(){

return mysql_fetch_array($this->result,MYSQL_ASSOC);

}

// public ‘count()’ method

public function count(){

if(!$rows=mysql_num_rows($this->result)){

throw new Exception(‘Error counting rows’);

}

return $rows;

}

// public ‘get_insertId()’ method

public function getInsertId(){

if(!$insId=mysql_insert_id($this->mysql->connId)){

throw new Exception(‘Error getting insert ID’);

}

return $insId;

}

// public ‘seek()’ method

public function seek($row){

if(!int($row)&&$row<0){

throw new Exception(‘Invalid row parameter’);

}

if(!$row=mysql_data_seek($this->mysql->connId,$row)){

throw new Exception(‘Error seeking row’);

}

return $row;

}

// public ‘getAffectedRows()’ method

public function getAffectedRows(){

if(!$rows=mysql_affected_rows($this->mysql->connId)){

throw new Exception(‘Error counting affected rows’);

}

return $rows;

}

}


As you can see, the above “Result” class comes in handy for processing MySQL result-sets in all sorts of clever ways. And it’s capable of doing some interesting things, like fetching and counting the rows returned in a data set, determining the ID of a particular insert operation, etc. It’s nothing too complex, actually.

Besides, as I said before, this class is stored in a “result.php” file, which should be included in this sample database-driven application via a “require_once()” function, as you’ve possibly done hundreds of times before.

So, having showed you the respective definitions of the two previous MySQL handling classes, I want to fetch a few database records from a basic “Users” table and display them on the browser. The following script should do the job quite decently:


try{

// include required classes

require_once ‘mysql.php';

require_once ‘result.php';

// connect to MySQL

$db=new MySQL(array
(‘host’=>’host’,’user’=>’user’,’password’=>’password’,
‘database’=>’database’));

// fetch users from database table

$result=$db->query(‘SELECT * FROM users ORDER BY id’);

// display user data

while($row=$result->fetch()){

echo ‘Id: ‘.$row['id'].’ First Name: ‘.$row['firstname'].’ Last Name: ‘.$row
['lastname'].’ Email: ‘.$row['email'].'<br />';

}

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


In this case, the above script will display some basic data about a few fictional users, including their first and last names, by using the pair of MySQL processing classes that you learned before. Nonetheless, the most important thing to highlight here is that the classes are loaded “manually” by using the popular “require_once()” PHP native function. This is a process that should be familiar to you.

So far, I’ve recreated a hypothetical situation where the classes required by a certain database-driven application are included manually into client code via a couple of “require_once()” functions.

Now that you’ve seen how this simple process is achieved, it’s time to take a close look at the handy “__autoload()” PHP 5 magic function. As you’ll see in a few moments, it will allow you to load the previous classes “automatically" and logically without having to use any “require_once()” statements.

To learn how this handy function will be used in the context of the prior database-driven application, please click on the link below and keep reading.

{mospagebreak title=Using the Magic Function}

Loading classes automatically: taking a first look at the “__autoload()” PHP 5 magic function

As I explained in the previous section, PHP 5 comes equipped with the “__autoload()” magic function for automatically including all of the source classes required by a specific application into client code. In others words, the PHP 5 interpreter will simply invoke this function automatically when a determined script attempts to utilize a class that hadn’t been defined previously.

This means that it’s possible to implement this function in such a way that it includes the source file of a given class when not available. Sounds rather confusing, doesn’t it? Well, fear not. In order to clarify how the “__autoload()” function works, below I rewrote the script that you saw in the prior section, this time using the mentioned function.

Please, have a close look at the following code sample:


// include required classes using the magic ‘__autoload()’ function

function __autoload($className){

require_once $className.’.php';

}

try{

// connect to MySQL

$db=new MySQL(array
(‘host’=>’host’,’user’=>’user’,’password’=>’password’,
‘database’=>’database’));

// fetch users from database table

$result=$db->query(‘SELECT * FROM users ORDER BY id’);

// display user data

while($row=$result->fetch()){

echo ‘Id: ‘.$row['id'].’ First Name: ‘.$row['firstname'].’ Last Name: ‘.$row
['lastname'].’ Email: ‘.$row['email'].'<br />';

}

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


If you study in detail the above example, you’ll understand very easily how the  “__autoload()” PHP function does its business. As you can see, in this case the function in question will try to include two different files, called “mysql.php” and “result.php” respectively, whenever the pertinent definitions of the “MySQL” and “Result” classes are required by this sample database-driven application. In this way it implements a powerful mechanism for loading all the source classes demanded by a certain script.

Of course, the major benefit of using this function is that’s no longer necessary to use a PHP include for each class that needs to be utilized. The “__autoload()” function will perform this task behind the scenes, so you won’t have to be concerned about this process. Pretty useful, right?

Besides, it’s easy to see that all the scripts that work with this function will obviously need to implement it concretely. This can be a bit annoying, but I think that you’ll be more than happy using it within your PHP 5-based applications.

Now that you’ve hopefully grasped the logic in utilizing the “__autoload()” PHP 5 magic function, it’s time to read the last section of this tutorial, where I’ll be listing the complete definitions of the two practical examples that I developed earlier. You can evaluate adequately the pros and cons in loading source classes with conventional includes and with the “__autoload()” function.

Go ahead and read the next few lines. I’ll be there, waiting for you.

{mospagebreak title=Comparing the two}

Comparing two different approaches for loading source classes: listing the previous code samples

As I promised in the previous section, here is the complete source code corresponding to the two examples that you learned earlier, where the first one uses conventional PHP includes to load the pertinent “MySQL” and “Result” classes, and the second one utilizes the handy “__autoload()” function:


(example using conventional PHP includes)


try{

// include required classes

require_once ‘mysql.php';

require_once ‘result.php';

// connect to MySQL

$db=new MySQL(array
(‘host’=>’host’,’user’=>’user’,’password’=>’password’,
‘database’=>’database’));

// fetch users from database table

$result=$db->query(‘SELECT * FROM users ORDER BY id’);

// display user data

while($row=$result->fetch()){

echo ‘Id: ‘.$row['id'].’ First Name: ‘.$row['firstname'].’ Last Name: ‘.$row
['lastname'].’ Email: ‘.$row['email'].'<br />';

}

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


// example using the magic ‘__autoload()’ function


function __autoload($className){

require_once $className.’.php';

}

try{

// connect to MySQL

$db=new MySQL(array
(‘host’=>’host’,’user’=>’user’,’password’=>’password’,
‘database’=>’database’));

// fetch users from database table

$result=$db->query(‘SELECT * FROM users ORDER BY id’);

// display user data

while($row=$result->fetch()){

echo ‘Id: ‘.$row['id'].’ First Name: ‘.$row['firstname'].’ Last Name: ‘.$row
['lastname'].’ Email: ‘.$row['email'].'<br />';

}

}

catch(Exception $e){

echo $e->getMessage();

exit();

}


From this point on, it’s up to you decide which approach fits your specific needs better when it comes to loading all the source classes required by a specific PHP 5 application. I’ve been using the “__autoload()” magic function for one year or so, and I consider it a superior option over common PHP includes.


Final thoughts

In this initial article of the series, I introduced the basics of using the “__autoload()” magic function that comes bundled with PHP 5. As you saw, it can be really useful for loading automatically all the source classes required by a given application.

However, this function has an important downside, since any exception thrown when attempting to load a concrete class simply can’t be caught inside a “try-catch” block. However, there are some workarounds that come in handy for solving this issue. And I’ll be showing them in the next part of the series.

Now that you’ve been warned, you won’t want to miss it!

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye