Eldre PHP-applikasjoner er ofte include-basert. Det vil si at include, include_once, require og require_once brukes for å laste klassedefinisjoner inn i minnet:

Her er et eksempel på legacy PHP-kode som inkluderer klasser manuelt og ikke bruker namespaces.

<?php
// File: show_users.php

require 'classes/Page.php';
require 'classes/User.php';
require 'classes/Html.php';            
require 'classes/http/Cookie.php';
require 'classes/helpers/Utils.php';

$page = new Page('show_users');

print $page->render();

Med mange sider og mange klasser blir det fort slitsomt og støyende med manuell inkludering av klasser. I moderne PHP kan vi nå registrere en autolaster som automatisk inkluderer klasser når de brukes.

Classmap

I et classmap er alle klasser oppført med en peker til sin fil.

<?php
// File: autoload.php

spl_autoload_register(function ($class) {

    $classMap = [
        'Page'      => 'classes/Page.php',
        'User'      => 'classes/User.php',
        'Html'      => 'classes/Html.php',
        'Cookie'    => 'classes/http/Cookie.php',
        'Utils'     => 'classes/helpers/Utils.php',
    ];

    require $classMap[$class];
});

Hver gang et objekt konstrueres vil PHP kalle på vår autolaster og gi den en sjanse til å inkludere riktig fil.

Ved å opprette en instans av Page vil autolasteren inkludere fila classes/Page.php.

For å registrere autolasteren inkluderer vi den helt øverst og fjerner alle andre inkluderinger av klasser:

<?php
// File: show_users.php

require 'autoload.php';

$page = new Page;

print $page->render();

Dette classmappet er manuelt konstruert og må oppdateres hver gang en ny klasse lages. Det fins verktøy som automatiserer prosessen ved å f.eks. rekursivt skanne hele classes/ mappa.

Hvis vi samler alle klasser direkte under classes/ vil en enkel autolaster som denne holde:

<?php
// File: autoload.php

spl_autoload_register(function ($class) {
    require 'classes/' . $class . '.php';
});

PSR-0

PSR-0 er en (DEPRECATED) bransjeanbefaling for hvordan strukturere klassefiler og namespaces.

I denne standarden blir namespaceseparatoren erstattet mappeseparator og understreker i klassenavnet blir også erstattet med mappeseparator. Resultatet blir prefikset med en basemappe og suffikset med .php.

For eksempel:

Page                => src/Page.php
My_Page             => src/My/Page.php
Vikan\Cookie        => src/Vikan/Cookie.php
Vikan\Blog\My_Page  => src/Vikan/Blog/My/Page.php

PSR-0 tillater klasser uten namespaces. De to første eksemplene er klasser som ikke lever i et namespace. Namespaces kom i PHP 5.3 (2009). Eldre kode brukte understrek som konvensjon for å signalisere namespace.

Her er PHP FIG sin eksempel implementasjon:

<?php

function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
}

PSR-4

PSR-4 er en nyere bransjestandard som deprecater PSR-0.

De to største forskjellene i forhold til PSR-0:

  • Ikke støtte for PEAR-style pseudo-namespaces: Foo_Bar_Baz
  • Forenklet mappestruktur som forkorter mappestrukturene

Med PSR-0/PSR-4 standard der namespacet Vendor\\Application\\ er koblet til src blir de respektive mappestrukturene slik:

Vendor\Application\Cookie: src/Vendor/Application/Cookie.php # PSR-0
Vendor\Application\Cookie: src/Cookie.php # PSR-4

Også PSR-4 fungerer med klasser som ikke er namespacet.

Composer

Composer er en dependency manager som støtter de fleste autolasting strategier.

composer.json:

{
    "autoload": {
        "classmap": ["classes"],
  
        "psr-0": {
            "Vendor\\Application\\": "classes"
        },
  
        "psr-4": {
            "Vendor\\Application\\": "classes"
        },

        "files": ["src/MyLibrary/functions.php"]
    }
}

For å generere autolasteren:

$ composer dump-autoload

Funksjoner uten namespace kan ikke autolastes men må inkluderes.

Hvis din kodebase ikke er namespacet gjør du f.eks. slik:

{
    "autoload": {
        "psr-0": {
            "": "classes"
        }
    }
}

Oppsummering

I en kodebase som ikke bruker namespaces lager du en mappe classes/ eller src/ og samler alle klasser der. Bruk PSR-0 autolasting.