7. Recursos PHP para a Internet Protocolo HTTP. Na aula passada vimos um script simples de autenticação de usuários. Neste script foi usado o tag META para passar uma URL ao servidor web. A linguagem PHP dispõe da função header para facilitar esta tarefa. <html> <body> <form action="aula07_01.php" method="post"> Login: <input type="text" name="login"> Senha: <input type="password" name="senha"><br><br> <input type="submit" value=" Entrar "> </form> </body> </html> <?php function validar($login, $senha) { // Inserir aqui o código de validação return (($login == "senne") && ($senha == "feg2003")); // Aqui comeca o script principal if (validar($login,$senha)) header("location: http://localhost/daiaula07/autoriza.php"); else echo("<h1>usuário não autorizado!!!</h1>");?> aula07_01.htm aula07_01.php Note que com o protocolo HTTP é possível executar um script PHP a partir de outro script PHP. ELFS, 2003 167
Exercício. Considere uma página como mostra a figura abaixo. Implementar o script aula07_02.php que exibe a página da instituição selecionada. aula07_02.htm E-Mail. A função mail() do PHP deve ser usada para envio de e-mail. Sua sintaxe é a seguinte: mail(destinatário, Assunto, Mensagem, Informações_Adicionais); Exemplo: aula07_03.htm Considere que, para serem enviados, os dados devem satisfazer as seguintes condições: Todos os campos são obrigatórios; A consistência do campo e-mail deve ser feita verificando apenas a existência do caractere @; O campo telefone deve ter sete ou oito caracteres. ELFS, 2003 168
<?php $erro = ""; aula07_03.php if ($nome == "") $erro.= "O nome não foi digitado.<br>"; Note nas atribuições à variável $erro o uso combinado dos operadores de concatenação (. ) e de atribuição ( = ) resultando no operador (.= ). Escrever $erro.= "string" é equivalente a escrever: $erro = $erro. "string" if ((strlen($telefone) > 8) (strlen($telefone) < 7)) $erro.= "O número do telefone deve ter sete ou oito caracteres.<br>"; if (strpos ($email, "@") == 0) $erro.= "O e-mail fornecido não é válido.<br>"; echo("<html><title>envio de formulário</title><body>\n"); if ($erro == "") { // Não houve erro no preenchimento do formulário mail("seu_email@feg.unesp.br", "Dados do Formulário", "Nome: $nome\n Telefone: $telefone\n E-mail: $email"); echo("obrigado por enviar seus dados!\n"); else echo("seus dados não foram enviados!<br> Verifique as mensagens de erro abaixo:<br><br><b> $erro </b>"); echo("</body></html>");?> Para usar a função mail é preciso configurar a sessão [mail function] do arquivo c:\apache\php\php.ini: SMTP = mail.feg.unesp.br sendmail_from = seu_email@seu_domínio.br ELFS, 2003 169
Upload de arquivos. Existe um tipo de campo de formulário que permite o envio de arquivos da máquina do usuário para o servidor. Isto é muito útil para enviar um arquivo para o servidor sem a necessidade de liberação de um acesso por FTP. Exemplo: aula07_04.htm <html> <body> <form action="aula07_04.php" method="post" enctype="multipart/form-data"> <input type="file" name="arq"><br><br> <input type="submit" value=" Enviar "> </form> </body> </html> Neste caso, como o nome do campo é arq, o script PHP terá acesso a duas variáveis: $arq (arquivo temporário referente ao arquivo especificado após clique no botão Browse...) e $arq_name (nome do arquivo). Se o botão Browse... não for usado para especificar o arquivo, $arq = "none". aula07_04.php <?php echo("<html><body>"); if (($arq == "none") or ($arq_name == "")) { echo("<p>arquivo não especificado!</p>"); echo("<p><a href=javascript:history.back();>voltar</a></p>"); A disjunção lógica é representada pelo operador ou pela palavra or. ELFS, 2003 170
else { $dest = "c:\\apache\\htdocs\\daiaula07\\".$arq_name; if (copy($arq, $dest) == 0) echo("<p>não foi possível copiar o arquivo!</p>"); else echo("<p>upload realizado com sucesso!</p>"); echo("</body></html>");?> A função int copy(string origem, string destino) copia o arquivo origem para o arquivo destino. Os strings origem e destino devem conter os nomes completos dos arquivos (incluindo os caminhos). A pasta destino deve existir (até mesmo em outro computador) e permitir gravação para que a cópia seja realizada. A função retorna 0 (false) caso a cópia não seja realizada. Protocolo FTP. A seqüência de tarefas para uso do protocolo FTP é a seguinte: Conectar ao servidor, Identificação (login e senha), Envio/Busca de arquivo(s), Desconectar. Os comandos para cada uma destas tarefas são os seguintes: $con = ftp_connect('servidor'); $log = ftp_login($con, 'login', 'senha'); ftp_put($con, 'arquivo_remoto', 'arquivo_local', FTP_BINARY); ftp_quit($con); Para download é só usar a função ftp_get($con, 'arquivo_local','arquivo_remoto', FTP_BINARY); ELFS, 2003 171
Exercício. Refazer a aplicação de upload de arquivos de modo a usar o protocolo FTP. Use o servidor 200.145.11.141, usuário "teste_php" e senha "123456789". Em seguida, experimente fazer o download do arquivo copiado no servidor para a pasta c:\temp. Cookies. Os cookies são usados para gravar alguma informação no computador cliente. Cada cookie representa um par (nome, valor). Cookies são úteis para armazenar algumas informações do usuário, tais como a quantidade de vezes que já visitou a página, ou algum dado fornecido numa visita anterior. Existem cookies persistentes e cookies de sessão. Os cookies persistentes são gravados em arquivo e perduram mesmo após o browser ser fechado, mas possuem data e hora de expiração. Os cookies de sessão não são armazenados em disco e permanecem ativos apenas enquanto a sessão do browser não for encerrada. Por padrão, existem algumas limitações para o uso de cookies: 300 cookies no total, 4 Kbytes por cookie, 20 cookies por servidor ou domínio. Para gravar cookies no cliente, deve ser utilizada a função setcookie(), que possui a seguinte assinatura: int setcookie(string nome, string valor, int exp, string path, string dominio, int segura); onde: nome - nome do cookie; valor - valor armazenado no cookie; ELFS, 2003 172
exp - data de expiração do cookie (opcional). Se não for definida, o cookie será de sessão; path - path do script que gravou o cookie; dominio - domínio responsável pelo cookie; segura - o valor 1 indica que o cookie só pode ser transmitido por uma conexão segura (https). Exemplo: setcookie("campus", "FEG", time()+3600); Neste caso, será gravado um cookie de nome "Campus" e valor "FEG", com tempo de expiração de uma hora (3600 segundos além do horário atual). Importante: Cookies só podem ser gravados antes do envio de qualquer informação para o cliente. Portanto todas as chamadas à função setcookie() devem ser feitas antes do envio de qualquer header ou texto. Existem duas formas de recuperar cookies gravados por scripts PHP: acessando o array $HTTP_COOKIE_VARS[] com índice igual ao nome do cookie; acessando uma variável $nome, onde nome é o nome do cookie. Por exemplo, para recuperar o valor do cookie acima podemos escrever: $HTTP_COOKIE_VARS["Campus"] ou $Campus ELFS, 2003 173
aula07_05.htm <html> <head> <title>exemplo de Cookie</title> </head> <body> <h2>exemplo de Cookie</h2> <form action="aula07_05.php" method="post"> <p>nome: <input type="text" name="nome"></p> <p>valor: <input type="text" name="valor"></p> <br> <p> <input type="radio" name="escolha" value="1" checked>armazenar</input> <input type="radio" name="escolha" value="2">recuperar</input> </p> <input type="reset" value="limpar"> <input type="submit" value="executar"> </form> </body> </html> O script aula07_05.php irá, com base no valor da variável $Escolha, gravar ou recuperar um cookie de sessão. ELFS, 2003 174
aula07_05.php <?php if ($Escolha == "1") { Note que a função setcookie() deve ser executada setcookie($nome, $Valor); antes de que algo seja enviado ao cliente. echo("<html><body>"); echo("<h2>cookie armazenado: ($Nome, $Valor)</h2>"); else { $Valor = $HTTP_COOKIE_VARS[$Nome]; if ($Valor == "") echo("<h2>não existe cookie $Nome!</h2>"); else echo("<h2>cookie recuperado: ($Nome, $Valor)</h2>"); echo("</body></html>");?> Defina alguns cookies e tente recuperá-los. Em seguida, feche o browser e carregue a página aula07_05.htm novamente e tente recuperar os cookies definidos. O que ocorre? ELFS, 2003 175
Tratamento de Erros A linguagem PHP permite a verificação e o tratamento de erros ocorridos na execução de scripts. O tratamento de erros pode ser feito no próprio script. O PHP possui vários níveis de erros e avisos, os quais são estabelecidos por constantes pré-definidas (ou por valores inteiros). Algumas constantes de erro: Constante E_ERROR E_WARNING E_PARSE E_NOTICE Valor 1 2 4 8 Significado Erros fatais (não podem ser recuperados), tais como: erros de alocação de memória. Advertências (a execução do script não é interrompida). Erros de sintaxe (parse errors). Notificações de possíveis erros (avisos sobre possíveis erros no código do script). Interessante para a depuração do script. E_ALL 2047 Todos os erros e advertências. O padrão do PHP é o nível E_ALL & ~E_NOTICE, ou seja, mostrar todos os erros exceto as notificações. Isto pode ser alterado em tempo de execução, chamando a função error_reporting(nível) com o nível desejado. Por exemplo, error_reporting(e_error E_WARNING E_PARSE), o que é equivalente a error_reporting(7). Note que 7 = 1 + 2 + 4, que são os valores inteiros associados às constantes E_ERROR, E_WARNING e E_PARSE. ELFS, 2003 176
Com o nível 0 (zero) nenhum aviso ou mensagem de erro será gerada em tempo de execução. Neste caso, podemos usar a variável $php_errormsg que conterá o último erro gerado pelo script, para criar rotinas específicas de tratamento de erros e para personalizar mensagens de erro para o usuário. Para criar rotinas de tratamento de erros e para a exibição de todas as mensagens de erro é preciso configurar o arquivo c:\apache\php\php.ini, alterando a diretiva track_erros para: track_errors = on. Exemplo. O script a seguir irá criar um arquivo erro.log (em formato XML) e irá enviar um e-mail com as mensagens de erro. <?php // Inibir a exibição automática de erros error_reporting(0); // Função de tratamento de erros function TrataErro($errno, $errmsg, $filename, $linenum) { // Data e hora para mensagem de erro $dhora = date("y-m-d H:i:s"); // Vetor de tipos de erro. $errortype = array ( 1 => "Erro", 2 => "Advertência", 4 => "Erro de sintaxe", aula07_06.php A função para tratamento de erros definida pelo usuário deve ter dois parâmetros obrigatórios: o número do erro e um string descrevendo o erro. A função pode ter três outros parâmetros opcionais: o nome do arquivo onde o erro ocorreu, o número da linha onde o erro ocorreu, e o contexto no qual o erro ocorreu. ELFS, 2003 177
8 => "Notificação", 16 => "Erro do interpretador PHP", 32 => "Advertência do interpretador PHP", 64 => "Erro de compilação", 128 => "Advertência de compilação", 256 => "Erro definido pelo usuário", 512 => "Advertência definida pelo usuário", 1024=> "Notificação definida pelo usuário" ); // Estabelecer os tipos para os quais serão exibidas mensagens de erro $user_errors = array(e_user_error, E_USER_WARNING, E_USER_NOTICE); $erro = "<erro>\r\n"; $erro.= "\t<data-e-hora>".$dhora."</data-e-hora>\r\n"; $erro.= "\t<numero-do-erro>".$errno."</numero-do-erro>\r\n"; $erro.= "\t<tipo-do-erro>".$errortype[$errno]."</tipo-do-erro>\r\n"; $erro.= "\t<mensagem>".$errmsg."</mensagem>\r\n"; if (in_array($errno, $user_errors)) $erro.= "\t<comentário>mensagem do usuário!!</comentário>\r\n"; $erro.= "\t<script>".$filename."</script>\r\n"; $erro.= "\t<linha-no-script>".$linenum."</linha-no-script>\r\n"; $erro.= "</erro>\r\n"; ELFS, 2003 178
// Para testar // echo $erro; // Salvar arquivo erro.log e enviar e-mail caso haja erro crítico error_log($erro, 3, "erro.log"); if ($errno == E_USER_ERROR) mail("seu_email@feg.unesp.br","erro Crítico",$erro); function distancia($vect1, $vect2) { if (!is_array($vect1)!is_array($vect2)) { trigger_error("parâmetros incorretos (são esperados vetores).", E_USER_ERROR); return NULL; A função trigger_error gera uma mensagem de erro, advertência ou notificação definida pelo usuário. if (count($vect1)!= count($vect2)) { trigger_error("vetores precisam ser do mesmo tamanho.", E_USER_ERROR); return NULL; for ($i=0; $i<count($vect1); $i++) { $c1 = $vect1[$i]; $c2 = $vect2[$i]; $d = 0.0; ELFS, 2003 179
if (!is_numeric($c1)) { trigger_error("coordenada $i no vetor 1 considerada como zero.", E_USER_WARNING); $c1 = 0.0; if (!is_numeric($c2)) { trigger_error("coordenada $i no vetor 2 considerada como zero.", E_USER_WARNING); $c2 = 0.0; $d += $c2*$c2 - $c1*$c1; return sqrt($d); A função set_error_handler estabelece uma função definida pelo usuário para o tratamento de erros, advertências ou notificações. A função retorna o tratador de erro anterior (caso exista). $old_error_handler = set_error_handler("trataerro"); // Constante indefinida, gerar uma advertência. $t = NAO_ESTOU_DEFINIDA; // Definir alguns vetores $a = array(2,3,"bobo"); $b = array(5.5, 4.3, -1.6); $c = array (1,-3); ELFS, 2003 180
?> // Gerar um erro de usuário $t1 = distancia($c,$b)."\n"; // Gerar outro erro $t2 = distancia($b,"eu não sou um vetor")."\n"; // Gerar uma advertência $t3 = distancia($a,$b)."\n"; A função error_log envia uma mensagem de erro para o servidor web, para uma porta TCP ou para um arquivo. O segundo parâmetro da função especifica qual deve ser o destino da mensagem. Os valores possíveis são: 0 - a mensagem é enviada para o sistema de log mantido pelo PHP (ou para um arquivo, dependendo de como está configurada a diretiva error_log). 1 - a mensagem é enviada por e-mail para o endereço especificado no terceiro parâmetro. 2 - a mensagem é enviada para um endereço IP (e, opcionalmente, para uma porta) estabelecido no terceiro parâmetro. 3 - ELFS, 2003 181
Exercício. Criar um site para manutenção do quadro de horários de uma escola. Considere as seguintes funcionalidades: Crie um novo banco de dados MySQL horario contendo duas tabelas: horario, com campos codhora (smallint) e horario (varchar(11)) e disciplinas, com campos coddisc(smallint) e nomedisc (varchar(20)). O botão Executar deverá executar a operação de banco de dados selecionada (Incluir, Excluir ou Alterar) correspondente aos dados estabelecidos nos campos Dia, Horário e Disciplina. O botão Mostrar deverá exibir o quadro de horário atual como um documento HTML, de acordo com as informações armazenadas no banco de dados. O botão Enviar deverá enviar uma mensagem com as informações do quadro de horário atual para um endereço de e-mail. ELFS, 2003 182