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/

6 Comments

  • By anderson, May 16, 2009 @ 22:10

    muito bom

  • By Vinicius, June 19, 2009 @ 15:34

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

  • By Leonardo França, June 24, 2009 @ 13:13

    Opa! bem lembrado!

  • By Igor Carvalho, August 24, 2009 @ 11:33

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

  • By Leonardo França, August 27, 2009 @ 17:43

    aparece algum erro no log do php?

  • By Igor Carvalho, October 25, 2009 @ 08:25

    Simplesmente a classe evocada nao é incluida…

Other Links to this Post

RSS feed for comments on this post. TrackBack URI

Leave a comment

WordPress Themes


Video & Audio Comments are proudly powered by Riffly