// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= Lição 2: Projetando a Aplicação. Lendo o Banco de Dados
:jbake-type: tutorial
:jbake-tags: tutorials 
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: Lição 2: Projetando a Aplicação. Lendo o Banco de Dados - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, Lição 2: Projetando a Aplicação. Lendo o Banco de Dados


Nesta lição, você cria e configura o projeto PHP para desenvolver sua aplicação, cria uma lista de páginas na aplicação e define as relações entre eles. Também desenvolve a funcionalidade básica da aplicação e a testa contra os dados inseridos no banco de dados de amostra na lição 1.

O código PHP escrito nessa lição executa as seguintes funções:

1. Obtém o nome de uma pessoa que o usuário digita.
2. Verifica se a pessoa realmente está no banco de dados. Fecha com uma mensagem de erro caso a pessoa não esteja no banco de dados.
3. Exibe uma tabela dos desejos dessa pessoa.

O documento atual é uma parte do tutorial Criando uma Aplicação Orientada pelo Banco de Dados no NetBeans IDE para PHP.

== Criando um Projeto PHP

Selecione Arquivo > Novo Projeto (Ctrl-Shift-N no Linux e Windows, ⌘-Shift-N no MacOS). Crie um novo projeto PHP chamado “wishlist” (lista de desejos). Quando você cria um projeto PHP, ele contém o arquivo index  ``index.php``  por default. Para obter informações sobre como criar e configurar um projeto PHP, consulte link:project-setup.html[+Configurando um Projeto PHP+].


== Definindo um Diagrama de Fluxo de Página

O escopo da sua aplicação cobre os seguintes casos de uso:

1. O usuário visualiza a lista de desejos de uma pessoa.
2. O usuário se registra como um novo wisher.
3. O usuário se conecta e cria sua lista de desejos.
4. O usuário se conecta e edita sua lista de desejos.

Para cobrir essa funcionalidade básica, você precisará implementar os seguintes arquivos PHP:

1. A página "inicial" index.php é usada para fazer log-in, registrar e alternar para as listas de desejos de outros usuários.
2. A página wishlist.php para exibir a lista de desejos de um wisher.
3. A página createNewWisher.php para registro como um wisher.
4. A página editWishList.php para editar uma lista de desejos pelo proprietário.
5. A página editWish.php para criar e editar desejos.

image::images/page-flow-diagram.png[]

Agora que finalizou as etapas preliminares, você pode começar a implementar a funcionalidade básica da sua aplicação. Comece visualizando a lista de desejos de um wisher. Esta funcionalidade não envolve quaisquer validações e pode ser testada facilmente, já que você já indicou os dados de teste no banco de dados. A funcionalidade será implementada em duas páginas, index.php e wishlist.php.


== Adicionando um Form a um index.php

O arquivo index.php não conterá códigos PHP, portanto, você poderá remover facilmente o seguinte bloco:

O arquivo  ``index.php``  é usado para dois propósitos:

* Exibir uma página com controles para indicar dados.
* Transferir os dados inseridos a outro arquivo PHP, onde os dados serão processados. Neste tutorial, os dados são passados para um arquivo chamado  ``wishlist.php`` , no qual, na próxima seção, você criará e escreverá os códigos.

Essas ações são realizadas por meio de um form HTML. Cada form HTML contém:

* Um conjunto de campos que corresponde aos controles na página.
* A “ação” que é executada depois que o usuário envia os dados do form. A ação é representada pelo caminho à página que processa os dados.

*Para adicionar um form ao index.php*:

1. Alterne para a janela Projetos, expanda o nó do seu projeto e o nó de Arquivos de Código-fonte e clique duas vezes no arquivo  ``index.php`` . O arquivo  ``index.php``  se abre na área do editor principal do IDE. O arquivo contém um modelo para a inserção dos códigos HTML e PHP.

NOTE: você pode ignorar as advertências do validador HTML.



. Remova o bloco PHP. O arquivo index.php não conterá códigos PHP.

image::images/remove-php-block.png[]



