Anda di halaman 1dari 7

Criando uma Aplicao Orientada pelo Banco de Dados Com o PHP. O...

https://netbeans.org/kb/docs/php/wish-list-lesson4_pt_BR.html?print=yes

Criando uma Aplicao Orientada pelo Banco de Dados com o PHP Lio 4: Otimizando o Cdigo com Classes e Objetos
Contedo do tutorial: 0. Criando uma Aplicao Orientada pelo Banco de Dados com o PHP - Pgina Principal 1. Criando o Banco de Dados a. Criando um Banco de Dados MySQL b. Criando Tabelas do Banco de Dados Oracle 2. Projetando a Aplicao. Lendo o Banco de Dados 3. Criando um Novo Usurio da Aplicao 4. => Otimizando o Cdigo Cdigo-fonte da Aplicao da Lio Anterior Criando o Arquivo db.php Criando a Classe WishDB Instanciando a Classe WishDB Adicionando um Construtor Classe WishDB Funes da Classe WishDB Funo get_wisherID_by_name Funo get_wishes_by_wisher_id Funo create_wisher Refatorando o Cdigo da Sua Aplicao Refatorando o Arquivo wishlist.php Refatorando o Arquivo createNewWisher.php O Cdigo-fonte da Aplicao aps a Lio Atual est Concludo Adicionando Segurana. Implementando o Log-in de Usurio da Aplicao Adicionando um Novo Desejo ao Banco de Dados Atualizando e Deletando Entradas no Banco de Dados Melhorando a Aparncia da Aplicao Usando a Tecnologia CSS Implantando a Aplicao em um Servidor Web Remoto

5. 6. 7. 8. 9.

Nesta lio, voc otimizar o cdigo para facilitar sua manuteno no futuro. Isso afeta os arquivos createNewWisher.php e wishlist.php. Alm disso, um novo arquivo chamado db.php criado. O cdigo do sua aplicao contm vrios blocos de cdigo semelhantes com consultas ao banco de dados. Para facilitar a leitura e a manuteno do cdigo no futuro, voc pode extrair esses blocos, implement-los como funes de uma classe separada chamada WishDB e colocar WishDB em db.php. Depois disso, voc pode incluir o arquivo db.php em qualquer arquivo PHP e usar qualquer funo de WishDB sem duplicao de cdigo. Essa abordagem garante que quaisquer alteraes em consultas ou funes sero feitas em um nico local e voc no ter de fazer parsing do cdigo inteiro da aplicao. Ao usar uma funo de WishDB, voc no altera o valor de quaisquer variveis de WishDB. Em vez disso, use a classe WishDB como um plano grfico para criar um objeto de WishDB, e altere os valores das variveis nesse objeto. Quando voc finaliza o trabalho com esse objeto, ele destrudo. Como os valores da classe WishDB nunca so alterados, voc pode reutilizar a classe por um nmero ilimitado de vezes. Em alguns casos, talvez voc queira ter vrias instncias de uma classe ao mesmo tempo, e em outros casos, talvez voc prefira uma classe "nica", onde voc possui apenas uma instncia de cada vez. O WishDB neste tutorial uma classe nica. Observe que o termo para criar um objeto de uma classe "instanciar" essa classe, e que outra palavra para um objeto uma "instncia" de uma classe. O termo geral para programar com classes e objetos "programao orientada por objeto" ou OOP. O PHP 5 usa um modelo OOP sofisticado. Consulte php.net para obter mais informaes. Neste tutorial, a funcionalidade de chamada do banco de dados movida de arquivos PHP individuais para classes WishDB. Usurios do MySQL tambm podem substituir a chamada mysqli de estilo de procedimento por chamadas orientadas por objetos. Isso para manter com o novo projeto orientado por objetos da aplicao O documento atual uma parte do tutorial Criando uma Aplicao CRUD no NetBeans IDE para PHP.

Cdigo-fonte da Aplicao da Lio Anterior


Usurios MySQL: clique aqui para fazer o download do cdigo-fonte que reflete o estado do projeto depois que a lio anterior estiver concluda. Usurios do Banco de Dados Oracle: clique aqui para fazer o download do cdigo-fonte que reflete o estado do projeto depois que a lio anterior estiver concluda.

