Palavra:   

Revista PHP / PHP

Alexandre Semmer

Bacharel em Ciências da Computação pela UNIPAN-Cascavel PR, trabalha com desenvolvimento em PHP para sistemas web à 3 anos. Gerente de projetos da WebGenium System. Tem conhecimentos em Java, Ajax, JavaScript, CSS, Padrões de Projetos, XML e JSON. Banco de dados MySQL e PostgreSQL

Includes nunca mais

Olá a todos, esse é meu primeiro artigo para a revista, primeiro de muitos espero, venho falar de uma funçãozinha muito útil do PHP5, __autoload(), esta função é uma das muitas intercepções inclusas no PHP5 (além de __call(), __set(), __get(), entre outras).

Como o nome já diz, esses métodos interceptam as chamadas, cada um com sua particularidade. No caso do __autoload(), é invocado sempre que uma classe é instanciada e seu arquivo não esta incluso, no caso é passado um parâmetro referente ao nome da classe instanciada para o método __autoload(). Estruturando bem seus diretórios e classes, você poderá instanciá-las em qualquer arquivo, sem se preocupar em incluí-las nas paginas. Neste artigo vou mostrar um exemplo de como estruturar um projeto para que o __autoload() seje utilizado.

1- Exemplo de uma estrutura de diretórios:

- Existe o diretório principal (artigo) que contem os outros diretórios e o arquivo Index.php.
- Diretórios classe e sistema (contendo a diretória listagem)
- E todos os arquivos estão com o mesmo nome (exemplo.php)
- O arquivo sistema/configuracao.php irá conter o método __autoload();



2- Criando as classes

Primeiro vamos criar a classe Sistema_Exemplo, essa será a nomenclatura de todas as classes. Partindo da raiz todos os diretórios serão inclusos no nome da classe, separados por “_” underline e o ultimo nome será o nome do arquivo php.

PHP
  1. <?php
  2. class Sistema_Exemplo {
  3.  
  4. protected $_att;
  5.  
  6. public function __construct($att){
  7. $this->_att = $att;
  8. }
  9.  
  10. public function get(){
  11. return sprintf("Diretório Sistema: %s",$this->_att);
  12. }
  13.  
  14. public function set($att){
  15. $this->_att = $att;
  16. }
  17. }
  18. ?>
www.revistaphp.com.br

Sistema_Exemplo: Bom não tem muito o que dizer, é uma classe comum. O arquivo será sistema/exemplo.php.

PHP
  1. <?php
  2. class Sistema_Listagem_Exemplo {
  3.  
  4. private $_lista = array("morango", "framboesa", "limão", "laranja");
  5. private $_escolha = null;
  6.  
  7. public function __construct($escolha = null){
  8. $this->_escolha = $escolha;
  9. }
  10.  
  11. public function getLista(){
  12. $lista = "<B>LISTA DE FRUTAS</B><BR>";
  13. foreach($this->_lista as $key=>$fruta){
  14. $lista .= ($fruta == $this->_escolha) ?
  15. sprintf("%d:<B>%s</B><br>",$key,$fruta)
  16. : sprintf("%d:%s<br>",$key,$fruta);
  17. }
  18. return $lista;
  19. }
  20.  
  21. }
  22. ?>
www.revistaphp.com.br

Sistema_Listagem_Exemplo: Ai já utiliza mais de um nível de diretórios, que é explicito no nome da classe, essa classe recebe o nome de uma das frutas e deixa ela em negrito na listagem . O arquivo será sistema/listagem/exemplo.php.

PHP
  1. <?php
  2. class Classe_Exemplo extends Sistema_Exemplo{
  3.  
  4. public function getDirClasse(){
  5. return sprintf("Diretório Classe: %s",$this->_att);
  6. }
  7. }
  8. ?>
www.revistaphp.com.br

Classe_Exemplo: Esta classe estende Sistema_Exemplo, sem precisar dar include na classe, mesma idéia para implements.

Agora vamos para o arquivo configuracao.php, nele que irá conter a função  __autoload().