. Abra a Paleta no menu Janela ou pressione Ctrl-Shift-8.


. Na seção *Forms HTML* da Paleta, arraste e solte um Form na seção <body> do  ``index.php`` . 

image::images/form-dnd.png[]



. A Caixa de Diálogo Inserir Form abre. No campo Ação, digite o caminho até o arquivo para o qual o form transferirá dados. Nesse caso, digite  ``wishlist.php`` . (Você criará esse arquivo no mesmo local que o  ``index.php`` . Consulte <<createNewFile,Criando wishlist.php e Testando a Aplicação>>.) Selecione o método GET para a transferência de dados. Dê um nome arbitrário ao form, como  ``wishList`` . Clique em OK quando acabar.

image::images/insert-form-dialog.png[]

O arquivo agora tem a seguinte aparência:

image::images/blank-form.png[]



. Entre os identificadores de abertura e fechamento do form, digite o texto “Show wish list of: ”.


. Arraste um componente de Entrada de Texto da seção *Forms HTML* da Paleta até o espaço após o texto “Show wish list of: ”. A caixa de diálogo Inserir Texto abre.


. Nomeie a entrada como  ``user`` . Selecione o tipo de entrada  ``text`` . Deixe todos os outros campos vazios e clique em OK.

image::images/insert-text-input.png[]

O arquivo agora tem a seguinte aparência:

image::images/form-with-text-input.png[]



. Adicione uma linha em branco acima da tag </form>. Nessa linha em branco, arraste e solte um componente Botão da seção *Forms HTML* da Paleta.


. A caixa de diálogo Inserir Botão abre. Digite  ``Go``  no campo Label e clique em OK.

image::images/insert-button-dialog.png[]



. Agora, o form se parece com o código abaixo, com uma única diferença. No código abaixo, o atributo  ``method``  está explícito na tag <form>. O NetBeans IDE não adicionou o atributo method ao seu form, pois o GET é o valor default desse atributo. Entretanto, você pode entender o código com mais facilidade se o atributo  ``method``  estiver explícito.

[source,xml]
----
<form action="wishlist.php" method="GET" name="wishList">
    Show wish list of: 
    <input type="text" name="user" value=""/>
    <input type="submit" value="Go" />
</form>
----

Observe os seguintes elementos do form:

* A tag de abertura <form> contém o atributo  ``action`` . O atributo action especifica o arquivo para o qual o form transferirá dados. Nesse caso, o arquivo se chama  ``wishlist.php``  e está na mesma pasta que o  ``index.php`` . (Você criará esse arquivo na seção <<createNewFile,Criando wishlist.php e Testando a Aplicação>>.)
* A tag de abertura <form> também contém o método a ser aplicado para a transferência de dados (GET). O PHP usa um array  ``$_GET``  ou  ``$_POST``  para os valores passados pelo form, dependendo do valor do atributo  ``method`` . Nesse caso, o PHP usa  ``$_GET`` .
* Um componente de entrada de ``texto`` . Esse componente é um campo de texto usado para inserir o nome do usuário cuja lista de desejos você deseja exibir. O valor inicial do campo de texto é uma sequência de caracteres vazia. O nome desse campo é  ``user`` . O PHP usa o nome do campo ao criar um array para os valores do campo. Nesse caso, o array para os valores desse campo é  ``htmlentities($_GET["user"])`` .
* Um componente de entrada  ``submit``  com o valor “Ir”. O tipo "submit" significa que o campo de entrada aparece na página como um botão. O valor “Ir” é o label do botão. Quando o usuário clica no botão, os dados no componente  ``texto``  são transferidos para o arquivo especificado no atributo  ``action`` .


== Criando wishlist.php e Testando a Aplicação

Em <<transferDataFromIndexToWishlist,Adicionando um Form ao index.php>>, foi criado um form no qual o usuário envia o nome de alguém cuja lista de desejos o usuário deseja ver. O nome é passado para a página  ``wishlist.php`` . Entretanto, essa página não existe. Se você executar o  ``index.php`` , ocorrerá um erro 404: File Not Found ao enviar um nome. Nesta seção, você criará a página  ``wishlist.php``  e testará a aplicação.