1 de 7

17/09/2013 13:06

Criando uma Aplicao Orientada pelo Banco de Dados Com o PHP. O...

https://netbeans.org/kb/docs/php/wish-list-lesson4_pt_BR.html?print=yes

Criando o Arquivo db.php


Crie uma nova subpasta na pasta Cdigos-fonte. Nomeie a pasta Incluso. Crie uma nova pasta nomeada db.php e coloque em Incluso. Depois disso, possvel adicionar mais arquivos para essa pasta que ser includa em outros arquivos PHP. Para criar o db.php em uma nova pasta: 1. Clique com o boto direito do mouse no n Cdigo-fonte e selecione Novo > Pasta no menu de contexto. A caixa de dilogo Nova Pasta aberta. 2. No campo Nome da Pasta, digite Incluso. Em seguida, clique em Finalizar. 3. Clique com o boto direito do mouse no n Incluso e selecione Novo > Arquivo PHP no menu de contexto. A caixa de dilogo Novo Arquivo PHP aberta. 4. No campo Nome do Arquivo, digite db. Em seguida, clique em Finalizar.

Criando a Classe WishDB


Para criar a classe WishDB, voc precisa inicializar as variveis da classe e implementar um construtor da classe. Usurios MySQL, observem a classe WishDB extends mysqli. Isso significa que o WishDB herda a funo e outras caractersticas da classe mysqli PHP. A importncia disso mostrada ao adicionar as funes mysqli classe. Abra o arquivo db.php e crie a classe WishDB. Na classe, declare variveis de configurao de banco de dados para armazenar o nome e a senha do proprietrio do banco de dados (usurio), o nome e o host do banco de dados. Todas essas declaraes de varivel so "privadas", o que significa que os valores iniciais nas declaraes no podem ser acessados de fora da classe WishDB (Consulte php.net). Declare tambm a varivel static $instance privada, que armazena a instncia do WishDB. A palavra-chave esttica significa que a funo na classe pode acessar a varivel mesmo quando no h instncia da classe. Para o Banco de Dados MySQL:
class WishDB extends mysqli {

// single instance of self shared among all instances private static $instance = null;

// db connection config vars private $user = "phpuser"; private $pass = "phpuserpw"; private $dbName = "wishlist"; private $dbHost = "localhost"; }

Para o Banco de Dados Oracle:


class WishDB {

// single instance of self shared among all instances private static $instance = null;

// db connection config vars private $user = "phpuser"; private $pass = "phpuserpw"; private $dbName = "wishlist"; private $dbHost = "localhost/XE"; private $con = null;

Instanciando a classe WishDB


Para outros arquivos PHP usarem funes na classe WishDB, esses arquivos PHP precisam chamar uma funo que crie um objeto ("instantiates") da classe WishDB. WishDB designado como uma classe nica, o que significa que somente uma instncia da classe existe de cada vez. Portanto, til evitar qualquer instanciao externa de WishDB, o que poderia criar instncias duplas. Dentro da classe WishDB, digite ou cole o seguinte cdigo:
//This method must be static, and must return an instance of the object if the object //does not already exist. public static function getInstance() { if (!self::$instance instanceof self) { self::$instance = new self; } return self::$instance; } // The clone and wakeup methods prevents external instantiation of copies of the Singleton class, // thus eliminating the possibility of duplicate objects. public function __clone() { trigger_error('Clone is not allowed.', E_USER_ERROR); } public function __wakeup() { trigger_error('Deserializing is not allowed.', E_USER_ERROR); }

A funo getInstance "pblica" e "esttica." "Pblica" significa que ela pode ser acessada publicamente de fora da classe. "Esttica" significa que a

2 de 7

17/09/2013 13:06

Criando uma Aplicao Orientada pelo Banco de Dados Com o PHP. O...

https://netbeans.org/kb/docs/php/wish-list-lesson4_pt_BR.html?print=yes

funo est disponvel mesmo quando a classe no tiver sido instanciada. Como a funo getInstance chamada para instanciar a classe, ela deve ser esttica. Observe que essa funo acessa a varivel$instance esttica e ajusta os valores como a instncia da classe. Os dois-pontos duplos (::), chamados de Operador de Resoluo de Escopo, e a palavra-chave self so usados para acessar funes estticas. Self usado na definio da classe para se referir classe em si. Quando os dois-pontos duplos forem usados fora da definio da classe, o nome da classe ser usado em vez de self. Consulte php.net no Operador de Resoluo de Escopo.

Adicionando um Construtor Classe WishDB


Uma classe pode conter um mtodo especial conhecido como 'construtor', que processado automaticamente sempre que uma instncia dessa classe criada. Neste tutorial, voc adiciona um construtor ao WishDB que se conecta ao banco de dados sempre que WishDB instanciado. Adicione o cdigo seguinte ao WishDB: Para o banco de dados MySQL:
// private constructor private function __construct() { parent::__construct($this->dbHost, $this->user, $this->pass, $this->dbName); if (mysqli_connect_error()) { exit('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); } parent::set_charset('utf-8'); }

Para o banco de dados Oracle:


// private constructor private function __construct() { $this->con = oci_connect($this->user, $this->pass, $this->dbHost); if (!$this->con) { $m = oci_error(); echo $m['message'], "\n"; exit; } }

Observe o uso da pseudovarivel $this em vez das variveis $con, $dbHost, $user ou $pass. A pseudovarivel $this usada quando um mtodo chamado de dentro do contexto de um objeto. Ela se refere ao valor de uma varivel nesse objeto.

Funes da Classe WishDB


Nesta lio, voc implementar as seguintes funes da classe WishDB: get_wisher_id_by_name para recuperar o id de um wisher com base em seu nome get_wishes_by_wisher_id para recuperar uma lista de desejos do wisher com um id especfico create_wisher para adicionar um novo registro de wisher aos wishers da tabela

Funo get_wisher_id_by_name
A funo requer o nome de um wisher como parmetro de entrada e retorna o wisher id. Digite ou cole a seguinte funo na classe WishDB, depois da funo WishDB: Para o banco de dados MySQL:
public function get_wisher_id_by_name($name) { $name = $this->real_escape_string($name); $wisher = $this->query("SELECT id FROM wishers WHERE name = '" . $name . "'"); if ($wisher->num_rows > 0){ $row = $wisher->fetch_row(); return $row[0]; } else return null; }

Para o banco de dados Oracle:


public function get_wisher_id_by_name($name) { $query = "SELECT id FROM wishers WHERE name = :user_bv"; $stid = oci_parse($this->con, $query); oci_bind_by_name($stid, ':user_bv', $name); oci_execute($stid); //Because user is a unique value I only expect one row $row = oci_fetch_array($stid, OCI_ASSOC); if ($row) return $row["ID"]; else return null; }

O bloco de cdigo executa a consulta SELECT ID FROM wishers WHERE name = [varivel para o nome do wisher]. O resultado da consulta um array de IDs dos registros que satisfazem a consulta. Se o array no estiver vazio, isso significa automaticamente que ela contm um elemento porque o nome do campo especificado como NICO durante a criao da tabela. Nesse caso, a funo retorna o primeiro elemento do array $result (o elemento

3 de 7

17/09/2013 13:06

Criando uma Aplicao Orientada pelo Banco de Dados Com o PHP. O...

https://netbeans.org/kb/docs/php/wish-list-lesson4_pt_BR.html?print=yes

com zero). Se o array estiver vazio, a funo retornar nula. Observao sobre Segurana: Para o banco de dados MySQL, a string $name tem escape para evitar os ataques de injeo SQL. Consulte Wikipedia sobre injees SQL e a documentao mysql_real_escape_string. Embora no contexto deste tutorial voc no esteja correndo o risco de injees SQL prejudiciais, recomendamos escapar as strings nas consultas MySQL que estariam correndo risco de tal ataque. O banco de dados Oracle evita esse problema usando variveis de ligao.

Funo get_wishes_by_wisher_id
A funo exige o id de um wisher como o parmetro de entrada e retorna os desejos registrados para o wisher. Indique o seguinte bloco de cdigo: Para o banco de dados MySQL:
public function get_wishes_by_wisher_id($wisherID) { return $this->query("SELECT id, description, due_date FROM wishes WHERE wisher_id=" . $wisherID); }

Para o banco de dados Oracle:


public function get_wishes_by_wisher_id($wisherID) { $query = "SELECT id, description, due_date FROM wishes WHERE wisher_id = :id_bv"; $stid = oci_parse($this->con, $query); oci_bind_by_name($stid, ":id_bv", $wisherID); oci_execute($stid); return $stid; }

O bloco de cdigo executa a consulta "SELECT id, description, due_date FROM wishes WHERE wisherID=" . $wisherID e retorna um conjunto de resultados que um array de registros que atende consulta. (O banco de dados Oracle usa variveis de ligao para o desempenho do banco de dados e motivos de segurana). A seleo realizada pelo wisherID, que a chave estrangeira dos desejos da tabela. Observao: o valorid no necessrio at a Lio 7.

Funo create_wisher
A funo cria um novo registro na tabela de wishers. A funo requer o nome e a senha de um novo wisher como os parmetros de entrada e no retorna dados. Indique o seguinte bloco de cdigo: Para o banco de dados MySQL:
public function create_wisher ($name, $password){ $name = $this->real_escape_string($name); $password = $this->real_escape_string($password); $this->query("INSERT INTO wishers (name, password) VALUES ('" . $name . "', '" . $password . "')"); }

Para o banco de dados Oracle:


public function create_wisher($name, $password) { $query = "INSERT INTO wishers (name, password) VALUES (:user_bv, :pwd_bv)"; $stid = oci_parse($this->con, $query); oci_bind_by_name($stid, ':user_bv', $name); oci_bind_by_name($stid, ':pwd_bv', $password); oci_execute($stid); }

O bloco de cdigo executa a consulta "INSERT wishers (Name, Password) VALUES ([variveis representando o nome e a senha do novo wisher]). A consulta adiciona um novo registro tabela "wishers" com os campos "nome" e "senha" preenchidos com os valores de $name e $password respectivamente.

Refatorando o Cdigo da Sua Aplicao


Agora que tem uma classe separada para trabalhar com o banco de dados, voc pode substituir blocos duplicados por chamadas para as funes relevantes desta classe. Isso ajudar a evitar erros ortogrficos e inconsistncia no futuro. A otimizao de cdigo que no afeta a funcionalidade chamada de refatorao.

Refatorando o Arquivo wishlist.php


Comece com o arquivo wishlist.php porque ele pequeno e as melhorias sero mais ilustrativas. 1. Na parte superior do bloco <?php ?> , insira a linha seguinte para permitir o uso do arquivo db.php:
require_once("Includes/db.php");

2. Substitua o cdigo que estabelece conexo com o banco de dados e que obtm o wisher ID por uma chamada para a funo get_wisher_id_by_name. Para o banco de dados MySQL, o cdigo a ser substitudo :
$con = mysqli_connect("localhost", "phpuser", "phpuserpw"); if (!$con) { exit('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); }

4 de 7

17/09/2013 13:06

Criando uma Aplicao Orientada pelo Banco de Dados Com o PHP. O...

https://netbeans.org/kb/docs/php/wish-list-lesson4_pt_BR.html?print=yes

//set the default client character set mysqli_set_charset($con, 'utf-8'); mysqli_select_db($con, "wishlist"); $user = mysqli_real_escape_string($con, $_GET['user']); $wisher = mysqli_query($con, "SELECT id FROM wishers WHERE name='" . $user . "'"); if (mysqli_num_rows($wisher) < 1) { exit("The person " . $_GET['user'] . " is not found. Please check the spelling and try again"); } $row = mysqli_fetch_row($wisher); $wisherID = $row[0]; mysqli_free_result($wisher);

$wisherID = WishDB::getInstance()->get_wisher_id_by_name($_GET["user"]); if (!$wisherID) { exit("The person " .$_GET["user"]. " is not found. Please check the spelling and try again" ); }

Para o banco de dados Oracle, o cdigo a ser substitudo :


$con = oci_connect("phpuser", "phpuserpw", "localhost/XE", "AL32UTF8"); if (!$con) { $m = oci_error(); echo $m['message'], "\n"; exit; } $query = "SELECT id FROM wishers WHERE name = :user_bv"; $stid = oci_parse($con, $query); $user = $_GET["user"]; oci_bind_by_name($stid, ':user_bv', $user); oci_execute($stid); //Because user is a unique value I only expect one row $row = oci_fetch_array($stid, OCI_ASSOC); if (!$row) { echo("The person " . $user . " is not found. Please check the spelling and try again" ); exit; } $wisherID = $row["ID"];

$wisherID = WishDB::getInstance()->get_wisher_id_by_name($_GET["user"]); if (!$wisherID) { exit("The person " .$_GET["user"]. " is not found. Please check the spelling and try again" ); }

O novo cdigo chama primeiro a funo getInstance no WishDB. O getInstance retorna uma instncia de WishDB, e o cdigo chama a funo get_wisher_id_by_name dentro dessa instncia. Se a lista de desejos solicitada no for encontrada no banco de dados, o cdigo terminar o processo, e exibir uma mensagem de erro. Nenhum cdigo necessrio para abrir uma conexo ao banco de dados. A conexo aberta pelo construtor da classe WishDB. Se o nome e/ou a senha for alterado, voc precisar atualizar somente as variveis relevantes da classe WishDB. 3. Substitua o cdigo que recebe desejos de um wisher identificado pelo ID com um cdigo que chama a funo get_wishes_by_wisher_id. Para o banco de dados MySQL, o cdigo a ser substitudo :
$result = mysqli_query($con, "SELECT description, due_date FROM wishes WHERE wisher_id=". $wisherID); $result = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID);

Para o banco de dados Oracle, o cdigo a ser substitudo :


$query = "select * from wishes where wisher_id = :id_bv"; $stid = oci_parse($con, $query); oci_bind_by_name($stid, ":id_bv", $wisherID); oci_execute($stid); $stid = WishDB::getInstance()->get_wishes_by_wisher_id($wisherID);

4. Remova a linha que fecha a conexo do banco de dados.


mysqli_close($con); or oci_close($con);

O cdigo no necessrio porque a conexo ao banco de dados automaticamente fechada quando o objeto WishDB destrudo. No entanto, mantenha o cdigo que libera o recurso. necessrio liberar todos os recursos que usam uma conexo para garantir que a conexo seja fechada corretamente, mesmo quando a funo close chamada ou se a instncia for destruda com a conexo do banco de dados.

Refatorando o Arquivo createNewWisher.php


A refatorao no afetar o form de entrada HTML ou o cdigo para exibir as mensagens de erro relacionadas. 1. Na parte superior do bloco <?php ?>, insira o cdigo seguinte para permitir o uso do arquivo db.php:
require_once("Includes/db.php");

5 de 7

17/09/2013 13:06

Criando uma Aplicao Orientada pelo Banco de Dados Com o PHP. O...

https://netbeans.org/kb/docs/php/wish-list-lesson4_pt_BR.html?print=yes

2. Delete a credencial da conexo do banco de dados ($dbHost, etc). Esses esto agora em db.php.. 3. Substitua o cdigo que estabelece conexo com o banco de dados e que obtm o wisher ID por uma chamada para a funo get_wisher_id_by_name. Para o banco de dados MySQL, o cdigo a ser substitudo :
$con = mysqli_connect("localhost", "phpuser", "phpuserpw"); if (!$con) { exit('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); } //set the default client character set mysqli_set_charset($con, 'utf-8');

/** Check whether a user whose name matches the "user" field already exists */ mysqli_select_db($con, "wishlist"); $user = mysqli_real_escape_string($con, $_POST['user']); $wisher = mysqli_query($con, "SELECT id FROM wishers WHERE name='".$user."'"); $wisherIDnum=mysqli_num_rows($wisher); if ($wisherIDnum) { $userNameIsUnique = false; }

$wisherID = WishDB::getInstance()->get_wisher_id_by_name($_POST["user"]); if ($wisherID) { $userNameIsUnique = false; }

Para o banco de dados Oracle, o cdigo a ser substitudo :


$con = oci_connect("phpuser", "phpuserpw", "localhost"); if (!$con) { $m = oci_error(); echo $m['message'], "\n"; exit; } $query = "select ID from wishers where name = :user_bv"; $stid = oci_parse($con, $query); $user = $_POST['user']; $wisherID = null; oci_bind_by_name($stid, ':user_bv', $user); oci_execute($stid); //Each user name should be unique. Check if the submitted user already exists. $row = oci_fetch_array($stid, OCI_ASSOC); if ($row) { $wisherID = $row["ID"]; } if ($wisherID != null) { $userNameIsUnique = false; } $wisherID = WishDB::getInstance()->get_wisher_id_by_name($_POST["user"]); if ($wisherID) { $userNameIsUnique = false; }

O objeto WishDB existe enquanto a pgina atual estiver sendo processada. Ele destrudo depois que o processamento concludo ou interrompido. O cdigo para abrir uma conexo ao banco de dados no necessrio porque isso feito pela funo WishDB. O cdigo para fechar a conexo no necessrio porque a conexo fechada assim que o objeto WishDB destrudo. 4. Substitua o cdigo que insere novos desejos no banco de dados pelo cdigo que chama a funo create_wisher. Para o banco de dados MySQL, o cdigo a ser substitudo :
if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { $password = mysqli_real_escape_string($con, $_POST["password"]); mysqli_select_db($con, "wishlist"); mysqli_query($con, "INSERT wishers (name, password) VALUES ('" . $user . "', '" . $password . "')"); mysqli_free_result($wisher); mysqli_close($con); header('Location: editWishList.php'); exit; } if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { WishDB::getInstance()->create_wisher($_POST["user"], $_POST["password"]); header('Location: editWishList.php' ); exit; }

Para o banco de dados Oracle, o cdigo a ser substitudo :


if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { $query = "INSERT INTO wishers (name, password) VALUES (:user_bv, :pwd_bv)"; $stid = oci_parse($con, $query); $pwd = $_POST['password']; oci_bind_by_name($stid, ':user_bv', $user); oci_bind_by_name($stid, ':pwd_bv', $pwd); oci_execute($stid); oci_close($con); header('Location: editWishList.php');

6 de 7

17/09/2013 13:06

Criando uma Aplicao Orientada pelo Banco de Dados Com o PHP. O...

https://netbeans.org/kb/docs/php/wish-list-lesson4_pt_BR.html?print=yes

exit; }

if (!$userIsEmpty && $userNameIsUnique && !$passwordIsEmpty && !$password2IsEmpty && $passwordIsValid) { WishDB::getInstance()->create_wisher($_POST["user"], $_POST["password"]); header('Location: editWishList.php' ); exit; }

O cdigo-fonte da Aplicao aps a Lio Atual est Concludo


Usurios do MySQL: clique aqui para fazer o download do cdigo-fonte que reflete o estado do projeto depois que a lio estiver concluda. Usurios do banco de dados Oracle: clique aqui para fazer o download do cdigo-fonte que reflete o estado do projeto depois que a lio for concluda.

Prximas Etapas
<< Lio anterior Prxima lio >> Voltar pgina principal do Tutorial

Links teis
Saiba mais sobre o uso de classes em PHP: Classes e Objetos Saiba mais sobre a refatorao de cdigo PHP: Sete Etapas Para Melhorar o Cdigo PHP Refatorao do PHP Envie-nos Seu Feedback Para enviar comentrios e sugestes, obter suporte e manter-se informado sobre os desenvolvimentos mais recentes das funcionalidades de desenvolvimento PHP do NetBeans IDE, junte-se lista de correspondncia users@php.netbeans.org. Voltar Trilha de Aprendizado PHP

7 de 7

17/09/2013 13:06