Uma aplicação web consiste em muitas classes PHP, e cada classe normalmente fica em um arquivo separado. Isso introduz a necessidade de incluir os arquivos.
Por exemplo, vamos supor que temos o arquivo chamado Application.php
que contém a definição para a classe \Zend\Mvc\Application. Antes que você possa
criar uma instância da classe Application em algum lugar do seu código,
você tem que incluir o conteúdo do arquivo Application.php (você pode fazer isso com o
ajuda do require_once, passando o caminho completo para o arquivo):
<?php
require_once "/path/to/zendframework/zend-mvc/src/Application.php";
use Zend\Mvc\Application;
$application = new Application();
Porém a medida que seu aplicativo for crescendo, pode ser difícil incluir cada arquivo necessário. O próprio Zend Framework 3 consiste em centenas de arquivos, e pode ser muito difícil carregar todas as bibliotecas e toda a sua dependências dessa maneira. Além disso, ao executar o código, o PHP levar tempo para processar cada arquivo, mesmo se você não criar um instância nenhuma classe.
Para corrigir esse problema, no PHP, o recurso de autoloading de classes foi introduzido.
A função spl_autoload_register() permite que você registre
uma função autoloader. Para sites complexos, você ainda pode criar
várias funções do autoloader, que são encadeadas em pilha.
Durante a execução do script, se o PHP encontrar um nome de classe que ainda não foi definido, ele chama todas as funções de autoloader registradas, até que a função autoloader inclua a classe ou gere um erro "não encontrado". Isso permite o "lazy" loading, que é quando o PHP apenas processa a classe definição apenas no momento da invocação de classe, quando é realmente necessário.
Para ter uma ideia de como funciona uma função de autoloader, abaixo vamos apresentar uma implementação simplificada de uma função autoloader:
<?php
// Autoloader function.
function autoloadFunc($className) 
{
    // Class map static array.
    static $classMap = [
        '\\Zend\\Mvc\\Application' => '/path/to/zendframework/zend-mvc/src/Zend/Mvc/Application.php',
        '\\Application\\Module' => '/path/to/app/dir/module/Application/Module.php',
        //...
    ];
    // Check if such a class name presents in the class map.
    if(isset(static::$classMap[$className])) {
        $fileName = static::$classMap[$className];
  
        // Check if file exists and is readable.
        if (is_readable($fileName)) {
            // Include the file.
            require $fileName;
        }
    }
}
// Register our autoloader function.
spl_autoload_register("autoloadFunc");
No exemplo acima, nós definimos autoloadFunc() como uma  função de autoloader,
a qual nos referiremos a ela como class map autoloader.
O class map autoloader usa o class map para mapear entre o nome da classe e caminho absoluto para o arquivo PHP contendo essa classe. O class map é apenas um PHP normal array contendo chaves e valores. Para determinar o caminho do arquivo por nome de classe, class map autoloader só precisa buscar o valor do array. É óbvio que o autoloader do class map funciona muito rápido. No entanto, a desvantagem é que você tem que manter o class map atualizado e vai ter que você adicionar um novo classe para o seu programa toda vez que atualizá-lo.
Como cada biblioteca tem seu fornecedor e cada uma delas usa suas próprias convenções de código e organização de arquivos, você terá que registrar uma função autoloader diferente para cada biblioteca, o que é bastante irritante (e na verdade este é um trabalho desnecessário). Para resolver esse problema, o padrão PSR-4 foi introduzido.
PSR significa PHP Standards Recommendation..
O padrão PSR-4 define a estrutura de código recomendada que uma aplicação ou biblioteca deve seguir para garantir a interoperabilidade do autoloader. Em duas palavras, o padrão diz que:
Os namespaces da classe devem ser organizados da seguinte maneira:
\<Nome da biblioteca (Vendor) >\(<Namespace>)*\<Nome da Classe>
Os namespaces podem ter quantos níveis forem desejados mas o Vendor deve ser o primeiro nome.
Namespaces devem mapear a estrutura de diretórios. Cada separador de namespace ('\')
é convertido em uma constante DIRECTORY_SEPARATOR para que a OS do sistema carregue o arquivo.
O nome de classe tem que ter sufixo com .php quando os arquivos forem carregados pelo o sistema.
Por exemplo, para a classe Zend\Mvc\Application,
você terá a seguinte estrutura de pastas:
/path/to/zendframework/zend-mvc/src
  /Zend
    /Mvc
       Application.php
A desvantagem disso é que você precisa colocar seu código em vários pastas (Zend e Mvc).
Para corrigir isso, o PSR-4 permite que você defina que uma
uma série de um ou mais de namespace e sub namespace corresponde a um "diretório base".
Por exemplo, se você tiver o nome completo da classe \Zend\Mvc\Application e se você definir
a série \Zend\Mvc corresponde ao diretório "/path/to/zendframework/zend-mvc/src",
você pode organizar seus arquivos da seguinte forma:
/path/to/zendframework/zend-mvc/src
    Application.php
Para o código em conforme com o padrão PSR-4, podemos escrever e registrar um autoloader, ao qual nos referiremos como autoloader "padrão":
<?php
// "Standard" autoloader function.
function standardAutoloadFunc($className) 
{
    // Replace the namespace prefix with base directory.
    $prefix = '\\Zend\\Mvc';
    $baseDir = '/path/to/zendframework/zend-mvc/src/';
    if (substr($className, 0, strlen($prefix)) == $prefix) {
        $className = substr($className, strlen($prefix)+1);
        $className = $baseDir . $className;
    }
    // Replace namespace separators in class name with directory separators.
    $className = str_replace('\\', DIRECTORY_SEPARATOR, $className);
  
    // Add the .php extension.
    $fileName = $className . ".php";
  
    // Check if file exists and is readable.
    if (is_readable($fileName)) {
        // Include the file.
        require $fileName;
    } 
}
// Register the autoloader function.
spl_autoload_register("standardAutoloadFunc");
O padrão do autoloader funciona da seguinte maneira. Assumindo que a classe do namespace
possa ser mapeado para a estrutura de diretórios um por um, a função calcula
o caminho para o arquivo PHP, transformando back-slashes (separadores de namespace) em
barras (separadores de caminho) e concatenando o caminho resultante com
o caminho absoluto para o diretório no qual a biblioteca está localizada. Então o
função verifica se tal arquivo PHP realmente existe, e se assim for, inclui
com a declaração require.
É óbvio que o autoloader padrão funciona mais devagar que o class map autoloader. No entanto, sua vantagem é que você não precisa manter nenhum class map, o que é muito conveniente quando você desenvolve um novo código e adiciona novas classes sua aplicação.
Zend Framework 3 está dentro dos pardrões da PSR-4, tornando possível usar mecanismo de carregamento automático em todos os seus componentes. Também é compatível com outras blibiotecas que utilizam o padrão PSR-4 como o Doctrine ou o Symfony.
O Composer pode gerar funções de autoloader (mesmo padrão de carregament ode classes e padrão PSR-4) para o código que você instala com ele.
O Zend Framework 3 usa a implementação do autoloader fornecida pelo Composer. Quando você instala um pacote com
Composer, cria automaticamente o arquivo APP_DIR/vendor/autoload.php,
que usa a função PHP spl_autoload_register() para registrar um autoloader. Desta forma todas as classes PHP
localizado no diretório APP_DIR/vendor serão carregados automaticamente.
Para auto-carregar classes PHP do seus próprios módulos (como o módulo Application), você terá que especificar
o autoload no seu arquivo composer.json:
"autoload": {
    "psr-4": {
        "Application\\": "module/Application/src/"
    }
},
Então, a única coisa que precisa ser feita é incluir esse arquivo no script de entrada do seu site index.php:
// Composer autoloading
include __DIR__ . '/../vendor/autoload.php';
O arquivo autoload.php é gerado toda vez que você instala um pacote com o Composer. Além disso, para faz o Composer gerar o arquivo autoload.php, você pode precisar executar o comando
dump-autoload:
php composer.phar dump-autoload
No Zend Skeleton Application, você pode ver como o padrão PSR-4 é aplicado
na prática. Para o módulo padrão do seu site, o módulo Application, classes PHP que
são registrados com o autoloader padrão são armazenados sob o APP_DIR/module/Application/src
diretório (abreviação "src" significa "source (fonte)").
Vamos nos referir ao diretório
srccomo o diretório de origem do módulo.
Por exemplo, vamos dar uma olhada no arquivo IndexController.php do módulo Application (imagem 3.2).
Imagem 3.2. Estrutura de pastas do skelleton application conforme o padrão PSR-4
Como você pode ver, ele contém a classe IndexController 1 pertencente ao namespace Application\Controller.
Para poder seguir o padrão PSR-4 e usar o autoloader padrão com esta classe PHP,
temos que colocá-lo no diretório Controller dentro da pasta do módulo.
1) A classe IndexController é o controller padrão do skelleton application
Vamos falar sobre controllers mais adiante no capítulo Model-View-Controller.