Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
PHP 7 Programming Cookbook

You're reading from   PHP 7 Programming Cookbook Over 80 recipes that will take your PHP 7 web development skills to the next level!

Arrow left icon
Product type Paperback
Published in Aug 2016
Publisher Packt
ISBN-13 9781785883446
Length 610 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Doug Bierer Doug Bierer
Author Profile Icon Doug Bierer
Doug Bierer
Arrow right icon
View More author details
Toc

Table of Contents (16) Chapters Close

Preface 1. Building a Foundation FREE CHAPTER 2. Using PHP 7 High Performance Features 3. Working with PHP Functional Programming 4. Working with PHP Object-Oriented Programming 5. Interacting with a Database 6. Building Scalable Websites 7. Accessing Web Services 8. Working with Date/Time and International Aspects 9. Developing Middleware 10. Looking at Advanced Algorithms 11. Implementing Software Design Patterns 12. Improving Web Security 13. Best Practices, Testing, and Debugging A. Defining PSR-7 Classes Index

Implementing class autoloading

When developing PHP using an object-oriented programming (OOP) approach, the recommendation is to place each class in its own file. The advantage of following this recommendation is the ease of long-term maintenance and improved readability. The disadvantage is that each class definition file must be included (that is, using include or its variants). To address this issue, there is a mechanism built into the PHP language that will autoload any class that has not already been specifically included.

Getting ready

The minimum requirement for PHP autoloading is to define a global __autoload() function. This is a magic function called automatically by the PHP engine when a class is requested but where said class has not been included. The name of the requested class will appear as a parameter when __autoload() is invoked (assuming that you have defined it!). If you are using PHP namespaces, the full namespaced name of the class will be passed. Because __autoload() is a function, it must be in the global namespace; however, there are limitations on its use. Accordingly, in this recipe, we will make use of the spl_autoload_register() function, which gives us more flexibility.

How to do it...

  1. The class we will cover in this recipe is Application\Autoload\Loader. In order to take advantage of the relationship between PHP namespaces and autoloading, we name the file Loader.php and place it in the /path/to/cookbook/files/Application/Autoload folder.
  2. The first method we will present simply loads a file. We use file_exists() to check before running require_once(). The reason for this is that if the file is not found, require_once() will generate a fatal error that cannot be caught using PHP 7's new error handling capabilities:
    protected static function loadFile($file)
    {
        if (file_exists($file)) {
            require_once $file;
            return TRUE;
        }
        return FALSE;
    }
  3. We can then test the return value of loadFile() in the calling program and loop through a list of alternate directories before throwing an Exception if it's ultimately unable to load the file.

    Tip

    You will notice that the methods and properties in this class are static. This gives us greater flexibility when registering the autoloading method, and also lets us treat the Loader class like a Singleton.

  4. Next, we define the method that calls loadFile() and actually performs the logic to locate the file based on the namespaced classname. This method derives a filename by converting the PHP namespace separator \ into the directory separator appropriate for this server and appending .php:
    public static function autoLoad($class)
    {
        $success = FALSE;
        $fn = str_replace('\\', DIRECTORY_SEPARATOR, $class) 
              . '.php';
        foreach (self::$dirs as $start) {
            $file = $start . DIRECTORY_SEPARATOR . $fn;
            if (self::loadFile($file)) {
                $success = TRUE;
                break;
            }
        }
        if (!$success) {
            if (!self::loadFile(__DIR__ 
                . DIRECTORY_SEPARATOR . $fn)) {
                throw new \Exception(
                    self::UNABLE_TO_LOAD . ' ' . $class);
            }
        }
        return $success;
    }
  5. Next, the method loops through an array of directories we call self::$dirs, using each directory as a starting point for the derived filename. If not successful, as a last resort, the method attempts to load the file from the current directory. If even that is not successful, an Exception is thrown.
  6. Next, we need a method that can add more directories to our list of directories to test. Notice that if the value provided is an array, array_merge() is used. Otherwise, we simply add the directory string to the self::$dirs array:
    public static function addDirs($dirs)
    {
        if (is_array($dirs)) {
            self::$dirs = array_merge(self::$dirs, $dirs);
        } else {
            self::$dirs[] = $dirs;
        }
    }  
  7. Then, we come to the most important part; we need to register our autoload() method as a Standard PHP Library (SPL) autoloader. This is accomplished using spl_autoload_register() with the init() method:
    public static function init($dirs = array())
    {
        if ($dirs) {
            self::addDirs($dirs);
        }
        if (self::$registered == 0) {
            spl_autoload_register(__CLASS__ . '::autoload');
            self::$registered++;
        }
    }
  8. At this point, we can define __construct(), which calls self::init($dirs). This allows us to also create an instance of Loader if desired:
    public function __construct($dirs = array())
    {
        self::init($dirs);
    }

How it works...

In order to use the autoloader class that we just defined, you will need to require Loader.php. If your namespace files are located in a directory other than the current one, you should also run Loader::init() and supply additional directory paths.

In order to make sure the autoloader works, we'll also need a test class. Here is a definition of /path/to/cookbook/files/Application/Test/TestClass.php:

<?php
namespace Application\Test;
class TestClass
{
    public function getTest()
    {
        return __METHOD__;
    }
}

Now create a sample chap_01_autoload_test.php code file to test the autoloader:

<?php
require __DIR__ . '/../Application/Autoload/Loader.php';
Application\Autoload\Loader::init(__DIR__ . '/..');

Next, get an instance of a class that has not already been loaded:

$test = new Application\Test\TestClass();
echo $test->getTest();

Finally, try to get a fake class that does not exist. Note that this will throw an error:

$fake = new Application\Test\FakeClass();
echo $fake->getTest();
You have been reading a chapter from
PHP 7 Programming Cookbook
Published in: Aug 2016
Publisher: Packt
ISBN-13: 9781785883446
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image