*Para criar a wishlist.php e testar a aplicação:*

1. Dentro do projeto “lista de desejos” que você criou, clique com o botão direito do mouse no nó dos arquivos de código-fonte e, no menu de contexto, selecione Novo > Página Web PHP. O assistente Nova Página Web de PHP é aberto.
2. Digite  ``wishlist``  no campo Nome do Arquivo e pressione Finalizar.
3. Clique com o botão direito do mouse no nó Código-fonte e selecione Executar Projeto no menu de contexto ou clique no ícone Executar Projeto Principal image:images/run-main-project-button.png[]na barra de ferramentas, caso você tenha definido o seu projeto como Principal. 

image::images/index-php-works.png[]



. Na lista de desejos Mostrar : caixa de edição, digite Tom e clique em Ir. Uma página vazia com a seguinte URL aparecerá: http://localhost:90/Lesson2/wishlist.php?user=tom. Esse URL indica que a sua página principal funciona corretamente.


== Estabelecendo a Conexão e Obtendo o Wisher ID

Nesta seção, você primeiro adiciona o código ao arquivo  ``wishlist.php``  que cria uma conexão ao banco de dados. Em seguida, adiciona o código para recuperar o número do wisher ID cujo nome foi digitado no form  ``index.php`` .

1. Clique duas vezes no arquivo wishlist.php. O modelo que se abre é diferente do index.php. Comece e termine o arquivo com as tags <html></html> e <body></body>, já que o arquivo também conterá um código HTML.

[source,php]
----
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title></title>
    </head>
    <body>
        <?php
            // put your code here
        ?>
    </body>
</html>

----


. Para exibir o título, digite o seguinte bloco de código imediatamente depois da tag de abertura <body>, antes da tag <?php gerada:

[source,php]
----

 Wish List of <?php echo htmlentities($_GET["user"])."<br/>";?>
----

O código agora tem a seguinte aparência:


[source,php]
----

<body>Wish List of <?php echo htmlentities($_GET["user"])."<br/>";?><?php// put your code here</body>

----

O bloco de código PHP exibe os dados recebidos usando o método GET no campo "user". Esses dados são transferidos do  ``index.php``  onde o nome do proprietário da lista de desejos Tom foi inserido no campo de texto "user". Repita as etapas de <<createNewFile,Testando index.php>> para ver se o wishlist.php funciona corretamente. 

image::images/wishlist-php-title-works.png[]



. Delete a seção comentada no bloco PHP do modelo. Em seu lugar, digite ou cole no código a seguir. Esse código abre a conexão ao banco de dados.

*Para o banco de dados MySQL:*


[source,php]
----
$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');

----

*Para o banco de dados Oracle:*


[source,php]
----
$con = oci_connect("phpuser", "phpuserpw", "localhost/XE", "AL32UTF8");
if (!$con) {
    $m = oci_error();
    exit('Connect Error ' . $m['message']);
}
----

O código tenta abrir uma conexão ao banco de dados e gera uma mensagem de erro, caso haja uma falha.

*Observação para os usuários do banco de dados Oracle:* Pode ser preciso alterar a conexão ao banco de dados no comando  ``oci_connect`` . A sintaxe padrão é “nome do host/nome do serviço". A conexão ao banco de dados Oracle XE nesse snippet de código é “localhost/XE” para seguir essa sintaxe.

NOTE:  É possível usar a funcionalidade autocompletar código do NetBeans IDE para as funções mysqli ou OCI8.

image::images/codecompletion.png[]image::images/codecompletion-oci.png[]



. Abaixo do código para abrir a conexão ao banco de dados, no mesmo bloco PHP, digite ou cole o código a seguir. Esse código recupera o wisher ID cuja lista tenha sido solicitada. Se o wisher não estiver no banco de dados, o código terminará o processo, ou sairá dele, e exibirá uma mensagem de erro.