PHP
  1. <?php
  2. function __autoload($classe) {
  3. if(class_exists($classe)){
  4. return true;
  5. }
  6. $caminho = explode('_',$classe);
  7. $arquivo = strtolower(str_replace("_","/",$classe)) . ".php";
  8. $diretorios = array("Classe","Sistema");
  9. if(in_array($caminho[0],$diretorios)){
  10. if (file_exists($arquivo)) {
  11. require_once $arquivo;
  12. return true;
  13. } else {
  14. echo sprintf("Arquivo não existe :
  15. <i style='color:#3333FF'>%s</i>",$arquivo);
  16. }
  17. }else{
  18. require_once $classe.".php";
  19. }
  20. }
  21. ?>
www.revistaphp.com.br

Bom quando for instanciado uma classe, como por exemplo:

PHP
  1. $objeto = new Classe_Exemplo("Teste");
www.revistaphp.com.br

A função _autoload é chamada recebendo como parâmetro a string “Classe_Exemplo”.

Linhas 2 a 5 : Verifica se a classe já existe, no caso de existir, não precisando incluir o arquivo novamente.
Linha 6: Passa para o vetor $caminho todos os diretórios e o nome do arquivo.
Linha 7: Troca o “_” por “/” e inclui a extensão, no caso a string “Classe_Exemplo” ficará “classe/exemplo.php”.
Linha 8: Vetor com os diretórios principais, possibilitando uma validação da classe.
Linha 9: Verifica se o primeiro diretório está contido no vetor de diretórios.
Linha 10: Verifica se o arquivo existe.
Linha 11 e 12: Inclui o arquivo na pagina.
Linha 14 e 15: Mostra uma mensagem que o arquivo não foi encontrado.
Linha 18: Possibilita a inclusão de um arquivo que esta na raiz.

Agora vamos testar no arquivo index.php.

PHP
  1. <?php
  2. require_once("sistema/configuracao.php");
  3.  
  4. $classe_exemplo = new Classe_Exemplo("Teste");
  5. echo $classe_exemplo->get() . "<br>";
  6. echo $classe_exemplo->getDirClasse() . "<br>";
  7.  
  8. $lista = new Sistema_Listagem_Exemplo("framboesa");
  9. echo $lista->getLista();
  10. ?>
www.revistaphp.com.br

Neste exemplo, só é preciso incluir o arquivo de configuração e instanciar as classes quando quiser J.

Diretório Sistema: Teste
Diretório Classe: Teste
LISTA DE FRUTAS
0:morango
1:framboesa
2:limão
3:laranja

Resultado do index.php


Espero que tenha ajudado, pois essa função é uma mão na roda para programar aplicações de pequeno e grande porte, créditos também para os colegas Everton e Anselmo que ajudaram nessa estrutura. Qualquer dúvida é só falar, próximos artigos vou escrever mais sobre as intercepções no PHP5. Valeu tudo de bom para vocês.

Opções de Interação

Comentários

Include somente uma vez
Por: Gedalias, 04/03/2009   10:45:49
Claro que não. o conteudo abaixo deverá estar em apenas em um arquivo, vamos chama-lo de, libloader.php, agora no arquivo mais alto de chamada inclua um, por exemplo:

require_once "conf/libloader.php" ou
include "conf/libloader.php"

na teoria a minha função __autoload será chamada a cada instanciacao de objetos e na pratica ela carrega cada classe a partir dos include_path que podem ser feito em tempo execucao ja que estou configurando os path do php, no exemplo citado por mim estou usando a funcao ini_set para compatiblidade com qualquer versão, mas ja que estamos falando de Orientacao a Objetos e este só se preza a partir do PHP5, então recomendo usar set_include_path(), para compatiblidade futura e que seu codigo tenham vida longa.

E para terminar, voce pode ter todas as classes de dominio no mesmo subdiretorio em ./library/
porem evite nomes duplicados pois o php não dá suporte a namespace e portanto duas classes de
dominio para dois sistemas diferentes chamada de Agenda, ou Usuario, ou QualquerCoisa entrarao em conflitos e vc não perceberá de imediato, só qund seu aplicativo for hospedado.

Espero ter esclarecido bem....
...todo o mal necessario
Por: Alexandre, 02/03/2009   08:35:27
toda vez que for instanciado uma classe o php vai abri o diretório e faze esses while e ifs ai???
todo o mal necessario
Por: Gedalias, 01/03/2009   15:54:54
eu ainda prefiro usar o metodo abaixo.
$base_dir=get_include_path();
$dir = dir("/www/library/");
while (false !== ($entry = $dir->read())) {
if(strpos($entry, ".")===false){
$base_dir.= $dir->path.$entry.":";
}
}
//echo "$base_dir";
$dir->close();
//set_include_path("$base_dir");//5.1
ini_set("include_path","$base_dir"); //****
function __autoload($classname){
require_once( $classname . ".class.php");
}

usar um bilioteca separado do sistema e fazer um include_path nomeio todos os meus arquivos de forma a seguir um convenção

NomeDaClass.clas.php ou
INomeDaInterface.class.php

faco um require_once('libloader.php'), que é o arquivo com o conteudo acima e deixo o PHP sabiamente tomar conta de tudo. Veja as permissoes de arquivos...
Vantagem
Por: Alexandre, 02/06/2008   17:47:58
O _autoload e o include são duas funções totalmente diferentes. Sempre que vc precisar trabalhar com uma classe, tenque incluir ela no arquivo que esta trabalhando (include ou require), o autoload é chamado quando uma classe é instanciada e não é encontrado o arquivo correspondente, assim vc podera tratala com o include, require, include_once ou require_once como desejar. Espero ter esclarecido sua dúvida.
Vantagen
Por: Eric, 25/05/2008   02:35:26
Olá amigo, teria como citar uma vantagem entre usar o autoload em relação a include?