Establishing a reference point: listing the complete source files of the previous database-driven application Before I show you how to improve the current signature of the “__autoload()” magic function, I want to list the definitions corresponding to all the source files that make up the sample database-driven application built in the previous article of the series. This will help you recall how it behaves when one of its classes can’t be included into client code. As you’ll probably remember, the primary goal of this basic application was fetching some rows from a “Users” MySQL database table, which were displayed on the browser later on. Naturally, the reason for coding this small program was simply to demonstrate the different behaviors shown by the “__autoload()” function when, for any reason, one of the pertinent source classes can’t be loaded as expected. That being said, here are the complete definitions of the files that comprise this primitive database-driven application, so take some time and have a close look at them, please: (definition of mysql.php file) 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); } } (definition of result.php file) 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; } } (definition of autoload_example.php file) try{ function __autoload($className){ if(!file_exists($className.'.php')){ return eval("class {$className}{public function __construct(){throw new } require_once $className.'.php'; } // connect to MySQL $db=new MySQL(array // 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 } } catch (Exception $e){ echo $e->getMessage(); exit(); } As illustrated previously, this basic database-driven application is composed of three source files. The first two are responsible for containing the “MySQL” and “Result” classes required to work correctly. The last one, which I called “autoload_example.php,” is tasked with retrieving user data from the pertinent database table. In addition, this file implements the “__autoload()” magic function to automate the process for loading the corresponding source classes. But undoubtedly, the most important thing to stress here is how the function works. When one of the source classes can’t be included into client code, it throws a “Class not found” exception, which is happily intercepted by the pertinent “try-catch()” block. So far, so good. At this stage the “__autoload()” function does a decent job of loading all the source classes required by this sample application. Nonetheless, I have to admit that all the exceptions thrown by this function aren’t very descriptive. Indeed, a laconic “Class not found” error message wouldn’t give you a clear clue of which class failed to load, right? Therefore, since this limitation exposed by the “__autoload()” function can be addressed with minor efforts, in the next section I’m going to show you how to incorporate some modifications to the function in question. These changes will enable the function to trigger indicative error messages when something goes wrong. To see how these changes will be incorporated into the current signature of this handy function, please jump forward and read the next few lines. I’ll be there, waiting for you.
blog comments powered by Disqus |
|
|
|
|
|
|
|