Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
203 lines (148 sloc) 5.54 KB

PSR-0 Autoloading

In this practical, you are going to create a PSR-0 compliant autoloader.

Definition

The following describes the mandatory requirements that must be adhered to for autoloader interoperability.

Mandatory

  • A fully-qualified namespace and class must have the following structure \<Vendor Name>\(<Namespace>\)*<Class Name>
  • Each namespace must have a top-level namespace ("Vendor Name").
  • Each namespace can have as many sub-namespaces as it wishes.
  • Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system.
  • Each _ character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR. The _ character has no special meaning in the namespace.
  • The fully-qualified namespace and class is suffixed with .php when loading from the file system.
  • Alphabetic characters in vendor names, namespaces, and class names may be of any combination of lower case and upper case.

Examples

  • \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
  • \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
  • \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
  • \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

Underscores in Namespaces and Class Names

  • \namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
  • \namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

The standards we set here should be the lowest common denominator for painless autoloader interoperability. You can test that you are following these standards by utilizing this sample SplClassLoader implementation which is able to load PHP 5.3 classes.

Overview

Four steps to achieve your goal:

  • implement autoloading from cache;
  • implement autoloading from namespace;
  • implement autoloading using underscore notation;
  • register the discovered classes in cache and dump it.

Get the code:

$ mkdir -p ~/php/tp2-1
$ cd !$ # go to new created directory
$ wget https://raw.github.com/willdurand-edu/php-practicals/master/files/psr0.tgz
$ tar xvfz psr0.tgz
$ rm psr0.tgz
$ cd psr0

Running the tree command should display the following:

.
├── generate.php
├── test.php
├── test_cache.php
├── test_namespace.php
├── test_underscore.php
└── vendor
    ├── Coffee
    │   ├── Bali.php
    │   ├── BlueMontain.php
    │   └── Sumatra.php
    ├── Soda
    │   ├── Juice
    │   │   ├── Orange.php
    │   │   └── Pineapple.php
    │   └── Lemonade.php
    ├── Wine
    │   ├── Bordeaux.php
    │   └── Chinon.php
    ├── autoload.php
    ├── autoload_cache.php
    ├── autoload_namespace.php
    └── autoload_underscore.php

Every class under vendor/ directory prints its name in the constructor:

<?php

class Foo
{
    public function __construct($log = true)
    {
        if ($log) {
            printf("%s\n", get_class($this));
        }
    }
}

Step 1: Register A New Autoloader

The SPL allows you to register a custom autoloader through the spl_autoload_register() and spl_autoload_unregister() methods. This part will be tested thanks to the test_cache.php script.

Register a closure as an autoloader in vendor/autoload_cache.php. The closure MUST use the following associative array:

$autoload_map = [
    'Coffee\Bali'        => 'Coffee/Bali.php',
    'Coffee\BlueMontain' => 'Coffee/BlueMontain.php',
    'Coffee\Sumatra'     => 'Coffee/Sumatra.php',
    'Soda\Lemonade'      => 'Soda/Lemonade.php',
    'Soda\Juice\Orange'  => 'Soda/Juice/Orange.php',
    'Wine\Bordeaux'      => 'Wine/Bordeaux.php',
    'Wine\Chinon'        => 'Wine/Chinon.php',
];

Now, test your code:

$ php test_cache.php

You should see:

Coffee\Bali
Coffee\BlueMontain
Coffee\Sumatra
Soda\Lemonade
Soda\Juice\Orange
Wine\Bordeaux
Wine\Chinon

Step 2: Guess Path From Namespace

Fix the vendor/autoload_namespace.php file to load classes based on namespaces.

Test your code:

$ php test_namespace.php

You should see:

Coffee\Bali
Coffee\BlueMontain
Coffee\Sumatra
Soda\Lemonade
Soda\Juice\Orange
Wine\Bordeaux
Wine\Chinon

Step 3: Load SnakeCase'd Class Names

Fix the vendor/autoload_underscore.php file to successfully execute test_underscore.php.

Hint: Don't Repeat Yourself (DRY), in other words, reuse the work that has been done before.

Then again, test your code by running:

$ php test_underscore.php

You should see:

Soda\Juice\Pineapple

Step 4: Combine'em All

Fix the vendor/autoload.php file in order to fully comply to PSR-0.

The following steps SHOULD be executed:

  • Load cache file;
  • check whether the class is already in cache, if so load it;
  • find class in definition map and add it to the cache;
  • save cache array in vendor/cache.php using the var_export() method.

You can jump to: Practical Work #2 - Part 2.