*Para o banco de dados MySQL:*


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

*Para o banco de dados Oracle:* (Observe que o oci8 não tem um equivalente para  ``mysqli_num_rows`` )


[source,php]
----
$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) {
    exit("The person " . $user . " is not found. Please check the spelling and try again" );
}
$wisherID = $row['ID'];
oci_free_statement($stid);

----

Os dados são selecionados no banco de dados  ``wishlist``  usando a conexão $con. O critério de seleção é o nome recebido do index.php como "user".

A sintaxe de uma instrução SQL  ``SELECT``  pode ser descrita brevemente da seguinte forma:

* Depois de SELECT, especifique os campos dos quais você deseja obter os dados. Um asterisco (*) representa todos os campos.
* Depois da cláusula FROM, especifique o nome da tabela da qual os dados devem ser recuperados.
* A cláusula WHERE é opcional. Especifique as condições do filtro nela.

A consulta mysqli retorna um objeto de resultado. O OCI8 retorna uma instrução executada. Em ambos os casos, você extrai uma linha como o resultado da consulta executada e extrai o valor da linha ID, armazendo-o na variável  ``$wisherID`` .

Por último, você libera o resultado da mysqli ou a instrução do OCI8. É necessário liberar todos os recursos que usam uma conexão antes que a conexão  seja fisicamente fechada. Do contrário, o sistema interno de  refcounting do PHP continuará mantendo a conexão do banco de dados subjacente aberta, mesmo se o  ``$con``  não for mais utilizável seguindo a chamada  ``mysqli_close()``  ou  ``oci_close()`` .

*Observação de segurança:* Para MySQL, o parâmetro  ``htmlentities($_GET["user"])``  tem escape para evitar os ataques de injeção SQL. Consulte link:http://en.wikipedia.org/wiki/SQL_injection[+Wikipedia sobre injeções SQL+] e a documentação mysql_real_escape_string. Embora no contexto deste tutorial você não esteja correndo o risco de injeções SQL prejudiciais, recomendamos escapar as strings nas consultas MySQL que estariam correndo risco de tal ataque. O OCI8 evita isso por meio de variáveis de bind.

Este bloco PHP agora está concluído. Se você estiver usando um banco de dados MySQL, o arquivo  ``wishlist.php``  se parecerá com o seguinte:


[source,php]
----

Wish List of <?php echo htmlentities($_GET["user"]) . "<br/>"; ?><?php$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');
  mysqli_select_db($con, "wishlist");
  $user = mysqli_real_escape_string($con, htmlentities($_GET["user"]));
  $wisher = mysqli_query($con, "SELECT id FROM wishers WHERE name='" . $user . "'");
  if (mysqli_num_rows($wisher) < 1) {
     exit("The person " . htmlentities($_GET["user"]) . " is not found. Please check the spelling and try again");
  }
  $row = mysqli_fetch_row($wisher);
  $wisherID = $row[0];
  mysqli_free_result($wisher);
  ?>
----

Se você estiver usando um banco de dados Oracle, o arquivo  ``wishlist.php``  se parecerá com o seguinte:


[source,php]
----

