Pergunta

Como a maioria dos desenvolvedores web estes dias, estou gostando os benefícios da arquitetura MVC sólida para aplicações web e sites. Ao fazer MVC com PHP, auotocarregáveis, obviamente, vem em muito útil.

Eu me tornei um fã do spl_autoload_register mais simplesmente definindo uma única função __autoload(), pois este é, obviamente, mais flexível, se você está incorporando diferentes módulos básicos que cada usar o seu próprio carregamento automático. No entanto, eu nunca me senti muito bem sobre as funções de carregamento que eu escrevo. Elas envolvem um monte de verificação de corda e digitalização diretório, a fim de olhar para possíveis classes para carregar.

Por exemplo, digamos que eu tenho um aplicativo que tenha um caminho de base definida como PATH_APP, e uma estrutura simples, com diretórios nomeados models, views e controllers. Eu muitas vezes empregam uma estrutura de nomeação pelo qual arquivos são nomeados IndexView.php e IndexController.php dentro do diretório apropriado, e os modelos geralmente têm nenhum esquema especial por padrão. Eu poderia ter uma função de carregador para esta estrutura como esta que fica registrado com spl_autoload_register:

public function MVCLoader($class)
{
    if (file_exists(PATH_APP.'/models/'.$class.'.php')) {
        require_once(PATH_APP.'/models/'.$class.'.php');
        return true;
    }
    else if (strpos($class,'View') !== false) {
        if (file_exists(PATH_APP.'/views/'.$class.'.php')) {
            require_once(PATH_APP.'/views/'.$class.'.php');
            return true;
        }
    }
    else if (strpos($class,'Controller') !== false) {
        if (file_exists(PATH_APP.'/controllers/'.$class.'.php')) {
            require_once(PATH_APP.'/controllers/'.$class.'.php');
            return true;
        }
    }
    return false;
}

Se não for encontrado depois disso, eu poderia ter outra função para sub-diretórios varredura no diretório modelos. No entanto, todo o if / else-ing, verificação de corda e digitalização diretório parece ineficiente para mim, e eu gostaria de melhorá-lo.

Estou muito curioso que nomeação e auotocarregáveis ??estratégias arquivo de outros desenvolvedores pode empregar. Eu estou olhando especificamente para boas técnicas a empregar para carregamento automático eficiente, e não alternativas para carregamento automático.

Foi útil?

Solução

Isto é o que tenho vindo a utilizar em todos os meus projetos (levantou direto da fonte do último):

public static function loadClass($class)
{
    $files = array(
        $class . '.php',
        str_replace('_', '/', $class) . '.php',
    );
    foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $base_path)
    {
        foreach ($files as $file)
        {
            $path = "$base_path/$file";
            if (file_exists($path) && is_readable($path))
            {
                include_once $path;
                return;
            }
        }
    }
}

Se eu olhar para SomeClass_SeperatedWith_Underscores ele vai olhar para SomeClass_SeperatedWith_Underscores.php seguido por SomeClass / SeperatedWith / Underscores.php enraizada em cada diretório no atual caminho de inclusão.

EDIT: Eu só queria colocar lá fora que eu uso isso para a eficiência no desenvolvimento, e não necessariamente o tempo de processamento. Se você tem PEAR em seu caminho, em seguida, com isso, você pode apenas usar as classes e não tem que incluí-los quando você precisar deles.

Eu tendem a manter minhas aulas em uma hierarquia de diretórios, com sublinhados quebrando namespaces ... Este código permite-me manter a boa estrutura do arquivo e arrumado, se eu quiser, ou para injetar um arquivo de classe rápida, sem diretórios aninhados se eu quer (para a adição de uma única classe ou dois para uma biblioteca que é acusado, mas não faz parte do projeto que eu estou trabalhando atualmente.)

Outras dicas

Eu aterrou nesta solução:

Eu criei um único script que atravessa minha pasta biblioteca de classes (que contém subpastas para módulos / sistemas separados), e analisa o conteúdo do arquivo em busca de definições de classe. Se ele encontrar uma definição de classe em um arquivo php (padrão de regex bastante simples), ele cria um link simbólico:

class_name.php -> actual/source/file.php

Isto deixa-me usar uma única função autoload, simples que as necessidades apenas o nome da classe e o caminho para a pasta symlink principal, e não tem que fazer qualquer manipulação path / string.

A melhor parte é que eu posso reorganizar meu código fonte completo ou adicionar um novo subsistema e apenas executar o script de geração de link para ter tudo carregados automaticamente.

Se você quiser eficiência, então você não deve estar usando o recurso de carregamento automático em tudo. O recurso autoload é para ser preguiçoso. Você deve fornecer um caminho explícito para o seu incluir arquivos quando você incluí-los. Se a sua função autoload pode encontrar esses arquivos, então você pode codificar para encontrá-los explicitamente. Quando estiver a trabalhar na vista parte do código e sobre para carregar uma nova classe vista, deixando a função autoload lidar com isso, primeiro ele assume sua classe é uma classe de modelo? Isso é ineficiente. Em vez disso o seu código deve ser apenas:

include_once $this->views_path . $class . '.php';

Se precisar de múltiplos caminhos "vista", fazer uma função que as opiniões cargas:

public function load_view($class) {
    // perhaps there's a mapping here instead....
    foreach ($this->views_paths as $path) {
        $filename = $path . $class . '.php';
        if (file_exists($filename)) {
            include_once $filename;
        }
    }
    throw ....
}

Em qualquer caso, no ponto onde o incluem ocorre, você tem o maior mais informações / precisas sobre a classe que você deseja carregar. Usando essa informação para carregar a classe é plenamente a estratégia de carregamento de classe apenas eficiente. Sim, você pode acabar com mais variáveis ??de classe ou (Proibir céu) algumas variáveis ??globais. Mas isso é uma compensação melhor do que apenas ser preguiçoso e digitalização de partes do sistema de arquivos para a sua classe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top