Namespaces e Autoload de classes em PHP 5
Autor: Mario Cezzare Angelicola Chiodi | Publicado: 2012-10-14T13:10:00-07:00

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
 



Este artigo é uma continuação da explicação do uso da função __autoload&nbsp;, só que neste utilizando namespaces.
Bem, como vimos a utilização do recurso de autoload, agora vou adequar os arquivos do post anterior p/ poder utilizar o recurso de namespaces. Pode parecer um pouco confuso até pegar o jeito, mas vale a pena. Esse novo conceito necessita de organização &nbsp;e &nbsp;algumas dicas q eu dou são:
Importantes:
1 - que vc utilize os namespaces de acordo com sua estrutura física de arquivos e pastas.Evite perda de tempo e confusões desnecessárias
2 - que vc dê uma boa lida nesses links :
-&nbsp;namespaces
-&nbsp;static&nbsp;

-&nbsp;__autoload&nbsp;

-&nbsp;spl

-&nbsp;spl_autoload_register,&nbsp;

-&nbsp;ArrayIterator





3 - que você aceite o novo padrão de implementação que está sendo pedido, e esqueça o jeito procedural de fazer as coisas. Daqui para frente pense sempre em OOP, Classes , Reutilização de Código;

4 - que antes de sair codificando alguma coisa, verifique se já existe alguma design pattern para o seu problema;

5 - Veja na documentação fornecida pelo fabricante ou mantenedor os modelos exemplos fornecidos. Penso que ninguém melhor para mostrar o melhor uso. No caso do php o site do PHP&nbsp;, da ORACLE&nbsp;e da IBM&nbsp;são boas referências;

Opcionais:

6 - Se possível faça um modelo UML antes do sistema, existem diversas ferramentas que facilitam criar os diagramas e uns até exportam o diagrama p/ código fonte (C,C++,PHP,JAVA,etc..), eu gosto do Astah

7 - Se vc quiser usar um esquema automágico no carregamento de classes, utilize sempre o mesmo esquema nos nomes de arquivos ou tudo.php ou tudo .class.php, no exemplo anterior eu mostrei um jeito semi-automático criando um array com os nomes das classse (aí pode utilizar qualquer nome, pois o mapeamento será manual, p/ pequenas aplicações não tem problema), e caminho dentro de uma função&nbsp;__autoload .

Nesse esquema a função spl_autoload_register já faz isso.&nbsp;



8- Utilize uma IDE p/ desenvolver, Netbeans, Eclipse, Dreamweaver, tanto faz. e utilize uma ferramenta que gere documentação de seu código. Isso permite analisar mais fácilmente o que já foi implementado e o que falta.


9- Quando achar que já sabe o bastante, continue pesquisando, as tecnologias são dinâmicas e requerem sempre atualizações ou melhorias.Penso que sempre existirá um jeito mais rápido de se fazer algo que já está sendo feito, depende do ponto de vista e da experiência do desenvolvedor.

Vamos ao namespaces :


1- Introdução namespaces&nbsp;
Antes de mostrar o projeto final, vou mostrar um exemplo simples p/ facilitar o entendimento ainda utilizando uma função __autoload():
Observe que quando vc quiser usar o comando use .. . a classe deve ter na 1ª linha uma definição de namespace p/ ser acessível.
E a definição namespace na classe que vc quer disponilizar o acesso.






/test/Foo.php este com namespace tests
&lt;?php
namespace tests;

class Foo {

    public function __construct() {}

    public function sayHello() {
        echo 'Hello &lt;br&gt;';
        $dt = new \DateTime();
    }

    public static function sayBye() {
        echo 'Bye ';
    }

    public static function init() {}

}?&gt;


/autoload.php sem utilizar declaração namespace
&lt;?php
function __autoload($classe) {
    echo "receiving $classe&lt;br&gt;";
    $nameClassOnly = strpos(strrev($classe), "\\");

    $classeAux = substr($classe, -$nameClassOnly);
    echo "would be $classeAux??&lt;br&gt;";

    $finalClass = str_replace('\\', '/', $classe);

    echo "including $finalClass&lt;br&gt;";
    require_once $finalClass . '.php';
    spl_autoload_register(array($classe, 'init'));//registra a classe com o metodo statico init
}?&gt;


