Curso de PHP Orientado a Objetos

download Curso de PHP Orientado a Objetos

of 61

Transcript of Curso de PHP Orientado a Objetos

  • Curso de PHP Orientado a ObjetosO curso de PHP Orientado a Objetos est divido nas seguintes partes:

    Parte 1 - Introduo a programao Orientada a Objetos: Nesta aula seremos apresentados aos conceitos iniciais da Programao Orientada a Objetos.

    Parte 2 - Dessa vez aprenderemos sobre os mtodos. Veremos tambm na prtica os mtodos de inicializao (construtor) e finalizao (destrutor).

    Parte 3 - Neste artigo vamos aprender o que herana e como ela funciona no PHP.

    Parte 4 - Dessa vez explicaremos de forma detalhada o que e quando usamos o Polimorfismo.

    Parte 5 - Neste artigo entenderemos o conceito de abstrao. Veremos na prtica como se aplicam as classes abstratas, finais, mtodos abstratos e mtodos finais.

    Parte 6 - Neste artigo voc aprender o conceito de encapsulamento, alm de aplicar a visibilidade de mtodos e propriedades.

    Parte 7 - Neste artigo veremos constantes, propriedades estticas e mtodos estticos.

    Parte 8 - Dessa vez, estudaremos o relacionamento entre objetos. Veremos na prtica como se d uma relao de associao, agregao e composio.

    Parte 9 - Dessa vez, estudaremos os mtodos interceptores, tambm conhecidos como mtodos mgicos.

    Parte 10 Veremos dessa vez o o mtodo especial __autoload e algumas funes para manipulao de objetos.

    Parte 11 Dessa vez, veremos o tratamento de erros no PHP, prtica fundamental para o desenvolvimento com qualidade.

    Parte 12 Dcimo segundo artigo do curso de PHP Orientado a Objetos. Dessa vez, estudaremos o PDO (PHP Data Object).

  • Parte 1Introduo a programao Orientada a Objetos: Nesta aula seremos apresentados aos conceitos iniciais da Programao Orientada a Objetos.

    Motivado pela falta de material de qualidade, resolvi iniciar hoje uma srie de artigos sobre PHP Orientado a Objetos.

    Pr-Requisitos:

    PHP Intermedirio Bsico de MySql Bsico em UML

    Ao final deste artigo, voc ser capaz de:

    Diferenciar POO da programao procedural Entender os benefcios da POO Definir Classe e Objetos Criar uma classe bsica

    A velha programao estruturada:

    Quando se trata de programao estruturada, estamos lidando com um conceito que dominou o contexto da engenharia de software durante vrias dcadas.

    Na programao estruturada, o blocos de cdigo (chamaremos de procedimentos e funes) se comunicam basicamente por meio de trs mecanismos bsicos: Sequncia, Deciso e Iterao.

    Sequncia: Representa os passos para executar um programa: Leia um valor, repita esse valor 10 vezes, escreva na tela: Concludo.

    Deciso: Permite o uso de expresses lgicas: SE o valor for igual a x ENTO execute a funo Y.

    Iterao: Permite a execuo repetitiva de um determinado bloco de comandos.

    Benefcios da programao orientada a objetos:

    Reutilizao de cdigo: Com certeza uma das maiores vantagens da POO. Uma vez que voc escreveu um determinado cdigo, nunca mais ser reescrito, no mximo modificado atravs de algumas

  • tcnicas que veremos no decorrer do curso. Caracterstica tambm denominada DRY (Dont Repeat Yourself).

    Eficincia: A POO associada a melhor eficincia devido suas caractersticas inerentes.

    Refactoring: Facilidade na hora de modificar a estrutura interna de um cdigo, sem alterar o resultado final.

    Manutenibilidade: Facilidade na manuteno do sistema, mesmo quando escrito por terceiros.

    Pablo DallOglio define o paradigma da Orientao a Objetos em seu livro, PHP Programando com Orientao a Objetos como:

    A orientao a objetos um paradigma que representa toda uma filosofia para construo de sistemas. Em vez de construir um sistema formado por um conjunto de procedimentos e variveis nem sempre agrupadas de acordo com o contexto, como se fazia em linguagens estruturadas (Cobol, Clipper, Pascal), na orientao a objetos utilizamos uma tica um pouco mais prxima do mundo real.

    Lidamos com objetos, estruturas que j conhecemos do nosso dia-a-dia e sobre as quais possumos maior compreenso.

    Orientao a Objetos Estudo das Classes e Objetos

    O conceito de classe nada mais do que uma estrutura que define um tipos de dados, podendo conter variveis (chamaremos de atributos) e tambm funes (chamaremos de mtodos). Classes manipulam definies e objetos manipulam valores.

    Como exemplo, vamos criar uma classe denominada carro. Automaticamente somos levados a pensar em algumas caractersticas inerentes aos carros que conhecemos, chamaremos de propriedades:

    Propriedades do carro: Ano, modelo, cor, fabricante e etc..

    Agora vamos pensar no que o carro faz, chamaremos de mtodos:

    Mtodos: Locomover, frear, buzinar e etc..

    Seguindo esta linha de pensamento, vamos criar a classe que define o carro, com suas devidas propriedades e mtodos, e em seguida comentaremos.

  • Class Carro{ public $ano; public $modelo; public $cor; public $fabricante; }

    Para testar, crie um novo arquivo php, salve como Carro.class.php. No esquea das tags de abertura e fechamento do php (

  • Parte 2Dessa vez aprenderemos sobre os mtodos. Veremos tambm na prtica os mtodos de inicializao (construtor) e finalizao (destrutor).

    Ao final deste artigo, voc ser capaz de:

    Criar mtodos para suas classes Entender melhor a criao dos objetos Entender o mtodo construtor e destrutor

    Vamos agora criar uma classe chamada Pessoa:

    Class Pessoa{ public $nome; public $altura; public $nascimento; public $salario; }

    Agora vamos criar uma instncia de pessoa:

    $p1 = new Pessoa();

    Agora vamos preencher seus atributos:

    $p1->nome = "Jos da Silva";$p1->altura = 1.82;$p1->nascimento = "1989-01-22"$p1->salario = 3600;

    Podemos verificar os valores inseridos da seguinte forma:

    echo " Meu nome : ".$p1->nome.", minha altura ".$p1->altura.", nasci no dia ".$p1->nascimento." e hoje meu salrio de ".$p1->salario.".";

    Agora vamos criar um mtodo para a classe Pessoa, que trabalhar com as propriedades do objeto. O mtodo ter o nome MostrarPessoa() e basicamente servir para mostrar os dados do objeto.

    Lembre-se que mtodo age dentro do escopo da classe.

  • Classe alterada:

    Class Pessoa{ public $nome; public $altura; public $nascimento; public $salario; public function MostrarPessoa(){ echo "Nome: ".$this->nome; echo "Altura: ".$this->altura; echo "Nascimento: ".$this->nascimento; echo "Salario: ".$this->salario; } }

    Temos um novo conceito apresentado aqui. Trata-se da pseudo-varivel $this, que serve basicamente para diferenciar as propriedades do objeto de variveis locais. Lembre-se, $this referencia o objeto ATUAL e acessa suas propriedades.Agora vamos novamente reescrever o objeto Pessoa executando o mtodo MostrarPessoa():

    $p1 = new Pessoa();$p1->nome = "Jos da Silva";$p1->altura = 1.82;$p1->nascimento = "1989-01-22";$p1->salario = 3600;//executando o mtodo$p1->MostrarPessoa();

    Quando o mtodo for executado, todos os dados do objeto P1 sero mostrados na tela.

    Perceba que para criar um mtodo, iniciamos com a palavra reservada public (isso em PHP 5, falaremos a respeito dessa funcionalidade no decorrer do curso, por enquanto, entenda como o parmetro que define a visibilidade do mtodo), seguido da palavra reservada function e o nome do mtodo.

    A grosso modo, podemos dizer que mtodos so funes que agem dentro de uma classe.

    importante salientar que da mesma forma que criamos $p1, poderamos criar $p2, $p3 e etc, todos com caractersticas (atributos) diferentes, mas executando o mesmo mtodo MostrarPessoa().

    Vamos utilizar de um exemplo clssico para diferenciarmos classe de objetos:

  • Uma classe como uma receita de bolo. No comemos a receita de bolo, no verdade? A utilizamos como referncia para prepar-lo. A funo da classe semelhante a receita do bolo: Criamos um objeto bolo a partir das especificaes da receita.

    Voltando aos mtodos, vamos agora modelar uma classe um pouco mais completa, ela se chamar conta, e ter os mtodos Sacar, Depositar e ObterSaldo.

    class Conta{ public $Cliente; public $Agencia; public $Conta; public $Saldo; public $Status; /* Mtodo Sacar() * Diminui o saldo em quantia */ function Sacar($quantia){ if( $quantia > 0 ){ $this->Saldo -= $quantia; } } /* Mtodo Depositar() * Deposita uma quantia, acrescendo o saldo */ function Depositar($quantia){ if ( $quantia > 0 ){ $this->Saldo += $quantia; } } /* Mtodo ObterSaldo() * Retorna o saldo da conta */ function ObterSaldo(){ return $this->Saldo; } }

  • importante notar que o mtodo Depositar e o mtodo Sacar recebem valores e esses so atribuidos as variveis do objeto.O mtodo ObterSaldo no recebe nenhum valor, ele apensa retorna (return) o valor atual da varivel $saldo.

    Executando o cdigo:

    //criando o objeto conta$conta1 = new Conta(); //setando seus atributos$conta1->Cliente = "Jose da Silva";$conta1->Agencia = 0196;$conta1->Conta = "07126934-24";$conta1->Saldo = 5000; //executando os mtodos$conta1->Depositar(500);$conta1->sacar(100);echo $conta1->ObterSaldo();

    mostrado o valor 5400, retornado pelo mtodo ObterSaldo.

    Mtodo Construtor:

    O Construtor um mtodo (assim como o mtodo Depositar, Sacar e ObterSaldo) executado toda vez que um objeto instanciado a partir de uma classe. Geralmente utilizado para executar procedimentos de inicializao de atributos do objeto. Quando executado o comando $x = New automaticamente chamado o mtodo construtor daquela classe.

    Perceba que na classe Conta que criamos anteriormente, no criamos o tal mtodo construtor, neste caso, as propriedades do objeto so inicializadas com o valor NULL, da a necessidade de atribuir valores a todas as propriedades (Cliente, Agencia, Conta e Saldo).

    Mtodo Destrutor:

    Tambm um mtodo especial e executado sempre que atribumos o valor NULL a um objeto ou quando utilizamos a funo unset() e em ltima instncia, quando o programa finalizado. Este mtodo comumente usado para apagar arquivos temporrios, finalizar conexes e etc.

    A seguir vamos criar o mtodo construtor e destrutor para a classe Conta que criamos anteriormente:

  • class Conta{ public $Cliente; public $Agencia; public $Conta; public $Saldo; public $Status; /* Mtodo Construtor * Inicializa as propriedades */ function __construct($Titular,$Agencia,$Conta,$Saldo,$Status){ $this->Cliente = $Titular; $this->Agencia = $Agencia; $this->Conta = $Conta; $this->Saldo = $Saldo; $this->Cancelada = $Status; } /* Mtodo Destrutor * Finaliza os objetos */ function __destruct(){ echo "O Objeto foi destrudo. "; } /* Mtodo Sacar() * Diminui o saldo em quantia */ function Sacar($quantia){ if( $quantia > 0 ){ $this->Saldo -= $quantia; } } /* Mtodo Despositar() * Deposita uma quantia, acrescendo o saldo */ function Depositar($quantia){ if( $quantia > 0 ){ $this->Saldo += $quantia; } }

  • /* Mtodo ObterSaldo() * Retorna o saldo da conta */ function ObterSaldo(){ return $this->Saldo; } }

    Perceba que um construtor definido pelo mtodo: __construct() (usa-se dois underscores __) e no caso da classe conta, ele foi responsvel por definir todos os atributos do objeto.

    Vamos agora criar o objeto:

    $conta1 = new conta("Jose da silva", "0144", "07126934-24", 5000, "ativa");echo $conta1->ObterSaldo();

    Criamos o objeto conta em $conta1, e no momento de sua criao enviamos os parmetros que o construtor precisa para preencher os respectivos atributos.

    Na imagem abaixo possvel identificar a relao do construtor com o memento de criao do objeto:

    Construtor recebendo os parmetros

  • Na prxima aula apresentaremos a herana e o conceito de polimorfismo.

  • Parte 3Neste artigo vamos aprender o que herana e como ela funciona no PHP.

    Ao final deste artigo, voc ser capaz de:

    Entender e aplicar o conceito de herana

    Herana:

    Assim como no mundo real, a palavra se refere ao conceito de receber algo, herana aqui pode ser entendida como um mecanismo que permite construir uma nova classe com base em uma classe previamente existente, em que a nova herda automaticamente todos os atributos, comportamentos e implementaes da classe-pai.

    Quando se trata de herana, estamos falando de um dos maiores benefcios da Orientao a Objetos, alm da capacidade de encapsulamento (essa veremos a seguir, por enquanto, trate o encapsulamento como algo importante). Com a herana, podemos reutilizar partes de cdigo j definidas, alm da agilidade, ela elimina a necessidade de duplicar ou rescrever certo cdigo. Essas caractersticas nos permitem ao invs de escrevermos uma estrutura totalmente nova, reaproveitar a estrutura existente mesmo que a mesma nos fornea apenas uma base abstrata para o desenvolvimento.

    Para estender uma nova classe (chamaremos de subclasse), utilizamos a palavra reservada extends.

    Quando criamos uma subclasse, todos os mtodos pertencentes a classe pai podem ser executados. Tambm possvel sobrescrever os seus mtodos e propriedades, a fim de criar novos, com outras caractersticas. Se na subclasse escrito um mtodo com o mesmo nome do mtodo existente na classe pai, passa a vigorar o mtodo da classe filha (subclasse).

    Para acessar os mtodos sobrescritos ou membros estticos da classe pai, utilizamos a palavra reservada parent.

    importante destacar que somente os mtodos protect e public podem ser reescritos (veremos detalhes sobre isso mais a frente).

    Nada melhor que um exemplo para facilitar o entendimento por isso, vamos retornar a nossa classe pessoa e a partir dela criaremos a classe funcionrio, pois o funcionrio uma pessoa,

  • consequentemente, funcionrio herdar as caractersticas da classe pessoa, ao invs de duplicarmos tudo de novo na classe funcionrio.

    class Pessoa{ public $Nome; public $AnoDeNascimento; public $Endereco; public $Telefone; /* Mtodo Construtor * Inicializa as propriedades */ function __construct($Nome, $AnoDeNascimento, $Endereco, $Telefone){ $this->Nome = $Nome; $this->AnoDeNascimento = $AnoDeNascimento; $this->Endereco = $Endereco; $this->Telefone = $Telefone; } /* Mtodo EscreveDados() * Retorna os dados da Pessoa */ function EscreveDados(){ echo "Nome: {$this->Nome} Ano de nascimento: {$this->AnoDeNascimento} Endereo: {$this->Endereco} Telefone: {$this->Telefone}"; } /* Mtodo ObterIdade() * Retorna a idade */ function ObterIdade(){ $ano_atual = date("Y",time()); return $ano_atual - $this->AnoDeNascimento; }}

    Caso voc tenha dvidas quanto a esta classe, consulte as aulas anteriores.

    Agora vamos criar a classe Funcionrio, que ir herdar da classe Pessoa, fique atendo aos comentrios e no se preocupe caso no entenda alguma parte do cdigo, iremos explicar detalhadamente em seguida:

  • require_once("Pessoa.class.php"); class Funcionario extends Pessoa{ public $Salario; public $Cargo; public $DiaPagamento; /* Mtodo Construtor * Inicializa as propriedades */ function __construct($Nome, $AnoDeNascimento, $Endereco, $Telefone, $Salario, $Cargo, $DiaPagamento){ // Chamada do mtodo do construtor da classe-pai parent::__construct($Nome, $AnoDeNascimento, $Endereco, $Telefone); // Inicializa as variveis/propriedades locais da Classe $this->Salario = $Salario; $this->Cargo = $Cargo; $this->DiaPagamento = $DiaPagamento; } /* Mtodo EscreverSalario * Escreve o salrio do funcionrio */ function EscreverSalario(){ echo "Salrio: {$this->$Salario} "; } /* Mtodo EscreveDados() * Este mtodo sobrescreve o mtodo EscreveDados() da classe-pai */ function EscreveDados(){ parent::EscreveDados(); echo "Salrio: {$this->Salario} Cargo: {$this->Cargo} Dia de pagamento: {$this->DiaPagamento} "; } }

  • Testando nosso exemplo de herana:

    require_once("Funcionario.class.php"); $leandro = new Funcionario("Leandro Castro", 1985, "Rua das Flores 33 - Juiz de fora","(32) 3232-3535", 4.000, "Desenvolvedor Java/PHP", 8); echo $leandro->ObterIdade(); $leandro->EscreveDados();

    Para um melhor entendimento, voc deve colocar em prtica os exemplos, analisar e estuda-los.

    Vamos comear analisando a classe Funcionrio:

    require_once("Pessoa.class.php");

    Nesta linha estamos adicionando a classe pessoa ao documento, levando em considerao que a classe pessoa est em outro arquivo.

    class Funcionario extends Pessoa{

    Nesta linha estamos dizendo que a classe Funcionrio herdar todas as caractersticas de Pessoa. Desta forma, Pessoa ser a superclasse, enquanto Funcionrio, a subclasse de Pessoa.

    public $Salario; public $Cargo; public $DiaPagamento;

    Nesta parte declaramos as propriedades do Funcionrio. Mas funcionrio no teria que ter um nome? Deixamos de criar a propriedade nome pois ela j est criada na classe Pessoa, consequentemente a classe Funcionrio herdou essa propriedade, sendo assim, no necessrio cria-la novamente.

    Continuando:

    function __construct($Nome, $AnoDeNascimento, $Endereco, $Telefone, $Salario, $Cargo, $DiaPagamento){ // Chamada do mtodo do construtor da classe-pai parent::__construct($Nome, $AnoDeNascimento, $Endereco, $Telefone);

  • Se voc achou esta parte complicada, fique tranquilo, mais simples do que parece.

    Lembra que estamos trabalhando na classe Funcionrio, que uma subclasse de Pessoa, com isso, Funcionrio possui todos os mtodos de Pessoa. Vimos que o construtor tambm um mtodo, executado quando criamos o objeto e neste caso, estamos sobrescrevendo este construtor.

    A linha 4 retrata exatamente isso, estamos dizendo que o pai (parent::) que ir receber os dados (nome, anodenascimento, endereco e telefone) e a classe Funcionrio que ficar responsvel pelos demais dados (salario, cargo e diadepagamento).

    Se no declarssemos o mtodo construtor na classe Funcionrio, seria usado o da classe pai, ou seja, o mtodo construtor de Pessoa.

    function EscreverSalario(){ echo "Salrio: {$this->$Salario} "; }

    Se voc esta estudando com ateno, percebeu que este mtodo foi uma nova implementao, ele no exsite na classe pai, pois alm de herdar, voc pode criar novos mtodos e propriedades.

    function EscreveDados(){ parent::EscreveDados(); echo "Salrio: {$this->Salario} Cargo: {$this->Cargo} Dia de pagamento: {$this->DiaPagamento} "; }

    Esta parte tambm importante, perceba que o mtodo EscreveDados existe na classe pai (volte e verifique) mas foi sobrescrito, e acrescentamos a impresso dos campos de salrio, cargo e diadepagamento. Neste caso, ser impresso todos os atributos contidos na classe pai (parent::) no mtodo EscreveDados, e tambm os atributos do mtodo EscreveDados da classe filha, ou seja, um complemento do mtodo pai.

    Vale lembrar que o PHP no suporta herana mltipla, isso pode ser feito com o uso de interfaces (veremos no futuro).

  • Concluso:

    Com este recurso, expandimos nosso cdigo, sem reescreve-lo, isso extremamente comum quando se trata de criar novas funcionalidades em um software.

    Cabe a voc estudar e aplicar os conceitos que aprendeu aqui.

  • Parte 4Dessa vez explicaremos de forma detalhada o que e quando usamos o Polimorfismo.

    Ao final deste artigo, voc ser capaz de:

    Entender e aplicar o conceito do polimorfismo

    Polimorfismo:

    Polimorfismo sempre um gargalo no ensino da POO. Sei, pela dificuldade que meus alunos encontram ao tentar compreender este conceito atravs de livros ou manuais que, em sua maioria, contemplam exemplos complexos com uma linguagem confusa ou tcnica de mais.

    Tentarei expor neste artigo, o conceito e a aplicabilidade do polimorfismo em sua forma mais simples, evitando o over engineering sobre o assunto.

    O polimorfismo significa muitas formas ou algo que pode mudar sua forma. Em termos de programao, polimorfismo pode ser entendido como um nico nome de classe ou mtodos que represente um cdigo diferente.

    Lembre-se: mesmo nome, porm cdigo diferente.

    Vantagens:

    O polimorfismo facilita a reutilizao de cdigo. Facilita a manuteno, visto que no preciso utilizar vrias

    estruturas condicionais para simular situaes diferentes.

    Para entender, vamos utilizar o clssico exemplo do banco, que tem 2 tipos de cheques: Cheque Comum e o Cheque Especial.

    Ambos os cheques possuem a mesma estrutura, porm um cobra 20% de juros (comum) e o outro cobra 10 % (especial).Vamos modelar inicialmente a classe Cheque:

  • class Cheque{ public $Valor; /* Mtodo Construtor * Recebe o parmetro $Valor. */ function __construct($Valor){ $this->Valor = $Valor; } /* Mtodo CalcularJuros() * Calcula os Juros, neste caso 20% */ function CalcularJuros(){ return $this->Valor * 1.20; } /* Mtodo TipoCheque() * Retorna o tipo do Cheque */ function TipoCheque(){ return "Comum"; } }

    Estrutura bsica, caso voc tenha dvidas com relao ao cdigo, consulte as aulas anteriores.

    Agora vamos modelar a classe ChequeEspecial, que vai herdar a classe Cheque:

    /* Perceba a herana acontecendo * definida pela palavra extends */class ChequeEspecial extends Cheque{ /* Mtodo CalcularJuros() - Opa!! Mas esse mtodo j no tinha sido * implementado na classe anterior? Sim, est a o polimorfismo. * O juros do Cheque especial 10%, no 20 como o anterior */ function CalcularJuros(){ //Perceba que herdamos a propriedade Valor da classe pai return $this->Valor * 1.10; } /* Mtodo TipoCheque() - Tambm Sobrescrito

  • * uso explicito do polimorfismo */ function TipoCheque(){ return "Especial"; } }

    Agora vamos testar o exemplo:

    //Incluimos as duas classes require_once("Cheque.class.php"); require_once("ChequeEspecial.class.php"); // Criao dos cheques $Cheques[1] = new Cheque(380.00); $Cheques[2] = new ChequeEspecial(600.00); $Cheques[3] = new Cheque(230.00); // Percorrendo os Cheques foreach ( $Cheques as $key => $Cheque ) { echo "Cheque $key ( {$Cheque->TipoCheque()} ) com juros: R$ {$Cheque->CalcularJuros()} "; }

    Temos ai um exemplo claro do polimorfismo, onde ChequeEspecial herdou todas as caractersticas da classe cheque, entretanto o que difere as duas classes a ocorrncia do polimorfismo nos mtodos TipoCheque() e CalculaJuros().

    Perceba que a classe ChequeEspecial sobrescreveu o mtodo CalcularJuros da classe-pai e mudou seu comportamento. O mtodo calcular juros nos dois tipos de cheque igual, o que difere o comportamento deles.

    importante notar tambm que a classe ChequeEspecial herdou o mtodo construtor da classe-pai, para setar o atributo $Valor.

    No foreach estamos apenas percorrendo o Array de objetos.

    Terminamos assim mais um contedo do curso. No prximo artigo falaremos sobre Classes Abstratas, Classes Finais, Mtodos Abstratos e Mtodos Finais.

  • Parte 5Neste artigo entenderemos o conceito de abstrao. Veremos na prtica como se aplicam as classes abstratas, finais, mtodos abstratos e mtodos finais.

    Ao final deste artigo, voc ser capaz de: Entender o conceito de Abstrao Criar Classes Abstratas Criar Classes Finais Criar Mtodos Abstratos Criar Mtodos Finais

    Abstrao:

    Podemos considerar abstrao uma forma de separar mentalmente, simplificar ou mesmo considerar isoladamente. Um sistema orientado a objetos no deve ser visto como uma nica pea, devamos separ-lo em partes, concentrando nas peas mais importantes e ignorando os detalhes (em primeiro momento) para que possamos construir peas bem-definidas que possam ser reaproveitadas mais tarde, formando uma estrutura hierrquica.

    Sempre que estiver desenvolvendo um sistema OO, voc deve aplicar este conceito, abstraia ao mximo, concentre-se em separar o sistema em mdulos.

    Classes Abstratas e Mtodos Abstratos

    Seguindo o conceito de abstrao que acabamos de expor, encontraremos classes que iro servir como classes estruturais ou seja, que esto na nossa hierarquia de classes para servirem de base para outras classes, mas que nunca sero instanciadas em objetos, somente suas filhas. Neste contexto, interessante definir est classe como abstrata, de modo que ningum consiga instancia-la.

    A grosso modo, classe abstrata nada mais do que um modelo comum, que deve ser seguido pelas classes filhas, nunca instanciado em objeto ou seja, no existe isoladamente.

    Mtodos abstratos possuem uma definio semelhante, no podem ser implementados nas classes abstratas, deve ser definido somente a assinatura do mtodo e deve obrigatoriamente, ser implementado na integra pela classe filha que o estender. Em suma, um mtodo

  • abstrato definido em uma classe abstrata, mas deve conter somente sua assinatura, o corpo do mtodo fica por conta das classes filhas.

    Com exemplo fica ainda mais fcil de entender:

    /*Definimos uma classe como abstrata * utilizando a palavra reservada abstract * antes da palavra class */ abstract class Animal{ public $nome; public $idade; //O mtodo construtor seta os dois atributos function __construct($nome, $idade) { $this->nome = $nome; $this->idade = $idade; } //O mtodo descrio retorna o nome e a idade public function Descricao() { return $this->nome . ", " . $this->idade . " anos de idade"; } /*O mtodo Falar deve *ser implementado na classe filha *perceba que ele no tem implementao */ abstract public function Falar();}

    Temos nessa classe todas as caractersticas comuns de um animal.

    Todo animal possui um nome e todo animal possui uma idade, todo animal fala (o cachorro faz Au Au, o gato faz Miau). Perceba que o mtodo Falar no possui nada implementado, alm disso, a definio do mtodo precedida pela palavra abstract, o que significa que o mtodo deve ser implementado em TODAS as classes que estenderem a classe Animal.

    Estamos levando para o mundo OO uma definio que temos no mundo real, veja: Um cachorro, um gato, um cavalo so animais, cada um com suas caractersticas especificas, mas todos so animais, todos possuem nome, idade e falam. No faria sentido criar o objeto Animal.

    Se tentarmos instanciar a classe animal teramos o seguinte erro:

  • Fatal error: cannot instantiate abstract class Animal in animal.class.php on line 5

    Obviamente agora temos que criar uma subclasse de Animal, chamaremos de Cachorro.

    // Herdamos a classe Animalclass Cachorro extends Animal{ /* Somos obrigados a implementar * o mtodo falar */ public function Falar() { return "Au Au!"; } /* Vamos tambm complementar * o mtodo Descricao */ public function Descricao() { return parent::Descricao() . ", eu sou um cachorro!"; }}

    Agora podemos instanciar a classe Cachorro sem problemas:

    $animal = new Cachorro("Rex", 5);echo $animal->Descricao();echo $animal->Falar();

    Da mesma forma que criamos a classe Cachorro, poderamos criar a classe Gato, Cavalo, Pato, todas herdando da classe Animal.

    Classes Finais:

    Classes finais podem ser definidas como classes que no podem ser estendidas ou seja, no pode ser uma superclasse.

    Uma classe definida como final quando colocamos a palavra reservada final antes da palavra class.

    final class Cachorro{ public $nome; public $idade; function __construct($nome, $idade) { $this->nome = $nome; $this->idade = $idade; }

  • public function Descricao() { return $this->nome . ", " . $this->idade . " anos de idade"; }}

    A classe cachorro definida aqui, no pode ser herdada por nenhuma outra classe.

    Mtodos finais:

    Assim como classes finais, um mtodo final no pode ser estendido e obviamente no pode ser abstrato, pois mtodos abstratos foram feitos para serem estendidos e declarados na classe filha.

    Para declarar um mtodo como final basta usar a palavra reservada final antes da palavra function.

    Class Cachorro{ public $nome; public $idade; /* Este mtodo no pode * se estendido (sobrescrito) */ final function Descricao() { return $this->nome . ", " . $this->idade . " anos de idade"; }}

    Terminamos assim mais um mdulo do curso.No prximo artigo falaremos sobre o encapsulamento.

  • Parte 6Neste artigo voc aprender o conceito de encapsulamento, alm de aplicar a visibilidade de mtodos e propriedades.

    Ao final deste artigo, voc ser capaz de:

    Entender o significado do encapsulamento para a POO; Entender e aplicar a visibilidade dos mtodos e propriedades.

    Encapsulamento

    um dos recursos mais interessantes que a programao orientada a objetos nos fornece. Trata-se de um mecanismo que prov proteo de acesso aos membros internos de um objeto.

    Alguns mtodos e propriedades devem ser s de responsabilidade da classe-pai. Sem os modificadores de acesso, ela perde esta responsabilidade, fazendo com que outras classes tenham acesso a estes mtodos e propriedades.

    Para atingir o encapsulamento, uma das formas definindo a visibilidade das propriedades e dos mtodos de um objeto. A visibilidade define a forma como essas propriedades devem ser acessadas. Existem trs formas de acesso:

    1. private: Este modificador no permite ser acessado por classes descendentes (classes-filhas), s pode ser acessado dentro da prpria classe.

    2. public: Este modificador o default (padro), ou seja, quando um mtodo no tiver um modificador de visibilidade definido, ele sempre ser public. Public significa que o mtodo ou propriedade em questo pode ser acessado por todas as outras classes e mtodos sem quaisquer restries.

    3. protected: Pode ser acessado apenas por mtodos da prpria classe e classes filhas.

    Podemos dizer que o encapsulamento nos permite ocultar tudo aquilo que no importante, ou seja, detalhes internos do funcionamento da classe so ocultos para os objetos. O objeto s conhece o que necessrio, o que ele no precisa saber/conhecer, fica oculto (a nvel de objeto).

  • Private

    At agora, nos artigos anteriores, declaramos classes como public e no definimos visibilidades dos mtodos. Vamos iniciar com um exemplo prtico, para facilitar a compreenso.

    A proposta criar uma classe chamada Fornecedor e marcaremos algumas das propriedades como private. Dessa forma, os elementos private s podero ser alterados por mtodos da mesma classe.

    Deixaremos para livre acesso, o nome e o valor, marcado como public.

    class Fornecedor{ private $Id; //identificao public $Nome; //nome do produto private $Compra; //valor de compra public $Valor; //valor de venda }

    Observe a imagem abaixo:

    Eclipse exibindo apenas as propriedades pblicas da classe Fornecedor

    Criamos o objeto Fornecedor e ao definir as propriedades, o prprio Eclipse, atravs de sua funo autocomplete, carregar somente as funes pblicas (public). Perceba que ele no exibe na lista as funes privadas (private).

  • Se mesmo assim voc tentar algo como:

    $empresa1 = new Fornecedor();$empresa1->Compra = 400;

    Ser retornado uma mensagem de erro, pois a propriedade Compra privada (private).

    Ok, mas como fao para atribuir algo a essa propriedade caso necessrio?

    Se voc fez essa pergunta, parabns!

    Para atribuir algo, basta criar um mtodo pertencente a classe Fornecedor que manipule estas propriedades. Que tal chamarmos de Set para definir e Get para obter o contedo dos atributos?

    Veja o exemplo:

    class Fornecedor{ private $Id; //identificao public $Nome; //nome do produto private $Compra; //valor de compra public $Valor; //valor de venda /* Olha o mtodo setCompra() * que vai definir um valor para * a propriedade $Compra*/ public function setCompra($Compra){ if (is_numeric($Compra) && $compra > 0) { $this->Compra = $Compra; } }/* Vamos agora criar o mtodo * getCompra que vai retornar * o contedo da propriedade $compra*/ public function getCompra(){ return $this->Compra; }}

  • Agora que criamos o mtodo get e set para a propriedade $Compra, possvel realizar a chamada normalmente:

    $empresa1 = new Fornecedor();$empresa1->Nome = "Vale";$empresa1->setCompra(400);echo "O valor do produto ".$empresa1->Nome." de ".$empresa1->getCompra();

    O interessante neste caso, perceber que para um determinado valor chegar a propriedade $Compra, ele deve passar pelo mtodo setCompra. Isso nos traz um controle maior sobre a aplicao visto que, voc pode realizar vrias operaes antes da chagada do valor, neste caso perceba que no mtodo setCompra, checamos se o valor um nmero (is_numeric) e se maior que zero.

    Poderamos criar um set e um get para mais elementos definidos como private mas cuidado, utilize os Getters e Setters somente quando existe a real necessidade, variveis internas ou que no precisam de nenhum tipo de verificao ou tratamento, no utilize.

    Prefira sempre utilizar mtodos Getter e Setters ao invs de um campo pblico (public) mas lembre-se, simplificar a alma da POO, criar dezenas de mtodos no simplifica.

    Protected

    Vimos no exemplo anterior, o uso do parmetro de visibilidade private. Vale ressaltar que quando uma propriedade definida como private, ela no pode ser sobrescrita por classes filhas, ou seja, uma classe filha no consegue chamar os mtodos setters e getters da classe pai (no caso do atributo estar como private).

    Caso voc tenha uma classe Funcionrio com o mtodo setSalario e o atributo Salrio do tipo private, e crie a subclasse Estagirio, voc no consegue chamar o mtodo mesmo fazendo uso da herana, est uma caracterstica do private.

    Em outras palavras, se um atributo do tipo private, ele s funciona na classe que foi declarado, caso voc queira fazer uso do mesmo em outras classes (filhas) necessrio modificar o tipo para Protected.

  • Veja:

    class Funcionario{ private $Id; private $Nome; private $Nascimento; private $Salario; function setSalario($Salario){ if (is_numeric($Salario) && $Salario > 0) { $this->Salario = $Salario; } } function getSalario(){ return $this->Salario; } }

    Agora, vamos criar a classe Estagirio, que ser uma subclasse de Funcionrio.

    class Estagiario extends Funcionario { /* Mtodo getSalario ser * sobrescrito pois o estagirio * neste modelo possui um bnus * de 10% */ function getSalario(){ return $this->Salario * 1.10; } }

    Depois das duas classes criadas, vamos criar o objeto estagirio:

    $junior = new Estagiario;$junior->setSalario(300);echo "O salario : ".$junior->getSalario;

    Essa ao resultaria em um erro. Isso ocorre porque a propriedade $Salario uma propriedade private, o que significa que ela somente pode ser acessada de dentro da classe em que ela foi declarada, neste caso, a classe Funcionrio.

    Para que as subclasses consigam acessar uma propriedade da classe pai, definimos como protected.

  • Exemplo:

    class Funcionario{ private $Id; private $Nome; private $Nascimento; protected $Salario; function setSalario($Salario){ if (is_numeric($Salario) && $Salario > 0) { $this->Salario = $Salario; } } function getSalario(){ return $this->Salario; } }

    Agora podemos criar a classe Estagirio da mesma forma que fizemos no exemplo anterior e em seguida criar o objeto:

    $junior = new Estagiario;$junior->setSalario(300);echo "O salario : ".$junior->getSalario;

    Com essa pequena modificao, tornamos o atributo $Salario extensvel a todas as classes que forem criadas a partir da classe Funcionrio. Este exemplo no retornaria erro.

    Public

    Explicar o comportamento do modificador de acesso public simples, pois a propriedade padro do PHP. Basicamente, quando no definido a visibilidade, ela ser pblica ou seja, voc pode modificar, herdar ou atribuir sem nenhum impedimento, no necessrio os mtodos Getters e Setters para propriedades pblicas.

    Terminamos aqui mais um artigo.

    No prximo veremos constantes e propriedades estticas.

  • Parte 7Neste artigo veremos constantes, propriedades estticas e mtodos estticos.

    imagem meramente ilustrativa

    Ao final deste artigo, voc ser capaz de:

    Entender o conceito de constantes na POO; Entender o conceito de propriedades estticas; Entender o conceito de mtodos estticos.

    As classes permitem armazenar valores de duas formas: constantes de classe e propriedades estticas. Estes atributos so comuns em todos os objetos da mesma classe.

    Constantes

    Primeiro vamos definir o que constante.

    Uma constante exatamente o oposto de uma varivel, ou seja, algo que mantm seu valor at o final do script (salvo alguma excees).

    Geralmente definimos uma constante perto do incio do cdigo ou em uma funo.

    A declarao de constantes feita atravs da palavra-chave const.

    Para acessar constantes de classe fora do escopo dela, a seguinte notao utilizada NomeClasse::Constante; e j dentro da classe, utilizamos a notao self::Constante. A palavra-chave self tambm pode ser utilizada para referenciar a prpria classe.

  • Vamos analisar:

    /* Vamos declarar uma * constante chamada pi*/class Funcoes{ const Pi = 3.14;} /* Vamos herdar Funcoes* e criar outra constante*/ class Aplicacao extends Funcoes{ const Versao = 3.8; function __construct($Nome){ echo $Nome. "< br/>"; echo self::Versao . "< br />"; echo parent::Pi . "< br />"; echo Funcoes::Pi . "< br />"; }} $sistema1 = new Aplicacao("CafeeSoftware");

    Perceba que acessamos a constante Pi tanto pela sintaxe:

    Funcoes::Pi, quanto pela sintaxe: parent::Pi.

    Lembre-se que parent se refere a classe-pai. E Pi da classe-pai de Aplicao. Self refere-se a classe em questo.

    Propriedades e mtodos estticos

    Podemos considerar que propriedades e mtodos estticos podem ser acessados sem a necessidade de instanciar um objeto. Utilizamos este recurso quando, por exemplo, temos um mtodo que acessado diversas vezes na mesma aplicao, e queremos economizar algumas linhas de cdigo a fim de no ter que criar um objeto a todo momento. importante destacar que um mtodo esttico no pode fazer referencia a propriedades internas pelo operador $this, pois este operador usado para referenciar instncias da classe ou seja, objetos.

    Utilizamos a palavra chave static para definir a declarao de membros estticos.

  • Vamos ao exemplo:

    class Teste{ public static $propriedade = "Esta uma propriedade esttica"; public static function MetodoEstatico(){ echo "Este um mtodo esttico"; }} /* Para acessar simples,* perceba que no necessrio* criar o objeto.*/ echo Teste::$propriedade;//Agora o mtodoTeste::MetodoEstatico();

    Membros estticos tambm podem ser acessados internamente utilizando o operador self (o mesmo que vimos anteriormente), veja:

    class Teste{ public static $propriedade = "www.cafeesoftware.com - Transformando Caf em Software"; public static function RetornaPropriedade(){ return self::propriedade; } public static function UsarMetodoRetorna(){ return self::RetornaPropriedade(); }}// Para acessar:echo Teste::RetornaPropriedade();Teste::UsarMetodoRetorna();

    Quando se tratar de uma subclasse herdando propriedades ou mesmo mtodos estticos, a referncia feita normalmente atravs da palavra reservada parent, como j vimos anteriormente.

    No prximo artigo estudaremos os relacionamentos: Composio, agregao e associao. Veremos na prtica quando ocorre cada um deles e sua utilizao no PHP.

  • Parte 8Dessa vez, estudaremos o relacionamento entre objetos. Veremos na prtica como se d uma relao de associao, agregao e composio. Ao final deste artigo, voc ser capaz de:

    Entender como se da a relao entre objetos Entender quando se d um relacionamento de associao,

    agregao e composio

    Imagem meramente ilustrativa

    Em OO comum que objetos se relacionem um com os outros para desempenhar suas tarefas. Neste tutorial veremos os tipos de relacionamentos existentes.

    Associao:

    a relao mais comum entre dois objetos. Quando acontece? Quando uma classe usa outra classe.

    Exemplo: Um motorista utiliza (depende do carro, mas este no faz parte do motorista) o carro para trabalhar.

    Agregao:

    o tipo de relao conhecida como todo/parte. Na agregao o objeto agrega outro objeto, ou seja, torna um objeto externo parte de si.. Assim o objeto pai poder utilizar funcionalidades do objeto agregado, mas ele no depende dele (agregado) para existir.

    Exemplo: A tampa de uma caneta parte da caneta, se a caneta no tiver a tampa, ela no deixar de ser uma caneta.

  • Composio:

    Neste caso, o objeto-pai responsvel pela criao e destruio de suas partes. O objeto-pai realmente possui as instncias de suas partes. Resumidamente, um s existe caso o outro tambm exista.

    Exemplo: O motor de um carro parte fundamental do carro.

    Agora que voc j conhece na teoria os tipos de relacionamento, que tal vermos na prtica?

    Associao:

    A forma mais comum de associao quando temos um objeto como atributo de outro. Criaremos um objeto Produto e outro Fornecedor. Onde Fornecedor um dos atributos de Produto.

    Vamos analisar o diagrama UML:

    Associao entre Produto e Fornecedor

    Observe que uma das propriedades (Fornecedor), espera receber um objeto do tipo Fornecedor.

    Vamos agora criar as duas classes e em seguida os objetos.

    class Produto{ public $Id; public $Nome; public $Valor; public $Fornecedor; public function __construct($Id, $Nome, $Valor, $Fornecedor){ $this->Id = $Id; $this->Nome = $Nome; $this->Valor = $Valor; $this->Fornecedor = $Fornecedor; } } class Fornecedor{ public $Id; public $RazaoSocial;

  • public $Endereco; public $Telefone; public function __construct($Id, $RazaoSocial, $Endereco, $Telefone){ $this->Id = $Id; $this->RazaoSocial = $RazaoSocial; $this->Endereco = $Endereco; $this->Telefone = $Telefone; } } $fornecedor = new Fornecedor(359, "Mercado da Casa", "Rua B", "3232-2222" ); $produto = new Produto(122, "Caf 250g", 2.85, $fornecedor ); echo "Cdigo: " . $produto->Codigo . "< br />";echo "Produto: " . $produto->Nome . "< br />";echo "Fornecedor: " . $produto->Fornecedor->RazaoSocial . "< br />";

    Perceba que, ao criar o objeto Produto, passamos o objeto Fornecedor, em seguida, para imprimir fizemos uma referenciao de Produto e Fornecedor.

    Agregao:

    Conforme visto anteriormente, esta relao se d quando temos o TODO/PARTE.

    Uma forma de exemplificar sua implementao e com o clssico exemplo de um carrinho de compras.

    Teremos duas classes, produto (bem parecido com a que vimos anteriormente) e a classe Carrinho.

    Observe o diagrama:

    Relao de Agregao

    Importante destacar que a propriedade Itens um array, poderia ser representando como: Itens[] : Produto.

  • Observer que a classe Carrinho possui dois mtodos, ExibeLista() e o CalculaTotal().

    Vamos criar codificar as duas classes e em seguida criar os objetos:

    class Produto{ public $Id; public $Nome; public $Valor; public function __construct($Id, $Nome, $Valor){ $this->Id = $Id; $this->Nome = $Nome; $this->Valor = $Valor; } }

    Agora vamos criar a classe Carrinho:

    class Carrinho{ private $itens; public function InsereProduto(Produto $item){ $this->itens[] = $item; } public function ExibeLista(){ foreach( $this->itens as $item ){ return $item->nome."< br />; } } public function CalculaTotal(){ $valor_total = 0; foreach( $this->itens as $item ){ $valor_total += $item->Valor; } echo " R$ " . number_format($valor_total, 2, ',', '.'); } }

  • Vamos as explicaes: Repare que na linha 5 da classe Carrinho estamos obrigando o $item a ser do tipo Produto. Este um conceito conhecido como TypeHinting ou Sugesto de tipo, caso este mtodo receba algo que no seja um Produto, ocasionar um erro.

    Na linha 7 estamos inserindo cada produto no array $itens.

    O mtodo ExibeLista apenas percorre o array de itens exibindo o nome de cada produto.

    O mtodo CalculaTotal percorre o array de itens somando o valor de cada um e em seguida mostrando (formatado) o valor final.

    Vamos testar?

    $produto1 = new Produto(1, "Milho verde", 1.75);$produto2 = new Produto(2, "Ervilha", 1.65);$produto3 = new Produto(3, "Caf 250Gr", 3.45);$produto4 = new Produto(4, "Refrigerante 2L", 3.69); $CarrinhoCompra = new Carrinho();$CarrinhoCompra->InsereProduto($produto1);$CarrinhoCompra->InsereProduto($produto2);$CarrinhoCompra->InsereProduto($produto3);$CarrinhoCompra->InsereProduto($produto4); $CarrinhoCompra->ExibeLista();$CarrinhoCompra->CalculaTotal();

    Ao executar, voc perceber que a lista de itens (nome) ser exibida, seguido do valor total.

    Composio:

    A diferena da composio para a agregao que quando o objeto todo destrudo, suas partes tambm so, exatamente por terem sido criadas pelo objeto todo. Podemos dizer que na composio o objeto-pai possui as instncias de suas partes.

    Observe a notao para a composio:

    Relao de Composio

  • Neste exemplo, a classe cliente ser responsvel por instanciar contato. Vamos agora codificar para entender melhor:

    class Contato{ public $Nome; public $Email; public $Telefone; /* Mtodo setContato() * Grava informaes de contato */ public function setContato($Nome, $Email, $Telefone){ $this->Nome = $Nome; $this->Email = $Email; $this->Telefone = $Telefone; } /* Mtodo EscreveContato() * Escreve as informaes de contato */ public function EscreveContato(){ echo "Nome: " . $this->Nome . "< br />"; echo "Email: " . $this->Email . "< br />"; echo "Telefone: " . $this->Telefone . "< br />"; } }

    Agora vamos criar a classe Cliente:

    class Cliente{ public $Codigo; public $Endereco; public $Contato; /* Mtodo construtor() * Construtor da classe */ public function __construct(){ /* Instancia um novo Contato * Perceba que isso s feito * aqui. No feito fora dessa * classe */ $this->Contato = new Contato(); }

  • /* Mtodo setContato() * Grava informaes de contato */ public function setContato($Nome, $Email, $Telefone){ // Chama e envia informaes para o objeto Contato $this->Contato->setContato($Nome, $Email, $Telefone); } /* Mtodo EscreveContato() * Escreve as informaes de contato */ public function EscreveContato(){ // Chama um mtodo do objeto Contato $this->Contato->EscreveContato(); } }

    Perceba que a classe Cliente s existe se tambm existir a classe Contato. Uma aplicao clara da relao de composio. Vamos agora testar o exemplo:

    $leandro = new Cliente();$leandro->Codigo = 7;$leandro->setContato("Leandro","[email protected]","(33) 3333-3333");$leandro->Endereco = "Rua 13 de maio"; $leandro->EscreveContato();echo "Endereo: " . $leandro->Endereco;

    Note que em nenhum momento instanciamos Contato, pois quem faz isso a classe Cliente, da a relao de composio.

    Finalizamos assim mais um artigo do curso.

    Na prxima aula veremos os mtodos __set(), __get() e __call() conhecidos como mtodos interceptores.

  • Parte 9Dessa vez, estudaremos os mtodos interceptores, tambm conhecidos como mtodos mgicos.

    Imagem meramente ilustrativa

    Ao final deste artigo, voc ser capaz de:

    Entender o que so os mtodos interceptores; Fazer uso dos mtodos __set(), __get() e __call().

    Intercepes:

    Mtodos de intercepo so mtodos especiais predefinidos no PHP. Seus nomes so reservados, todos prefixados com dois caracteres _ (underscore) no incio.

    Os mtodos __set(), __get() e __call so alguns desses mtodos. Trata-se de mtodos opcionais e geralmente utilizados para executarem aes consideradas especiais e especficas.

    __set()

    O mtodo __set() invocado toda vez que um atributo no declarado da classe recebe a atribuio de um valor. Este mtodo espera dois parmetros, o primeiro contendo o nome do atributo e o segundo seu valor.

    Em resumo, toda vez que for atribudo um valor a uma propriedade do objeto, automaticamente esta atribuio passa pelo mtodo __set().

  • Para facilitar o entendimento, vamos ao exemplo:

    /* Vamos crair a classe Pessoa* com somente uma propriedade* chamada Idade.*/class Pessoa{ private $Idade; /* Quando tentarmos * atribuir um valor * para a propriedade idade * o mtodo __set() entre em ao */ public function __set( $propriedade, $valor ){ if( $propriedade == "Idade" ){ if( is_integer($valor) && strlen($valor) > 1 ){ $this->Idade = $valor; echo "Valor: " . $valor . " Atribudo propriedade: " . $propriedade; }else{ echo "Valor: " . $valor . "NO atribudo propriedade: " . $propriedade; } } } } $leandro = new Pessoa();$leandro->Idade = 27;

    Observe que criamos o objeto normalmente (linha 36) e quando fomos atribuir 27 a propriedade idade do objeto, nosso amigo __set() interceptou, validou e s assim, permitiu ou no que o valor chegasse de fato ao atributo $idade.

    Lembre-se, o __set() sempre espera dois parmetros: $propriedade e $valor. Esses sempre devem ser verificados.

    Imagine que em sua aplicao voc possui a propriedade senha. Voc pode utilizar o __set() para validar se a senha informada pelo usurio atende todos os requisitos necessrio e s depois, a propriedade recebe o contedo (caso hipottico).

  • __get()

    Anlogo ao mtodo __set(), o __get() chamado quando um atributo da classe precisa ser retornado para o objeto. Ele espera um parmetro, que ser preenchido com o nome do atributo chamado.

    Para exemplificar melhor o uso do __get(), vamos ao exemplo:

    class Carro{ public $Nome; private $Valor; const MargemLucro = 8; public function __construct($Nome, $Valor){ $this->Nome = $Nome; $this->Valor = $Valor; } /* Quando o usuario requisitar * uma propriedade, o __get() * ir interceptar, verificar se a * propriedade a "Valor" e realizar * o ajuste da margem de lucro */ function __get($Propriedade){ if( $Propriedade == "Valor" ){ $valor_reajustado = $this->Valor * ( 1 + self::MargemLucro / 100 ); return "R$ " . number_format($valor_reajustado, 3, ',', '.'); } } } $vectra = new Carro("Vectra 2.0", 40.000);echo $vectra->Valor;

    Perceba que ao executar, quando realizamos a requisio a propriedade Valor, o mtodo __get() faz a intercepo, ajusta o valor para a margem de lucro pr-definida alm de formatar e s assim o valor e entregue.

    Esta um uso clssico do mtodo __get().

    __call()

    Diferente dos mtodos __set() e __get(), o mtodo __call() entra

  • em ao quando feita uma chamada a um mtodo (no mais uma propriedade) que no existe. Sempre que um mtodo no existir no objeto, automaticamente a execuo ser direcionada para ele que tambm recebe dois parmetros, o nome e o parmetro informados, assim ele pode decidir o que fazer nesta situao.

    Vamos ao exemplo para entender melhor:

    class Carro{ public $Nome; private $Valor; const MargemLucro = 8; public function __construct($Nome, $Valor){ $this->Nome = $Nome; $this->Valor = $Valor; } //Este o mtodo que far a intercepo function __call($Metodo, $Parametros){ echo "Mtodo executado: " . $Metodo; echo "Parmetros do mtodo:"; // Um array para mostrar os parametros passados foreach ( $Parametros as $Chave => $Parametro ){ echo "Parmetro {$Chave} = " . $Parametro; } } } $vectra = new Carro("Vectra s.0", 40.000);// Opa!! Que mtodo esse?? Ah, deixa que o __call cuidaecho $vectra->DefineCaracteristicas("Preto",2.0,"4 portas");

    Ao executar, ser mostrado todas as caractersticas passadas pelo mtodo DefineCaracteristicas, justamente pela intercepo realizada pelo mtodo __call(). Mesmo no tendo este mtodo na classe.

    Existem diversos outros mtodos considerados especiais, clique aqui para consultar a lista completa.

    Lembre-se que estes mtodos foram projetados para facilitar a vida do programador, grandes frameworks como Zend fazem uso dessa funcionalidade para atribuir de forma dinmica nas camadas do modelo de viso. Falaremos sobre frameworks em breve.

  • Terminamos assim mais uma aula.

    Utilize o espao de comentrios para dvidas, crticas, elogios ou sugestes. sempre um prazer ler sua opinio sobre meu contedo.Gostaria de agradecer novamente pelos comentrios que venho recebendo.

    Na prxima aula estudaremos um pouco mais sobre mtodos, desta vez o __autoload(), alm de conhecermos algumas funes para manipulao de objetos.

  • Parte 10Veremos dessa vez o o mtodo especial __autoload e algumas funes para manipulao de objetos.

    Ao final deste artigo, voc ser capaz de:

    Utilizar o mtodo __autoload para carregar suas classes; Utilizar os mtodos:

    o get_class_methods, is_a, get_parent_class, get_objetct_vars e get_class_vars.

    O mtodo __autoload()

    A partir da verso 5 do PHP, foi inserido uma nova forma de carregar classes. Essa abordagem para carregamento sob demanda feita atravs da funo __autoload. Est funo permite que o desenvolvedor no tenha que declarar uma longa lista de includes ou require_once no incio de cada script.

    O que fizemos at agora foi criar as classes de forma isolada e inclu-las separadamente em um arquivo.

    Veja o exemplo:

    Arquivo Classe1.class.php

    class Classe1{ public $propriedade;}

    Arquivo Classe2.class.php

    class Classe2{ public $propriedade;}

    Arquivo Classe3.class.php

    class Classe3{ public $propriedade;}

    Agora suponhamos que seja necessrio carregar todas essas 3 classes em um arquivo. O procedimento normal seria:

  • Arquivo Carregar.php

    //incluindo os arquivosrequire_once("Classe1.class.php");require_once("Classe2.class.php");require_once("Classe3.class.php");// $ob1 = new Classe1();$ob2 = new Classe2();$ob3 = new Classe3();

    Observe que quanto mais classes forem utilizadas, maior o nmero de arquivos que devem ser carregados no incio do script.

    Para aliviar a vida do programador, alm de ser uma boa prtica, podemos fazer uso da funo __autoload substituindo o bloco de require_once.

    Vamos ao exemplo:

    Suponha que os arquivos Classe1.class.php, Classe2.class.php e Classe3.class.php j estejam criados.

    Arquivo Carregar.php

    //novo mtodofunction __autoload($classe){ //verificamos o nome do arquivo dir = $classe .".class.php"; //confirmando se o arquivo existe if (file_exists(dir)){ //se exister, faz a incluso require_once($dir); }}//Agora podemos criar os objetos normalmente$ob1 = new Classe1();$ob2 = new Classe2();$ob3 = new Classe3();

    Perceba que o nome da classe a ser instanciada deve ser o incio do nome do arquivo. Dessa forma no termos problemas ao criar os objetos.

  • Agora que conhecemos o mtodo __autoload, vamos estudar algumas funes para manipulao de objetos. Certamente no futuro voc far uso de algumas delas.

    get_class_methods

    Esta funo responsvel por retornar os nomes dos mtodos de uma classe. Este retorno se da por meio de um vetor.

    Suponha que uma classe chamada Carro tenha os mtodos: Acelerar, Frear e Ligar.

    Agora vamos executar a funo:

    print_r(get_class_methods('Carro'));

    O retorno seria:

    Array([0]=>Acelerar [1]=>Frear [2]=>Ligar);

    Is_a

    Verifica o tipo de uma classe. Vamos considerar a classe Funcionario. Em seguida, vamos criar uma classe filha chamada Estagiario.

    class Funcionario{ public $codigo; public $nome;} class Estagiario extends Funcionario{ public $bolsa; }

    Agora que vamos criar um objeto do tipo Estagirio e em seguida verificar o tipo.

    $junior = new Estagiario(); //verificando if (is_a($junior, "Funcionario")){ echo "Objeto do tipo funcionario.";} else { echo "Objeto no do tipo funcionario.";}

    Ao executar, como o objeto to tipo funcionrio, a primeira mensagem seria chamada: Objeto do tipo funcionario.

  • get_parent_class

    Basicamente o que o get_parent_class faz retornar a classe-pai de um objeto. Considerando a mesma estrutura do exemplo anterior (classe Funcionario e a classe Estagirio), a execuo da funo se daria da seguinte forma:

    $junior = new Estagiario();echo get_parent_class($junior);

    O retorno dessa funo seria o nome da classe pai:

    Funcionario

    get_objetct_vars

    Esta funo retorna o nome e contedo das propriedades de um objeto. Vamos analisar o exemplo:

    class Funcionario{ public $codigo; public $nome; public $salario;} $maria = new Funcionario();$maria->codigo = 100;$maria->nome = "Maria da Silva";$maria->salario= 3000; //Chamamos a funo print_r(get_object_vars($maria));

    O resultado seria:

    Array([codigo] =>100 [nome]=>"Maria da Silva" [salario]=>3000)

    get_class_vars

    Utilizada para retornar (tambm em forma de array) as propriedades de uma classe.

    Vamos ao exemplo:

    class Funcionario{ public $codigo; public $nome; public $salario;}//chamando a funo

  • print_r( get_class_vars('Funcionario'));

    O resultado:

    array([codigo]=>[nome]=>[salario]);

    Assim terminamos mais uma aula.

    Na prxima, estudaremos de forma detalhada o tratamento de erros, prtica fundamental para um bom programador.

  • Parte 11Dessa vez, veremos o tratamento de erros no PHP, prtica fundamental para o desenvolvimento com qualidade.

    Ao final deste artigo, voc ser capaz de:

    Utilizar as funes de tratamento de erros com: die(), trigger_error(), set_error_handler e error_log;

    Realizar o tratamento de excees.

    Tratar erros considerado uma boa prtica quando o assunto desenvolvimento de sistemas. Essa prtica diferencia programadores de verdade de curiosos, seu cdigo fonte ser muito mais valorizado, seguro e robusto quando aplicado as tcnicas de tratamento.

    No PHP existem trs tipos de erros: Notices (notificaes), Warnings (alertas) e os Fatals (fatais). Os erros fatais quando ocorrem fazem com que o script finalize de forma imediata. Pode ocorrer quando, por exemplo, uma funo ou um mtodo que no existe chamado.

    A funo die()

    Antes de explicar sobre a funo die(), vale ressaltar que seu uso deve ser cuidadoso, pois quando chamada, a funo die() interrompe a execuo do script. Podemos dizer que se trata de uma funo muito radical, por isso, seu uso no recomendvel, salvo alguma excees.

    Vamos analisar:

    //verificando se o mtodo Teste() existeif (function_exists("Teste")){ //Caso exista, executamos echo Teste();} else { /*Caso no exista * interrompemos a execuo * usando a funo die() */ die("Ocorreu um erro");}echo "Isso no ser impresso, pois o script no vai chegar at aqui";

    Perceba que a execuo do script interrompida quando a funo die() chamada, o que faz com que seja impresso no navegador somente a frase Ocorreu um erro. Ignorando o restante do script.

  • Lanamento de Erros

    Essa uma forma elegante de se manipular erros. Utilizamos basicamente duas funes:

    trigger_error() e a set_error_handler().

    A primeira lana um erro e a segunda define uma funo que manipular os erros lanados.

    trigger_error()

    Esta funo espera dois parmetros:

    erro: Mensagem de erro gerada; tipo: Tipo de erro.

    Tipos de erros:

    E_USER_ERROR: Erro fatal gerado pelo usurio. A execuo do script interrompida;

    E_USER_WARNING: Erro no fatal gerado pelo usurio. A execuo do script no interrompida;

    E_USER_NOTICE: Padro. Aviso gerado pelo usurio. A execuo do script no interrompida.

    Vamos analisar um exemplo para entender melhor a aplicabilidade:

    /* Esperamos receber* algo passado por $_GET*/if (!(isset($_GET['nome']))){ /* Caso no seja passado * geramos o erro */ trigger_error("O campo nome no foi informado.", E_USER_WARNING);}

    Como resultado a execuo deste script, supondo que no tenha sido passado nada atravs do campo nome, o seguinte erro seria mostrado:

    Warning: O campo nome no foi informado. in c:\Xampp\projeto\index.php line

    Perceba que a sada do erro agora foi tratada.

  • set_error_handler()

    Essa funo defini qual funo manipular os erros lanados.

    possvel por exemplo, alm de tratar os erros com mensagens personalizadas, envi-los por email, armazen-los em um arquivo de log ou mesmo em um banco de dados.

    Por padro o php envia o log de erros para o sistema de log do servidor onde roda a aplicao, isso depende da configurao do php.ini. Podemos utilizar a funo error_log() em conjunto com a funo set_error_handler() para enviar emails sobre os erros selecionveis.

    Vamos ao exemplo:

    /* Primeiro vamos criar a funo * que trata os erros e faz o envio do email */ function erroEmail($erro, $erro_str){ error_log("Erro: [$erro] $erro_str", 1, "[email protected]", "From: [email protected]"); } // Agora inicializamos o tratador de erros set_error_handler("erroEmail", E_USER_WARNING); // Criando um erro qualquer, para ver a coisa funcionar $teste = true; if ( $teste != false ){ trigger_error("O valor no falso :( ", E_USER_WARNING); }

    Para o exemplo funcionar necessrio que voc tenha um servidor de email configurado. Provavelmente se voc testar localmente, no dar certo.

    Voc tambm pode, ao invs de enviar o email, armazena-lo em um arquivo de texto utilizando a funo fopen().

    Tratamento de excees

    Esta maravilha (sim, fantastico) foi includa no PHP 5. Antes j existia para outras linguagens de programao como C++, Java e

  • Delphi. Basicamente uma exceo muda o curso normal de um script caso ocorra um erro.

    Uma exceo um objeto especial derivado da classe Exception que contm alguns mtodos que relatam ao programador o que aconteceu. Vamos agora conhecer estes mtodos:

    getMessage() Retorna a mensagem de erro; getCode() Retorna o cdigo de erro; getFile() Retorna o arquivo no qual o erro ocorreu; getLine() Retorna a linha na qual o erro ocorreu; getTrace() Retorna um array com as aes at o erro; getTraceAsString() Retorna as aes em forma de string.

    Quando executamos operaes que podem resultar em erros, usamos o bloco try para monitor-los. Dentro das operaes crticas, quando ocorre um erro, usamos o comando throw para lanar uma exceo (Objeto Exception), para interromper a execuo do bloco contido na clausula try, a qual recebe esta exceo e repassa para outro bloco de comandos catch. Dentro do bloco catch podemos definir o que fazer:

    Emitir uma mensagem de erro para o usurio e cancelar a execuo do script ou armazenar os detalhes do erro em um arquivo de log e etc.

    Para simplificar, vamos ao exemplo:

    //Uma funo que abre um deternimado arquivo function AbrirArquivo( $arquivo = null ){ //Caso o parametro arquivo esteja em vazio... if( !$arquivo ){ //Geramos a execeo throw new Exception("Parmetro com o nome do arquivo no especificado."); } //Se o arquivo no existir... if( !file_exists($arquivo) ){ //Geramos outra exceo throw new Exception("Arquivo no encontrado."); } //Caso no consiga ler o arquivo.. if( !$data = @file_get_contents($arquivo) ){ //Tambm gerada uma exceo

  • throw new Exception("No foi possvel ler o arquivo."); } // Caso esteja tudo certo, retornamos os dados return $data; } /* "protegemos" a chamada da funo AbrirArquivo() * utilizando o try */ try{ $arquivo = AbrirArquivo("/log/error.log"); echo $arquivo; } /* O catch captura o erro e trata * da forma com que desejar */ catch( Exception $exc ) { /* Imprimimos o arquivo, * a linha e a mensagem * de erro gerada. */ echo $exc->getFile() . " - Na linha " . $exc->getLine() . " # " . $exc->getMessage(); }

    O resultado, caso o arquivo no seja encontrado:

    c:\Xampp\aula\TratamentoErros.php - Linha 10 # Arquivo no encontrado.

    Tratar erros fundamental, essa prtica protege o cdigo e deixa o algoritmo com aspecto bem mais profissional.

    E assim finalizamos mais um artigo do curso.

    Estamos chegando ao fim do que eu havia pensado em escrever sobre este tema. Teremos apenas mais um artigo, sobre PDO, que pretendo publicar amanh (12 de abril), caso a febre no volte a me perseguir.

  • Parte 12Dcimo segundo artigo do curso de PHP Orientado a Objetos. Dessa vez, estudaremos o PDO (PHP Data Object).

    Ao final deste artigo, voc ser capaz de:

    Conhecer e utilizar um mdulo OO (PDO) para acesso a Banco de Dados.

    Conhecendo o PDO

    PDO (PHP Data Objects). Trata-se de um mdulo PHP construdo sob o paradigma Orientado a Objetos que fornece uma padronizao da forma com que o PHP se comunica com o banco de dados relacional. PDO, portanto, uma interface que define um conjunto de classes e a assinatura de mtodos de comunicao com uma base de dados.

    Muitos confundem PDO com uma biblioteca de abstrao de acesso base de dados, o que no verdade, visto que ela no faz a leitura e traduo das instrues SQL, adaptando-as aos mais diversos drivers de banco de dados existentes. Cada SGBD relacional possui uma sintaxe prpria para construo de SQL. Embora muitos deles se aproximem da especificao da SQL-92, algumas diferenas existem.

    Dito isso, podemos concluir que utilizar o PDO no significa que seu sistema ser portvel entre diferentes SGBDs. Ela simplesmente unifica a chamada de mtodos, delegando-os para as suas extenses correspondentes e faz uso do que h de mais recente no que diz respeito orientao a objetos presente no PHP5.

    Utilizando o PDO

    Para utilizar o PDO, primeiro instanciado um objeto da classe PDO, que representa a conexo com o banco. No construtor da classe, passamos os parmetros necessrios. Cada driver PDO especifica uma forma de como montado o chamado DNS, que uma string de conexo para o SGBD correspondente. Alm do DNS, tambm informado, por parmetro, o usurio, a senha de acesso e algumas opes adicionais.

  • Para exemplo vamos criar alguns exemplos de DNS para o Mysql, PostgreSQL, SQLite e Firebird:

    new PDO('sqlite:teste.db');new PDO("firebird:dbname=c:\\banco.GDB", "SYSDBA", "masterkey");new PDO("pgsql:dbname=exemplo;user=user;password=senha;host=localhost");

    Agora vamos ao exemplo completo utilizando o MySql e PDOPara os exemplos descritos a seguir, criaremos uma tabela chamada alunos:

    CREATE TABLE IF NOT EXISTS alunos ( id int(10) NOT NULL AUTO_INCREMENT, nome varchar(65) NOT NULL, idade int(3) NOT NULL, sexo char(1) NOT NULL, PRIMARY KEY (id)) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT = 1; INSERT INTO alunos (nome,idade,sexo) VALUES ('Leandro',27,'M'),('Joo',24,'M'),('Flavia',19,'F'),('Maria',27,'F');

    Com a tabela criada, e os 4 registros inseridos, vamos criar a conexo e realizar uma seleo:

    // Conexo PDO com um banco de dados MySQL local $dsn = 'mysql:host=localhost;port=3306;dbname=phpoo'; $usuario = 'root'; $senha = ''; $opcoes = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_CASE => PDO::CASE_LOWER); try { $pdo = new PDO($dsn, $usuario, $senha, $opcoes);} catch (PDOException $e) { echo 'Erro: ' . $e->getMessage();} $aluno = $pdo->query('SELECT nome, idade FROM alunos'); // Percorrendo sobre o resultado da Query while ($obj = $aluno->fetchObject()) { echo "Nome: " . $obj->nome . "< br />"; echo "Idade: " . $obj->idade . "< br />< br />"; }

    Resultado:Nome: LeandroIdade: 27

  • Nome: JooIdade: 24Nome: FlaviaIdade: 19Nome: MariaIdade: 27

    Prepared Statements:

    Est uma funcionalidade interessante que ameniza muitos erros. Com o uso dos prepared statements no h necessidade de concatenar vrias variveis e usar escape de aspas para prover segurana, uma vez que este mtodo considerado um dos mais seguros se tratando de segurana contra SQL injection.Se segurana no um motivo que te convence, utilizando Prepared Statements temos uma melhora significativa em temos de performance na execuo das querys.Para utilizar esta funcionalidade, basta colocarmos os valores no array que ser passado por parmetro para o mtodo execute.

    Vamos ao exemplo:

    // Conexo PDO com um banco de dados MySQL local $dsn = 'mysql:host=localhost;port=3306;dbname=phpoo'; $usuario = 'root'; $senha = ''; $opcoes = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_CASE => PDO::CASE_LOWER); try { $pdo = new PDO($dsn, $usuario, $senha, $opcoes);} catch (PDOException $e) { echo 'Erro: ' . $e->getMessage();} // Usando "?" nos pontos-chave$aluno = $pdo->prepare('SELECT * FROM alunos WHERE id=?'); // Passando o valor a ser usado no "?"$dados = array(2);$resultado = $aluno->execute($dados); // Escrevendo o resultado da consulta$obj = $aluno->fetchObject(); echo "Nome: " . $obj->nome . "< br />";echo "Idade: " . $obj->idade . "< br />< br />"; ?>

  • Resultado:

    Nome: JooIdade: 24

    De acordo com o que foi comentado anteriormente, o uso de Prepared Statements deixa nossa consulta muito mais rpida, visto que a mesma fica previamente compilada e pronta para execuo com os novos valores. Ao invs do SGBD interpretar toda a SQL, ele apenas atribui novos valores aos pontos chave e realiza a operao.

    Existem outras formas para o uso de Prepared Statements, vamos conhecer mais uma:

    // Conexo PDO com um banco de dados MySQL local $dsn = 'mysql:host=localhost;port=3306;dbname=phpoo'; $usuario = 'root'; $senha = ''; $opcoes = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_CASE => PDO::CASE_LOWER); try { $pdo = new PDO($dsn, $usuario, $senha, $opcoes);} catch (PDOException $e) { echo 'Erro: ' . $e->getMessage();} // Usando pontos-chave nomeados$aluno = $pdo->prepare('SELECT * FROM alunos WHERE nome=:nome AND sexo=:sexo'); // Passando os valores a serem usados em :nome e :sexo$dados = array(':nome' => 'Flavia', ':sexo' => 'F');$resultado = $aluno->execute($dados); // Escrevendo o resultado da consulta$obj = $aluno->fetchObject(); echo "Nome: " . $obj->nome . "< br />";echo "Idade: " . $obj->idade . "< br />< br />";

    Resultado:

    Nome: FlaviaIdade: 19

    PDO fetch()

    possvel retornar dados de uma consulta de diversas formas, uma delas fazendo uso da funo fetch(). Ela aceita diversos parmetros:

  • PDO::FETCH_ASSOC Retorna um array indexado pelo nome da coluna;

    PDO::FETCH_NUM Retorna um array indexado pela posio numrica da coluna;

    PDO::FETCH_BOTH Retorna um array indexado pelo nome e pela posio numrica da coluna;

    PDO::FETCH_OBJ Retorna um objeto annimo (stdClass) onde cada coluna acessada como se fosse uma propriedade.

    Vamos ao exemplo:

    // Conexo PDO com um banco de dados MySQL local $dsn = 'mysql:host=localhost;port=3306;dbname=phpoo'; $usuario = 'root'; $senha = ''; $opcoes = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_CASE => PDO::CASE_LOWER); try { $pdo = new PDO($dsn, $usuario, $senha, $opcoes);} catch (PDOException $e) { echo 'Erro: ' . $e->getMessage();}// Resgatando todos os registros$aluno = $pdo->query('SELECT * FROM alunos'); // Exibindo com PDO::FETCH_ASSOCwhile( $row = $aluno->fetch(PDO::FETCH_ASSOC) ){ echo "Nome: " . $row['nome'] . "< br />"; echo "Sexo:" . $row['sexo'] . "< br />"; }

    Concluso:

    No vamos abordar aqui todas as funcionalidades do PDO. Lembre-se que a biblioteca PDO : Segura, rpida, consistente e prtica. Voc deve fazer uso e se aperfeioar. Para maiores informaes clique aqui.

    Chegamos ao final do nosso curso. Foram 12 artigos abordando tudo aquilo que julgo necessrio para comear no mundo OO. Tentei dar nfase nos pontos que geram maior dvida. Agora, cabe a voc fazer uso do que aprendeu, no desanime, no incio, deixar o paradigma estruturado pode ser difcil, mas no futuro voc perceber que valeu a pena. No em um ms que voc se tornar um expert. Novidades aparecero, ento continue estudando com afinco e pratique bastante.

  • Recomendo que voc aprenda um bom Framework. Isso vai te fornecer versatilidade, alm de ser uma exigncia do mercado. Basicamente a idia por trs de um framework est ligada ao modelo MVC (Model View Controller). De forma geral, o que ele faz isolar a programao, lgica de negcio e a camada de exibio.

    Referencia:

    http://cafeesoftware.com/curso-de-php-orientado-a-objetos/

    Curso de PHP Orientado a ObjetosParte 4Parte 5Parte 6Parte 7Parte 8Parte 9Parte 10O mtodo __autoload()get_class_methodsIs_aget_parent_classget_objetct_varsget_class_vars