domingo, 14 de outubro de 2012

Namespaces e Autoload de classes em PHP 5


Este artigo é uma continuação da explicação do uso da função __autoload , 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  e  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 :
namespaces
static 
spl


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 , da ORACLE e da IBM 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 __autoload .
Nesse esquema a função spl_autoload_register já faz isso. 

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 

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
<?php
namespace tests;

class Foo {

    public function __construct() {}

    public function sayHello() {
        echo 'Hello <br>';
        $dt = new \DateTime();
    }

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

    public static function init() {}

}?>

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

    $classeAux = substr($classe, -$nameClassOnly);
    echo "would be $classeAux??<br>";

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

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

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


<?php
require 'autoload.php';
use tests\Foo ;
$foo = new Foo();
$foo->sayHello();

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

echo "<pre>";
print_r(spl_autoload_functions());
echo "</pre>";?>

resultado :



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


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

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

MyFooClass::sayBye();
echo "<pre>";
print_r(spl_autoload_functions());
echo "</pre>";
?>

resultado :

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

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

$cliente = new Cliente();
$util= new Utils();
$util->mostraObjeto($cliente);
echo "<pre>";
print_r(spl_autoload_functions());
echo "</pre>";
?>

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

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

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

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

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

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

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

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

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

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

?>


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

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

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

Nenhum comentário: