Generally it's a good idea to keep our classes in separate script files, one class per file. It also helps to name each class file after the class it contains. For example, we might create a class called Person and store it in a file called Person.php inside a classes folder (so that we know that Person.php contains a class). Or if we have created a class called Fruit, we might store it in a file called class.Fruit.php.
Then, when our script needs to create a Person object, it can include the Person.php file to create the class, then go ahead and create an object from the class:
<?php
require_once( "classes/Person.php" );
$p = new Person();
?>
require_once() lets us include one PHP script file inside another, which means we can break up our PHP application into small, manageable script files. Not only does this good practice help to keep our scripts organized and maintainable, but it lets us take advantage of a nifty feature of PHP: class autoloading.
With autoloading, we create an __autoload() function somewhere in our script. This function should accept a class name as an argument. Then, whenever another part of our script attempts to create a new object from a nonexistent class, __autoload() is automatically called, passing in the class name. This gives our __autoload() function a chance to find and include the class file, thereby allowing the PHP engine to carry on and create the object.
Here's an example __autoload() function:
function __autoload( $className ) {
$className = str_replace ( "..", "", $className );
require_once( "classes/$className.php" );
}
This function stores the name of the nonexistent class in a $className parameter. It then filters this parameter to ensure it contains no ".." substrings (which could potentially be used by an attacker to open files or folders above the classes folder). Finally, it calls PHP's require_once() function to load the file in the classes folder with the same name as the missing class. This should cause the class to be created, allowing the object in turn to be created from the class.
For example, imagine the same script contained the following code:
$p = new Person;
When the PHP engine encounters the new Person construct, it looks to see if the Person class has been defined. If not, it calls the previously defined __autoload() function. This in turn includes and runs the file Person.php inside the classes folder, which creates the class and allows the new Person object to be created.
If the PHP engine can't find an __autoload() function, or if our __autoload() function fails to load the Person class, the script exits with a "Class 'Person' not found" error.
spl_autoload_register()
The major drawback to the __autoload() function is that we can only provide one autoloader with it. PHP 5.1.2 introduced spl_autoload() which allows us to register multiple autoloader functions, and in the future the __autoload() function will be deprecated.
The introduction of spl_autoload_register() gave us (programmers) the ability to create an autoload chain, a series of functions that can be called to try and load a class or interface. For example:
<?php
function autoloadRegister($className) {
$filename = "class/register/" . $className . ".php";
if (is_readable($filename)) {
require $filename;
}
}
function autoloadPerson($className) {
$filename = "class/person/" . $className . ".php";
if (is_readable($filename)) {
require $filename;
}
}
spl_autoload_register("autoloadRegister");
spl_autoload_register("autoloadPerson");
Generally the functions are called in the order they’re registered, but the order can also be affected by additional arguments passed to spl_autoload_register(). It’s important to remember that once a function has been registered with spl_autoload_register(), the __autoload() function will no longer be called. If we have an __autoload() function we want to run as part of our autoloader chain, then we’ll have to register it with spl_autoload_register().
Then, when our script needs to create a Person object, it can include the Person.php file to create the class, then go ahead and create an object from the class:
<?php
require_once( "classes/Person.php" );
$p = new Person();
?>
require_once() lets us include one PHP script file inside another, which means we can break up our PHP application into small, manageable script files. Not only does this good practice help to keep our scripts organized and maintainable, but it lets us take advantage of a nifty feature of PHP: class autoloading.
With autoloading, we create an __autoload() function somewhere in our script. This function should accept a class name as an argument. Then, whenever another part of our script attempts to create a new object from a nonexistent class, __autoload() is automatically called, passing in the class name. This gives our __autoload() function a chance to find and include the class file, thereby allowing the PHP engine to carry on and create the object.
Here's an example __autoload() function:
function __autoload( $className ) {
$className = str_replace ( "..", "", $className );
require_once( "classes/$className.php" );
}
This function stores the name of the nonexistent class in a $className parameter. It then filters this parameter to ensure it contains no ".." substrings (which could potentially be used by an attacker to open files or folders above the classes folder). Finally, it calls PHP's require_once() function to load the file in the classes folder with the same name as the missing class. This should cause the class to be created, allowing the object in turn to be created from the class.
For example, imagine the same script contained the following code:
$p = new Person;
When the PHP engine encounters the new Person construct, it looks to see if the Person class has been defined. If not, it calls the previously defined __autoload() function. This in turn includes and runs the file Person.php inside the classes folder, which creates the class and allows the new Person object to be created.
If the PHP engine can't find an __autoload() function, or if our __autoload() function fails to load the Person class, the script exits with a "Class 'Person' not found" error.
spl_autoload_register()
The major drawback to the __autoload() function is that we can only provide one autoloader with it. PHP 5.1.2 introduced spl_autoload() which allows us to register multiple autoloader functions, and in the future the __autoload() function will be deprecated.
The introduction of spl_autoload_register() gave us (programmers) the ability to create an autoload chain, a series of functions that can be called to try and load a class or interface. For example:
<?php
function autoloadRegister($className) {
$filename = "class/register/" . $className . ".php";
if (is_readable($filename)) {
require $filename;
}
}
function autoloadPerson($className) {
$filename = "class/person/" . $className . ".php";
if (is_readable($filename)) {
require $filename;
}
}
spl_autoload_register("autoloadRegister");
spl_autoload_register("autoloadPerson");
Generally the functions are called in the order they’re registered, but the order can also be affected by additional arguments passed to spl_autoload_register(). It’s important to remember that once a function has been registered with spl_autoload_register(), the __autoload() function will no longer be called. If we have an __autoload() function we want to run as part of our autoloader chain, then we’ll have to register it with spl_autoload_register().
No comments:
Post a Comment