PHP & MySQL José Francisco [[email protected]] Os slides originais são parte do material de cursos anteriores do curso de PHP, ministrados por Sérgio Clemente. Com modificações! Também possui a contribuição de Cleviton V. F. Monteiro. Conteúdo didático é baseado em diversas fontes como: tutoriais, livros e o site oficial de PHP. Inspirado também em slides de Jobson Ronan, instrutor de Java Avançado do CITi. Roteiro Classes em PHP 5 Trabalhando com Blob’s Modelo de Objeto O modelo de objeto em PHP foi totalmente reescrito. Melhor performance e mais vantagens. Mantém a compatibilidade com versões anteriores. Mais robusta. É finalmente Orientação a Objetos. Passagem de Objetos Os objetos são passados por referência. As modificações feitos no objeto dentro de um método serão vistas fora do método que as fez. Em PHP 4 isso não ocorreria pois a passagem é por valor. É criada uma cópia, interna ao método, do objeto passado por parâmetro. As modificações não serão sentidas pelo objeto original. Exemplo <?php class Automovel { # atributo da classe var $nome = ""; #Obtem o nome do Automóvel function getNome () { return $this->nome; } #Altera o nome do Automóvel function setNome ($nome) { $this->nome = $nome; } # instancia um Objeto da Classe Automovel $automovel = new Automovel; # Seta o nome do Automovel $automovel->setNome("Gol"); # Função alterar function alterarNomeAutomovel ($automovel) { $automovel->setNome("Palio"); } # Imprime o nome do Automovel echo $automovel->getNome(); } ?> Saídas: PHP 4 PHP 5 Gol Palio Encapsulamento É o ato de esconder a implementação dos serviços fornecidos pelo objeto. O uso de tais objetos depende unicamente do uso dos serviços que ele fornece (métodos) e não da sua implementação (atributos). Permite um maior reuso e manutenibilidade de código. Maior clareza ao se utilizar um objeto. “Caixa Preta” Encapsulamento – PHP5 Foram introduzidos os modificadores de acesso: public private protected Aplica-se a propriedades e métodos. Caso não seja definido um dos modificadores para o método ou a propriedade este será automaticamente público. Mantém a compatibilidade. public Modificador que permite um acesso universal. Qualquer outra classe (ou mesmo não sendo classe) pode ter acesso. A ausência de modificador automaticamente define o membro ou método como public. private Modificador com menor grau de acesso. Membros e funções com private só podem ser acessados entro da própria classe. Muito utilizado com as propriedades (atributos) da classe para que não se tenha acesso às mesmas. protected Modificador que permite um grau de acesso intermediário. Apenas a própria classe e suas filhas (extensoras) têm acesso a tais membros e métodos. Exemplo <?php class Pessoa { protected $salario; } class Funcionario extends Pessoa { # Gera um erro de acesso a propriedade function alteraSalario ($empregado) { $empregado->salario = 1000; } ?> # Torna o salário acessível public function getSalario () { return $this->salario; } # seta o salario caso seja maior que R$1000 public function setSalario ($valor) { if ($valor >= 1000) { $this->salario = $valor; } } } O atributo só pode ser acessado (fora das classes) via métodos. Exemplo 2 – php.net class MinhaClasse { public $publica = 'Public'; protected $protegida = 'Protected'; private $privada = 'Private'; function imprimeAlo() { echo $this->publica; echo $this->protegida; echo $this->privada; } } $obj = new MinhaClasse(); echo $obj->publica; // Funciona echo $obj->protegida; // Erro Fatal echo $obj->privada; // Erro Fatal $obj->imprimeAlo(); // Mostra Public, Protected e Private Exemplo 3 – php.net class MinhaClasse2 extends MinhaClasse { // Nós podemos redeclarar as propriedades públicas e protegidas mas não as privadas protected $protegida = 'Protected2'; function imprimeAlo() { echo $this->publica; echo $this->protegida; echo $this->privada; } } $obj2 = new MinhaClasse2(); echo $obj2->publica; // Works echo $obj2->privada; // Undefined echo $obj2->protegida; // Fatal Error $obj2->imprimeAlo(); // Mostra Public, Protected2, Não Private Chamada Sobrecarregada de Métodos Agora tem suporte a chamadas de métodos de objetos retornados por outros métodos diretamente. class Departamento { private $funcionario; public function getFuncionario () { return $this->funcionario; } ... } $departamento = new Departamento; # altera o salariodo funcionario $departamento->getFuncionario()->alteraSalario(2000); Contrutores/Destrutores Não havia mecanismos de destruição de objetos. Construtor com o mesmo nome da classe. Em PHP 5: É possível a definição de dois métodos: __construct() __destruct() Melhor debug Limpar arquivos, etc. Construtores/Destrutores <?php class CestaCompra { #Método construtor de minha compra function __construct () { echo "construindo..."; } # Método destrutor de minha compra function __destruct () { echo "destruindo..."; } } $cesta = new CestaCompra; ?> Saída: construindo... destruindo... O construtor pode ter parâmetros. Heranças Necessita de chamadas explicitas para os métodos. class MinhaCestaCompra extends CestaCompra { function __contruct () { parent::__construct(); echo "construindo minha cesta...“; } function __destruct () { } } Saída: construindo... construindo minha cesta... destruindo... Classes Abstratas Em PHP 5 é introduzido o conceito de classe abstrata. Estas classe não podem ter instancias. Ela só pode ser herdada. Servem para padronização de código Manutenibilidade Reuso Classes Abstratas abstract class Pessoa { private $nome; //... } class Funcionario extends Pessoa { //... } # Instanciaria sem problemas a classe nãoabstrata $funcionario = new Funcionario; # Dará um erro quando for executado $pessoa = new Pessoa; Podem possuir ou não atributos Fatal error: Cannot instantiate abstract class Pessoa ... Interfaces Defini um protocolo de serviços fornecidos pelo objeto. interface Conta { public function getSalto (); } class ContaCorrente implements Conta { // ... public function getSalto () { return $this->saldo; } } Interface Este código retornaria um erro fatal: interface Conta { public function getSalto (); } class ContaCorrente extends Conta { // ... /* public function getSalto () { return $this->saldo; } */ } A classe ContaCorrente não defini um método obrigatório. Constantes em Classes Foi introduzido o conceito de constante de classe. Pode ser acessível a qualquer momento. Não são acessíveis diretamente a partir de uma instancia do objeto. Informação no contexto de classe class Pessoa { const NUMERO = 5; } echo Pessoa::NUMERO; • O valor é acessível fora da classe. • Geralmente são escritas em uppercase. Propriedades Estáticas Não são variáveis de instância, e sim de classes class Monstro { static $quantidade_monstros; public function __construct () { Monstro::$quantidade_monstros++; } } echo Monstro::$quantidade_monstros; $monstro = new Monstro; echo Monstro::$quantidade_monstros; Operador de Resolução de Escopo - :: Referenciar constantes de classe Referenciar variáveis estáticas (Variáveis de Classe) Utilizado em conjunto com: self: membros da mesma classe onde foi chamada. parent: membros da classe pai. NomeClasse: membros de uma classe. Sobrecarga de Membros As chamadas a membros do objeto são sobre carregados pelos métodos __set(string nome, mixed valor) e __get(mixed nome); “nome” é o nome da variável que deve ser modificada ou restaudada. “valor” é o valor que deve ser atribuído à variável Só são disparados quando um objeto ou o objeto herdado não possuir os membros invocados. Sobrecarga de Membros function __set($nm, $val) { print "Atribuindo à [$nm] o valor $val\n"; class Setter { public $n; private $x = array("a" => 1, "b" => 2, "c" => 3); if (isset($this->x[$nm])) { $this->x[$nm] = $val; echo "OK!\n"; } else { echo "Não funcionou\n"; } function __get($nm) { print "Pegando [$nm]\n"; if (isset($this->x[$nm])) { $r = $this->x[$nm]; print "Retornando: $r\n"; return $r; } else { echo "Nada!\n"; } } } } $foo = new Setter(); $foo->n = 1; $foo->a = 100; $foo->a++; $foo->z++; var_dump($foo); Saída Atribuindo à [a] o valor 100 OK! Pegando [a] Retornando: 100 Atribuindo à [a] o valor 101 OK! Pegando [z] Nada! Atribuindo à [z] o valor 1 Não funcionou! object(Setter)#1 (2) { ["n"]=> int(1) ["x:private"]=> array(3) { ["a"]=> int(101) ["b"]=> int(2) ["c"]=> int(3) } Sobrecarga de Função As chamadas funções do objeto são sobre carregados pelos métodos __call(string nome, array arg); “nome” é o nome do método invocado. “arg” é um array contendo os argumentos do método Só são disparados quando um objeto ou o objeto herdado não possuir os métodos invocados. Sobrecarga de Função Saída: <?php class Caller { private $x = array(1, 2, 3); function __call($m, $a) { print "Método $m chamado:\n"; var_dump($a); return $this->x; } } $foo = new Caller(); $a = $foo->teste(1, "2", 3.4, true); var_dump($a); ?> Método teste chamado: array(4) { [0]=> int(1) [1]=> string(1) "2" [2]=> float(3.4) [3]=> bool(true) } array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } Mais que isso Iteração de Objetos Patterns Métodos Mágicos Palavra-Chave 'final' Clonando objetos Comparando objetos Reflexão Indução de Tipo BLOB Dá maior segurança aos dados sigilosos do site. Maior flexibilidade e mais robustez nas requisição. Fica mais elegante que por um monte de arquivos em uma pasta. Deixa cara arquivo com um ID de identificação e não apenas o nome. Etc. Exemplo Um HTML que envia um arquivo qualquer para o servidor. <HTML> <HEAD> <TITLE>:: Curso PHP :: CITi ::</TITLE> </HEAD> <BODY> <h3>Selecione um arquivo para enviar:</h3><BR> <form enctype="multipart/form-data" action="action.php" method= post> <input name= userfile type= file><BR> <input type= submit name= enviar value= Enviar> </form> </BODY> </HTML> Tratamento dos Dados Pegar o arquivo temporário. Abrí-lo. Adicionar os caracteres especiais necessários “addslashs()”. Pegar o tipo de dados que será armazenado. $uploaded = $_FILES['userfile']['tmp_name']; $size = $_FILES['userfile']['size']; echo $uploaded; $file_handler = fopen($uploaded, "r"); $file_content = fread($filehandler, $size); $file_content = addslashes($file_content); $content_type = $_FILES['userfile']['type']; Armazenar o blob (LongBlob) Criar conexão com o banco de dados. Insere o conteúdo e o tipo dele no banco. $con = mysql_connect("localhost","root","jfp"); mysql_select_db('exemploblob', $con); mysql_query("INSERT INTO exblob (dado, tipo) VALUES (‘$file_content’,’$content_type’)", $con); echo mysql_error($con); mysql_close($con); Recuperando a informação Cria as conexões necessárias com o banco. Caso encontre algum documento com os parâmetros informados: Set o header do HTTP para o tipo de conteúdo que será retornado. Mostre o conteúdo (echo, print, etc). Em caso contrário ignore ou mostre uma mensagem de erro. Poderia juntamente com session ou cookie limitar o acesso aos dados. Recuperando a informação Algo parecido com isso: $id = $_GET['id']; $con = mysql_connect("localhost","root","jfp"); mysql_select_db('exemploblob', $con); $result = mysql_query("SELECT * FROM exblob WHERE id = $id", $con); if ($conteudo = mysql_fetch_array($result)) { header ("Content-type: ".$conteudo['tipo']); echo $conteudo['dado']; } else { echo "Nenhum arquivo encontrado!"; } echo mysql_error($con); Dúvidas?? PHP & MySQL José Francisco [[email protected]]