RobotLoader: autoloading de classes
RobotLoader é uma ferramenta que garante o conforto do carregamento automático de classes para toda a sua aplicação, incluindo bibliotecas de terceiros.
- livramo-nos de todos os
require
- apenas os scripts necessários serão carregados
- não requer convenções estritas de nomenclatura de diretórios ou arquivos
- extremamente rápido
- nenhuma atualização manual de cache, tudo acontece automaticamente
- biblioteca madura, estável e amplamente utilizada
Podemos, portanto, esquecer estes blocos de código familiares:
require_once 'Utils/Page.php';
require_once 'Utils/Style.php';
require_once 'Utils/Paginator.php';
// ...
Instalação
Você pode baixar o RobotLoader como um único arquivo independente
RobotLoader.php
, que você insere usando require
em seu script e imediatamente tem disponível
o autoloading confortável para toda a aplicação.
require '/path/to/RobotLoader.php';
$loader = new Nette\Loaders\RobotLoader;
// ...
Se você está construindo uma aplicação usando Composer, pode instalá-lo através dele:
composer require nette/robot-loader
Uso
Assim como o robô do Google percorre e indexa páginas da web, o RobotLoader percorre todos os scripts PHP e registra quais classes, interfaces, traits e enums encontrou neles. Ele então armazena os resultados da pesquisa no cache e os usa na próxima requisição. Basta especificar quais diretórios ele deve percorrer e onde armazenar o cache:
$loader = new Nette\Loaders\RobotLoader;
// diretórios que o RobotLoader deve indexar (incluindo subdiretórios)
$loader->addDirectory(__DIR__ . '/app');
$loader->addDirectory(__DIR__ . '/libs');
// definimos o cache para o diretório 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
$loader->register(); // iniciamos o RobotLoader
E é isso, a partir deste momento não precisamos usar require
. Ótimo!
Se o RobotLoader encontrar um nome de classe duplicado durante a indexação, ele lançará uma exceção e informará você sobre isso. O RobotLoader também atualiza automaticamente o cache quando precisa carregar uma classe que não conhece. Recomendamos desativar isso em servidores de produção, veja Caching.
Se você quiser que o RobotLoader pule alguns diretórios, use $loader->excludeDirectory('temp')
(pode ser
chamado várias vezes ou passar vários diretórios).
Por padrão, o RobotLoader relata erros em arquivos PHP lançando a exceção ParseError
. Isso pode ser suprimido
usando $loader->reportParseErrors(false)
.
Aplicação Nette
Dentro de uma aplicação Nette, onde o objeto $configurator
é usado no arquivo de inicialização
Bootstrap.php
, a notação pode ser simplificada:
$configurator = new Nette\Bootstrap\Configurator;
// ...
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->addDirectory(__DIR__ . '/../libs')
->register();
Analisador de arquivos PHP
O RobotLoader também pode ser usado puramente para pesquisar classes, interfaces, traits e enums em arquivos PHP sem usar a função de autoloading:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// pesquisa diretórios por classes / interfaces / traits / enums
$loader->rebuild();
// retorna um array de pares classe => nome do arquivo
$res = $loader->getIndexedClasses();
Mesmo com tal uso, você pode utilizar o cache. Graças a isso, ao escanear novamente, arquivos inalterados não serão analisados repetidamente:
$loader = new Nette\Loaders\RobotLoader;
$loader->addDirectory(__DIR__ . '/app');
// definimos o cache para o diretório 'temp'
$loader->setTempDirectory(__DIR__ . '/temp');
// pesquisa diretórios usando o cache
$loader->refresh();
// retorna um array de pares classe => nome do arquivo
$res = $loader->getIndexedClasses();
Caching
O RobotLoader é muito rápido porque usa o cache de forma inteligente.
Durante o desenvolvimento, você praticamente não percebe que ele está rodando em segundo plano. Ele atualiza continuamente o cache, pois espera que classes e arquivos possam surgir, desaparecer, ser renomeados, etc. E não escaneia repetidamente arquivos que não foram alterados.
Ao implantar em um servidor de produção, por outro lado, recomendamos desativar a atualização do cache usando
$loader->setAutoRefresh(false)
(na Aplicação Nette, isso acontece automaticamente), pois os arquivos não mudam.
Ao mesmo tempo, é necessário limpar o cache ao carregar uma nova versão no hosting.
A varredura inicial dos arquivos, quando o cache ainda não existe, pode, compreensivelmente, levar um momento para aplicações maiores. O RobotLoader tem prevenção integrada contra cache stampede. Esta é uma situação em que um grande número de requisições simultâneas chegam ao servidor de produção, que iniciam o RobotLoader, e como o cache ainda não existe, todas começariam a escanear os arquivos. O que sobrecarregaria desproporcionalmente o servidor. Felizmente, o RobotLoader funciona de forma que, com múltiplas requisições simultâneas, apenas a primeira thread indexa os arquivos, cria o cache, as outras esperam e, subsequentemente, usam o cache.
PSR-4
Hoje, é possível usar o Composer para
autoloading seguindo o PSR-4. Simplificando, é um sistema onde namespaces e nomes de classes correspondem à estrutura de
diretórios e nomes de arquivos, ou seja, por exemplo, App\Core\RouterFactory
estará no arquivo
/path/to/App/Core/RouterFactory.php
.
O RobotLoader não está vinculado a nenhuma estrutura fixa, por isso é útil em situações em que você não se sente confortável em ter a mesma estrutura de diretórios projetada como namespaces em PHP, ou quando desenvolve uma aplicação que historicamente não usa tais convenções. Também é possível usar ambos os loaders juntos.