O que é carregamento automático; Como você usa spl_autoload, __autoload e spl_autoload_register?


204

Estou aprendendo padrões avançados de PHP e tentando implementar métodos novos e úteis. No começo, eu estava usando __autoloadapenas para escapar, incluindo vários arquivos em cada página, mas recentemente vi uma dica sobre__autoload manual

spl_autoload_register () fornece uma alternativa mais flexível para o carregamento automático de classes. Por esse motivo, o uso de __autoload () é desencorajado e pode ser preterido ou removido no futuro.

mas eu realmente não consigo descobrir como implementar spl_autoloadespl_autoload_register

Respostas:


335

spl_autoload_register() permite registrar várias funções (ou métodos estáticos de sua própria classe Autoload) que o PHP colocará em uma pilha / fila e chamará sequencialmente quando uma "nova classe" for declarada.

Então, por exemplo:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class/';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

No exemplo acima, "MyClass" é o nome da classe que você está tentando instanciar, o PHP passa esse nome como uma string para spl_autoload_register(), o que permite pegar a variável e usá-la para "incluir" a classe / arquivo apropriado . Como resultado, você não precisa especificamente incluir essa classe por meio de uma instrução include / require ...

Simplesmente chame a classe que você deseja instanciar, como no exemplo acima, e como você registrou uma função (via spl_autoload_register()) própria que descobrirá onde toda a sua classe está localizada, o PHP usará essa função.

A vantagem de usar spl_autoload_register()é que, diferentemente de __autoload()você não precisar implementar uma função de carregamento automático em todos os arquivos que você cria. spl_autoload_register()também permite registrar várias funções de carregamento automático para acelerar o carregamento automático e torná-lo ainda mais fácil.

Exemplo:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

Com relação a spl_autoload , o manual declara:

Esta função deve ser usada como uma implementação padrão para __autoload(). Se nada mais for especificado e spl_autoload_register()for chamado sem nenhum parâmetro, essas funções serão usadas para qualquer chamada posterior a __autoload().

Em termos mais práticos, se todos os seus arquivos estiverem localizados em um único diretório e seu aplicativo usar não apenas arquivos .php, mas arquivos de configuração personalizados com extensões .inc, por exemplo, uma estratégia que você poderia usar seria adicionar seu diretório contendo todos os arquivos para o caminho de inclusão do PHP (via set_include_path()).
E como você também requer seus arquivos de configuração, você usaria spl_autoload_extensions()para listar as extensões que deseja que o PHP procure.

Exemplo:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

Como spl_autoload é a implementação padrão do __autoload()método mágico, o PHP chamará spl_autoload quando você tentar instanciar uma nova classe.

Espero que isto ajude...


35
Esta pode ser uma das melhores respostas na história das respostas de todos os tempos. Respeito. Eu tive um desses "OMG! Tudo faz sentido agora!" momentos por sua causa, meu bom homem. Acho que posso começar um fã-clube.
Apenas Plain High

2
Para tornar essa a melhor resposta de todas as respostas já em universos alternativos, adicione que spl_autoload muito, hum, "útil" (?) Converte todos os nomes de arquivos em minúsculas (veja meu comentário em @ usuário abaixo). Não é possível usar a baunilha spl_autoload_register () se você gosta do seu CapitalLettersAndStuff.
Just Plain alta

6
@ Just Plain High Eu não estou tendo esse problema e todos os meus arquivos de classe são camelcased. BTW, esta é uma resposta maravilhosa. Isso me ajudou a entender um conceito simples que eu não conseguia entender até ler este post! Minha linha de 85 (e crescente) arquivo de inclusão que inclui todos os meus arquivos de classe agora tem 7 linhas!
Kd #

2
Esta é realmente uma boa resposta, mas estou perdendo uma coisa. Qual é a funcionalidade padrão real? Com as classes que eu conheço, ele usa o espaço para nome como caminho e o nome da classe como nome do arquivo. Embora eu não possa descobrir como isso funciona com funções.
SiXoS

2
Não é um dos grandes benefícios do uso spl_autoload_register()(e __autoload()em geral) que ele carrega preguiçosamente inclui arquivos / classes? Isso está implícito na resposta, mas não é explicitamente declarado. Para mim, essa é uma informação crítica que seria perfeita para inclusão na sua resposta! :)
rinogo

13

Desde o PHP 5.3, você pode usar spl_autoload_register()com espaços para nome, o que significa que você pode organizar seu projeto e carregar automaticamente suas classes php sem nenhuma necessidade ou inclusão e sem redefinir uma __autoload()função.

Para demonstrar esse comportamento, basta criar um arquivo chamado index.php:

<?php
spl_autoload_register();
var_dump(new Main\Application);

Em seguida, crie uma pasta chamada Main localizada ao lado do arquivo index.php. Por fim, cria um arquivo chamado Application.php localizado em Main e cole o seguinte código nele:

<?php namespace Main;
class Application{}

9
Uma observação da minha brincadeira com tudo isso: spl_autoload () - e, portanto, spl_autoload_register () - converte nomes de arquivos em letras minúsculas (apesar dos relatórios de erros, argumentos e votação furiosa). Isso significa que você pode estar procurando por "Main \ Application", mas spl_autoload está procurando por "main \ application". Se você gosta de camelos, como eu, terá que escrever sua própria função. Há um bom exemplo de iniciante aqui: github.com/ircmaxell/PHP-CryptLib/blob/…
Just Plain High

1
Prós: spl_autoload_register () é o método mais rápido de carregamento automático Contras: ele funcionará apenas com arquivos / classes em minúsculas e espaços para nome também, que atualmente são muito grandes (não há opção para usar o CamelCase etc.). Mas se você pode viver com a estrutura namespace / classname.php, não procure mais.
Stamster 19/09/16

1
spl_autoload_register()A implementação padrão não pode encontrar classes herdadas. Portanto, usando padrões, arquivos em minúsculas e diretórios que refletem o caminho do espaço para nome, tudo funciona bem, a menos que eu tenha uma classe que estenda outra classe (pai). O PHP então gera um erro que não consegue encontrar a classe pai, mesmo que todos estejam no mesmo diretório / espaço para nome! O que é confuso é que literalmente apenas as classes de primeiro nível são encontradas, então eu tive que colocar outra spl_autoload_register()regra de função anônima logo após a 1ª ordem para incluir manualmente classes pai / herança herdadas.
Stamster

1

Aqui está a maneira como eu uso o Autoload. No exemplo dado, pretendo carregar classes de três diretórios diferentes.

function namespaceAutoload($rawClass){

$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';

foreach ($possiblePaths as $templatePath) {
    $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
    if (file_exists($path)) {
        require_once "$path";
        break;
    }
} spl_autoload_register("namespaceAutoload"); 

No exemplo dado, o PHP procurará o namespace \ class nesses três diretórios usando esses três formatos diferentes de nome de arquivo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.