/callFoo.php&nbsp;sem utilizar declaração namespace mas usando o autoload e o comando use namespace\classe


&lt;?php
require 'autoload.php';
use tests\Foo ;
$foo = new Foo();
$foo-&gt;sayHello();

$dt = new DateTime();
echo $dt-&gt;format(date('d/m/Y H:i:s')) . "&lt;br&gt;";
//static method
Foo::sayBye();

echo "&lt;pre&gt;";
print_r(spl_autoload_functions());
echo "&lt;/pre&gt;";?&gt;


resultado :





/callFoo_1.php&nbsp;sem utilizar declaração namespace mas usando o autoload e o comando&nbsp;use namespace\classe &nbsp;e utilizando um Alias p/ a classe Foo


&lt;?php
require 'autoload.php';
use tests\Foo as MyFooClass;
$foo = new MyFooClass();

$foo-&gt;sayHello();
$dt = new DateTime();
echo $dt-&gt;format(date('d/m/Y H:i:s')) . "&lt;br&gt;";

MyFooClass::sayBye();
echo "&lt;pre&gt;";
print_r(spl_autoload_functions());
echo "&lt;/pre&gt;";
?&gt;

resultado :



e como fica isso mais perto da realidade sem Foo, bar, etc ?

/callCliente.php&nbsp;sem utilizar declaração namespace mas usando o autoload e o comando&nbsp;use ...
&lt;?php
require 'autoload.php';
use app\model\Cliente;
use app\lib\Utils;

$cliente = new Cliente();
$util= new Utils();
$util-&gt;mostraObjeto($cliente);
echo "&lt;pre&gt;";
print_r(spl_autoload_functions());
echo "&lt;/pre&gt;";
?&gt;


/app/model/Cliente.php
&lt;?php
namespace app\model;
final class Cliente {

    private $id;
    private $nome;
    private $email;

    function __construct() {
        $this-&gt;id = 0;
        $this-&gt;nome = null;
        $this-&gt;email = null;
    }
    

    public static function init() {
        __construct();
    }

    public function getId() {
        return $this-&gt;id;
    }

    public function setId($id) {
        $this-&gt;id = $id;
    }

    public function getNome() {
        return $this-&gt;nome;
    }

    public function setNome($nome) {
        $this-&gt;nome = $nome;
    }

    public function getEmail() {
        return $this-&gt;email;
    }

    public function setEmail($email) {
        $this-&gt;email = $email;
    }
    public function __toString() {
        return "id:".$this-&gt;getId()." nome:".$this-&gt;getNome()." email:".$this-&gt;getEmail();
    }
}

?&gt;



/app/lib/Utils.php
&lt;?php
namespace app\lib;
class Utils {
      private  $styleBox;  

      public static function init(){
          __construct() ;
      }
     public function __construct() {}

    public static function mostraObjeto($object) {
        echo "&lt;pre style=\"
        font-family: Tahoma, Geneva, sans-serif;
 background-color: #FFC;
 font-size: 9px;
 border: thin solid #03C;
 cursor: text;
 filter: Xray;\"&gt;";
        print_r($object);
        echo "&lt;/pre&gt;";
        echo "&lt;hr size=\"1\" width=\"100%\"&gt;";
    }
}?&gt;

Teste.
resultado



Experimente criar novas classes e usá-las, ou mover os arquivos de lugar p/ entender bem o conceito de namespace

Agora que você já entendeu o conceito de namespaces vamos a Aplicação, a idéia é fazer um CRUD dos Clientes utilizando o jQuery para realizar as operações e o PHP servir apenas como um BackEnd e DataStore , mas como já expliquei neste post como utilizar namespaces, &nbsp;vou começar o Post da aplicação. pois já temos o que precisamos...



Dúvidas, Contribuições, Sugestões? Poste..Grato,Até a próxima.