Pages

22 de jun. de 2011

[PHP] Carregamento automático e recursivo de classes ( Autoload )

Fala galera,

Algumas pessoas me perguntaram como fazer o carregamento automático das classes, sem precisar ficar incluindo a devida classe. Uma das soluções é utilizar o método __autoload(), nativo do php. Ele recebe um parâmetro do tipo String. Sempre que é declarada uma nova classe o método __autoload() é acionado e o parâmetro recebido é o nome da classe declarada.

O uso do __autoload() para somente uma pasta pode ser feito por exemplo:

function __autoload($classe) {
    include "c:/desenv/classes/".$classe.".php";
}

Essa é uma das maneiras para fazer o uso do __autoload() para somente uma pasta.
Agora, caso vocês possuam uma estrutura de, por exemplo, mais de uma pasta e subpastas, podemos esse script que eu desenvolvi, que acho ideal para quem utiliza camadas de controle, modelo e persistencia de dados, divididas por módulos:

<?php
/**
 * @abstract método responsável pela busca de diretórios
 * @param $src String
 * @return array
 */
function buscarDiretorios($src) {
    $diretorios = array();
    foreach(new DirectoryIterator($src) as $file){
        $bool = preg_match("#\.php|\.\.|\.|\.inc|\.svn#", $file);
        if(!$bool) {
            $diretorios[] = $file->getFilename();
        }
    }
    return $diretorios;
}

/**
 * @abstract método responsável pelo carregamento automático das classes.
 * @param $class String
 */
function __autoload($class) {
    
    $caminho = "";
    if (file_exists(CLASS_DIR . "{$class}.php")) {
        $caminho = CLASS_DIR . "{$class}.php";
    } elseif (file_exists(CLASS_DIR . "DAO/{$class}.php")) {
        $caminho = CLASS_DIR . "DAO/{$class}.php";
    } elseif (file_exists(CLASS_DIR . "Control/{$class}.php")) {
        $caminho = CLASS_DIR . "Control/{$class}.php";
    } elseif (file_exists(CLASS_DIR . "Model/{$class}.php")) {
        $caminho = CLASS_DIR . "Model/{$class}.php";
    } elseif (file_exists(CLASS_DIR . "pde/{$class}.php")) {
        $caminho = CLASS_DIR . "pde/{$class}.php";
    }

    if(!$caminho) {
        $diretorios = buscarDiretorios(CLASS_DIR);
        foreach ($diretorios as $diretorio) {
            $subDiretorios = buscarDiretorios(CLASS_DIR . $diretorio);
            foreach($subDiretorios as $subDiretorio) {
                if (file_exists(CLASS_DIR . "{$diretorio}/{$subDiretorio}/{$class}.php")) {
                    $caminho = CLASS_DIR . "{$diretorio}/{$subDiretorio}/{$class}.php";
                }
            }
        }
    }

    if ($caminho) {
        require_once "$caminho";
    }
}
?>

É isso galera, espero ter ajudado.