Wish List of <?php echo htmlentities($_GET["user"]) . "<br/>"; ?>
  <?php
  $con = oci_connect("phpuser", "phpuserpw", "localhost/XE", "AL32UTF8");
  if (!$con) {
     $m = oci_error();
     exit('Connect Error ' . $m['message'];
     exit;
  }
  $query = "SELECT id FROM wishers WHERE name = :user_bv";
  $stid = oci_parse($con, $query);
  $user = htmlentities($_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) {
     exit("The person " . $user . " is not found. Please check the spelling and try again" );
  }
  $wisherID = $row["ID"]; 
  oci_free_statement($stid);
  ?>
----

Se você testar a aplicação e inserir um usuário inválido, a mensagem seguinte aparecerá.

image::images/wishlist-php-title-user-not-found-works.png[]


== Exibindo uma Tabela de Desejos

Nessa seção, você pode adicionar o código que exibe uma tabela HTML dos desejos associados ao wisher. O wisher é identificado pelo ID recuperada no código da seção anterior.

1. Abaixo do bloco PHP, digite ou cole o seguinte bloco de código HTML. Esse código abre uma tabela, especifica a cor de suas bordas (preto), e "desenha" o cabeçalho da tabela com as colunas "Item" e "Data de vencimento."

[source,xml]
----

<table border="black">
    <tr>
        <th>Item</th>
        <th>Due Date</th>
    </tr>
</table>
----
A tag </table> fecha a tabela.


. Insira o seguinte bloco de código PHP acima da tag de fechamento </table>.

*Para o banco de dados MySQL:*


[source,php]
----

<?php$result = mysqli_query($con, "SELECT description, due_date FROM wishes WHERE wisher_id=" . $wisherID);while ($row = mysqli_fetch_array($result)) {echo "<tr><td>" . htmlentities($row["description"]) . "</td>";echo "<td>" . htmlentities($row["due_date"]) . "</td></tr>\n";}mysqli_free_result($result);mysqli_close($con);?>
----

*Para o banco de dados Oracle:*


[source,php]
----

<?php$query = "SELECT description, due_date FROM wishes WHERE wisher_id = :id_bv";$stid = oci_parse($con, $query);oci_bind_by_name($stid, ":id_bv", $wisherID);oci_execute($stid);while ($row = oci_fetch_array($stid)) {echo "<tr><td>" . htmlentities($row["DESCRIPTION"]) . "</td>";echo "<td>" . htmlentities($row["DUE_DATE"]) . "</td></tr>\n";}oci_free_statement($stid);oci_close($con);?>
----

Dentro do código:

* A consulta SELECT recupera os desejos com suas datas de vencimento para o whisher especificado por seu ID, que foi recuperada na etapa 4, e armazena os desejos e as datas de vencimento em um array $result.
* Um loop exibe os itens do array $result como linhas na tabela enquanto o array não está vazio.
* As linhas do form das tags <tr></tr>, as células do form das tags <td></td> nas linhas, e \n inicia uma nova linha.
* A função  ``htmlentities``  converte todos os caracteres que tenham a entidade HTML equivalentes às entradas HTML. Isso ajuda a prevenir link:http://en.wikipedia.org/wiki/Cross-site_scripting[+scripts de site cruzados+].
* As funções, no final, liberam todos os recursos (resultados do mysqli e instruções do OCI8) e fecha a conexão ao banco de dados. Observe que é necessário liberar os recursos que usam uma conexão antes que a conexão possa ser fisicamente fechada. Do contrário, o sistema interno de refcounting do PHP manterá a conexão do banco de dados subjacente aberta, mesmo se a conexão não for mais utilizável seguindo a chamada  ``oci_close()``  ou  ``mysqli_close()`` .

*Cuidado: *Certifique-se de digitar os nomes dos campos de banco de dados exatamente como eles foram especificados durante a criação da tabela do banco de dados. Para Oracle, os nomes das colunas são retornados com letras maiúsculas por default.



. Para testar a aplicação, execute o projeto como descrito na seção <<createNewFile,Testando index.php>>.

image::images/wishlist-php-works.png[]


== O código-fonte da Aplicação após a Lição Atual está Concluído

Usuários MySQL: clique link:https://netbeans.org/files/documents/4/1928/lesson2.zip[+aqui+] para fazer o download do código-fonte que reflete o estado do projeto depois que a lição estiver concluída.

Usuários de banco de dados Oracle: clique link:https://netbeans.org/projects/www/downloads/download/php%252Foracle-lesson2.zip[+aqui+] para fazer o download do código-fonte que reflete o estado do projeto depois que a lição estiver concluída.


== Próxima Etapa

link:wish-list-lesson1.html[+<< Lição anterior+]

link:wish-list-lesson3.html[+Próxima lição >>+]

link:wish-list-tutorial-main-page.html[+Voltar à Página Principal do Tutorial+]



