Autoload no PHP 5

É costume ao se desenvolver implementando Design Patterns, a criação de um arquivo por classe e vários packages para organização de seu projeto. Com o crescimento do projeto, acaba se tornando uma tarefa ardua escrever todos os includes necessários no inicio de cada classe. No PHP 5, foi adicionado a função de autoload para facilitar o desenvolvimento, com ela, não é mais necessario uma longa lista de includes, basta instanciar a classe que esta será automaticamente carregada.
Um exemplo de uso de autoload:

PHP:
  1. <?php
  2. function __autoload($class_name) {
  3.     require_once $class_name . '.php';
  4. }
  5.  
  6. $obj  = new MyClass1();
  7. $obj2 = new MyClass2();
  8. ?>

O único problema que teremos é que dependendo do package, teremos que adaptar o caminho do require_once, o que torna-se trabalhoso. Uma maneira de resolver isso seria adicionar os diretorios do package no include_path do PHP, podemos implementar a função set_include_path que define o caminho do include_path em tempo de execução.

PHP:
  1. set_include_path(".;C:\package1.;C:\package2");

Agora não importa o caminho meu package, a classe será carregada sem problemas. Mas podemos melhorar implementando a SPL(Standard PHP Library) no meu projeto, para isso usarei a função spl_autoload, que é usada como implementação padrão do __autoload(). Ela procura os nomes das classes em minúsculo com as extensões .inc e .php no include path.
Para completar teremos um método para varrer os diretorios, para inclui-los no include_path, tomando o devido cuidado para não listar diretorios que podem comprometer o projeto.

PHP:
  1. <?php
  2. class Loader  
  3. {
  4.     public function __construct()
  5.     {
  6.         $dir = self::scanDirectories(dirname(__FILE__));
  7.         for ($i=0;$i<count($dir);$i++)
  8.         {
  9.             $str .= ".;".$dir[$i];
  10.         }
  11.         set_include_path($str);
  12.         spl_autoload_register(array("Loader","load"));
  13.     }
  14.    
  15.     public static function load($class)
  16.     {
  17.         spl_autoload_extensions('.php');
  18.         spl_autoload($class);
  19.     }
  20.    
  21.     public static function scanDirectories($rootDir, $allData=array())
  22.     {
  23.         $invisibleFileNames = array(".", "..", ".htaccess", ".htpasswd");
  24.         $dirContent = scandir($rootDir);
  25.         foreach($dirContent as $key => $content)
  26.         {
  27.             $path = $rootDir.'/'.$content;
  28.             if(!in_array($content, $invisibleFileNames))
  29.             {
  30.                 if(is_dir($path) && is_readable($path))
  31.                 {
  32.                     $allData[] = $path;
  33.                     $allData = self::scanDirectories($path, $allData);
  34.                 }
  35.             }
  36.         }
  37.         return $allData;
  38.     }
  39. }
  40. $loader = new Loader();
  41. ?>

E para testar:

PHP:
  1. /*require_once 'br/com/leonardofranca/vo/Vo1.php';
  2. require_once 'br/com/leonardofranca/vo/Vo2.php';
  3. require_once 'br/com/leonardofranca/services/Services.php';
  4. require_once 'br/com/leonardofranca/controller/FrontController.php';
  5. require_once 'br/com/leonardofranca/view/Form.php';
  6. require_once 'br/com/leonardofranca/Main.php';*/
  7. require_once 'Loader.php';
  8. class Test  
  9. {
  10.     function __construct()
  11.     {
  12.         $service = new Services();
  13.         $vo1= new Vo1();
  14.         $vo2= new Vo2();
  15.         $form= new Form();
  16.         $main= new Main();
  17.     }
  18. }
  19. $test = new Test();

Pode ser usado também com o ZendAMF:

PHP:
  1. require_once 'Zend/Amf/Server.php';
  2. //require_once 'HelloWorld.php';
  3. //require_once 'RoundTrip.php';
  4. //require_once 'services/World.php';
  5. //require_once 'services/Hello.php';
  6. //require_once 'services/UserVO.php';
  7. //require_once 'br/com/leonardofranca/vo/ContatosVO.php';
  8. //require_once 'br/com/leonardofranca/Contatos.php';
  9. //...
  10. require_once 'Loader.php';
  11.  
  12. /** Bootstrap */
  13.  
  14. // Instantiate server
  15. $server = new Zend_Amf_Server();
  16. $server->setClass('Contatos');
  17. $server->setClass('HelloWorld');
  18. $server->setClass('RoundTrip');
  19. echo($server->handle());

referencias
SPL(Standard PHP Library)
http://br.php.net/autoload
http://www.rafaeldohms.com.br/2007/01/10/otimizando-codigo-com-__autoload/pt/

Esses artigos podem ser interessantes também

  • No Related Post
PHP, ZendAMF

8 comments


  1. Vinicius

    Muito bom!
    Agora, no exemplo da função set_include_path, faltou o PATH_SEPARATOR, não?

  2. Igor Carvalho

    muit bom, porem nao deu certo comigo, deu erro de classe nao encontrara, a classe que eu chamei, igual ao exemplo…

  3. aparece algum erro no log do php?

  4. Igor Carvalho

    Simplesmente a classe evocada nao é incluida…

  5. Éder

    Bom eu sou iniciante em php e em programação também, porém eu estou estudando no livro php Orientado a objetos e eu vi a função autoload e tentei implementá-la, sem sucesso, gostaria de saber se alguém pode me ajudar?

  6. Guilherme Ribeiro

    Eu fiz e deu certo :

    function __autoload($classe){

    if(file_exists(“app.ado/{$classe}.class.php”)){
    include_once “app.ado/{$classe}.class.php”;
    }
    }

    Vc provavelmente errou o caminho do diretório.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>