Baixe o app para aproveitar ainda mais
Prévia do material em texto
AN02FREV001/REV 4.0 1 PROGRAMA DE EDUCAÇÃO CONTINUADA A DISTÂNCIA Portal Educação CURSO DE AJAX E PHP COMO LINGUAGEM DE SERVIDOR Aluno: EaD - Educação a Distância Portal Educação AN02FREV001/REV 4.0 2 CURSO DE AJAX E PHP COMO LINGUAGEM DE SERVIDOR MÓDULO III Atenção: O material deste módulo está disponível apenas como parâmetro de estudos para este Programa de Educação Continuada. É proibida qualquer forma de comercialização ou distribuição do mesmo sem a autorização expressa do Portal Educação. Os créditos do conteúdo aqui contido são dados aos seus respectivos autores descritos nas Referências Bibliográficas. AN02FREV001/REV 4.0 3 SUMÁRIO 1 REQUISIÇÕES USANDO O XMLHTTPREQUEST 1.1 O XMLHTTPREQUEST 1.2 ARQUIVO PHP PARA SER INVOCADO POR UMA REQUISIÇÃO 1.3 PRIMEIRO EXEMPLO DE CONEXÃO USANDO O XMLHTTPREQUEST 1.4 JUNTANDO O CLIENTE E O SERVIDOR 1.5 ESTADOS DE RETORNO DE UMA REQUISIÇÃO 1.6 PROCESSANDO PARÂMETROS 1.7 TRATAMENTO DE EXCEÇÕES REFERÊNCIAS BIBLIOGRÁFICAS AN02FREV001/REV 4.0 4 1 REQUISIÇÕES USANDO O XMLHTTPREQUEST 1.1 O XMLHTTPREQUEST Em poucas palavras, o XMLHttpRequest é um objeto definido dentro do Javascript que torna possível a comunicação assíncrona com um servidor web, sem a necessidade de recarregar a página por completo. Ele vai servir de base para o desenvolvimento das aplicações escritas seguindo a plataforma AJAX, pois fará as conexões como servidor, recuperará alguma informação e a deixará disponível para uso no cliente. Com a disponibilização de dados em formato XML e o uso de serviços por uma grande quantidade de empresas, pode ser necessário ou conveniente que o próprio documento HTML se conecte ao servidor que oferece o conteúdo em XML para obter alguma informação. A existência deste objeto dentro do contexto do Javascript oferece essa possibilidade, repassando a informação obtida em seguida fazendo com que alguma atualização nos objetos DOM (Document Object Model) da página possa ser manipulada. Como ele executa no lado do cliente, devem ser considerados os pontos específicos de cada navegador nesse momento, pois cada qual implementa este objeto de uma determinada forma. Assim, a criação dos respectivos objetos para a conexão ao servidor seguiria o seguinte padrão: <script language=”javascript”> var req = new XMLHttpRequest(); </script> O exemplo acima cria um objeto para a conexão ao servidor em plataformas que derivam do Firefox ou que seguem o padrão estabelecido pelo W3C para conexões remotas usando AJAX. O código sempre deve existir dentro de um bloco de código Javascript, normalmente no cabeçalho da página. <script language=”javascript”> var req = new ActiveXObject("Microsoft.XMLHTTP"); </script> AN02FREV001/REV 4.0 5 Ao se trabalhar com esse tipo de objeto em navegadores da Microsoft, ainda é necessário considerar um caso especial, pois a Microsoft não segue o padrão dos objetos existentes para se trabalhar com conexões remotas (a empresa nunca primou por seguir padrão, preferindo sempre criar cópias baseadas naquilo que existe no mercado e gerando uma ruptura na compatibilidade dos sistemas, o que é extremamente crítico para sistemas na web). O objetivo é o mesmo e o objeto tem a mesma função, estabelecer uma conexão assíncrona com um servidor, só que usa de objetos que o Microsoft Internet Explorer entenda. No momento em que a conexão está sendo aberta, como dificilmente se tem em qual navegador a aplicação irá rodar, o código tem que estar preparado para considerar ambos, tratando cada caso especial. Isso torna a programação mais complexa e maçante, mas é o preço pago para oferecer o máximo de compatibilidade ao usuário. Existem algumas bibliotecas e sistemas nos dias de hoje que geram código compatível para diferentes navegadores a partir de uma linguagem única, o que torna o processo mesmo difícil. 1.2 ARQUIVO PHP PARA SER INVOCADO POR UMA REQUISIÇÃO Sempre que se trabalha com programação cliente/servidor é necessário ter código no lado cliente e também no lado servidor. No momento, estamos trabalhando tendo o navegador na máquina do usuário como cliente e um servidor remoto Apache executando e servindo páginas PHP como servidor. No contexto do AJAX, esse servidor poderia ser trocado por qualquer tecnologia que trabalhe requisições HTTP, como JSP, Perl ou Microsoft ASP, com poucas variações a menos das específicas da sintaxe da linguagem de programação. O contexto desta seção é mostrar como deve ser escrito um arquivo com código PHP que ao ser requisitado por uma página que use AJAX deve AN02FREV001/REV 4.0 6 responder. Como será visto, é algo bem próximo do encontrado num arquivo normal em que o resultado fosse diretamente mostrado na tela do usuário. Veja um exemplo simples: <?php echo "data requisicao: " . date("d-m-Y"); ?> Repare que o arquivo PHP criado não possui nada de diferente de um arquivo normalmente escrito na linguagem. Caso ele seja invocado diretamente num navegador, ele imprimirá na tela o texto entre aspas seguido da data atual do servidor. Este deve ser um arquivo separado, que para fins do exemplo será chamado de pega_data.php e este, sim, é de extrema importância que seja um arquivo PHP, pois ele fará uso da lógica presente nas estruturas do PHP. 1.3 PRIMEIRO EXEMPLO DE CONEXÃO USANDO O XMLHTTPREQUEST Antes de realizar qualquer alteração na página do lado do cliente, precisamos estabelecer uma conexão com o servidor para futuramente buscar alguma informação nele. Iremos definir agora uma função padrão, em Javascript, que abre a conexão com um servidor definido como parâmetro e deixa ativo um objeto do tipo XMLHttpRequest para futuras invocações: <html> <head> <script language=”javascript”> var req; function carrega_http_request(url) { req = false; if (window.XMLHttpRequest && !(window.ActiveXObject)) { try { req = new XMLHttpRequest(); AN02FREV001/REV 4.0 7 } catch(e) { req = false; } } else if(window.ActiveXObject) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } } if (req) { req.onreadystatechange = alerta_resultado; req.open("GET", url, true); req.send(""); } 007D </script> </head> </html> Vamos analisar cada um dos pontos da função acima. Primeiro, a definição de um bloco Javascript que deve ser colocada diretamente no cabeçalho do documento HTML que fará uso da interatividade com AJAX. Dentro dele está definida uma variável global, que fica disponível para todas as funções e demais trechos do Javascript. Essa variável será a responsável por armazenar a conexão com o servidor. Em seguida, define-se uma função que inicializa a conexão com o servidor e que deve possuir todo o tratamento dos casos especiais que cada navegador tem no momento de abrir uma conexão daquele tipo. Associado ao objeto window (que representa a tela do navegador), caso o browser derive da família Firefox ou então siga o padrão estabelecido pelo W3C, ele terá o objeto XMLHttpRequest e não o objeto correspondente para o caso do Internet Explorer. Caso essas condições sejam verdade, tenta-se estabelecer a conexão usando ele, sempre abraçado por um bloco try/catch, pois pode gerar um erro. AN02FREV001/REV 4.0 8 Vale uma observação a respeito do bloco try/catch, estrutura que existe em diversas outras linguagens de programação, especialmente as mais modernas, que traz uma maneira de controlar os erros gerados pelo código- fonte. Neste contexto, a ferramentade execução do Javascript do navegador tentará executar a instrução que estiver dentro do bloco try, caso ele consiga executar corretamente não será executada a instrução dentro do bloco catch, caso contrário, numa execução com erro dentro do fluxo normal, tenta-se executar o que está ali. Por outro lado, caso esse código seja executado dentro de um navegador da Microsoft, os testes serão avaliados e tentarão cair dentro do bloco else if. Mesmo ali, existem duas possibilidades, pois cada versão dos navegadores da Microsoft implementa um tipo de objeto de conexão remota. Tenta-se primeiro o mais recente, caso ele gere algum erro, tenta-se com a versão mais antiga, pois deve tratar-se de um navegador mais antigo. A todo o momento, caso algum erro seja gerado e não seja possível recuperá-lo para um estado em que fique correto, a variável req será marcada como false, como uma indicação de que houve algum problema que não pode ser recuperado. Ao final, depois que as tentativas de conexão foram todas feitas, essa variável é testada. Caso ela tenha um conteúdo diferente de false, quer dizer que criação do objeto foi corretamente feita e pode-se passar para o passo em que a conexão com o servidor é realizada, bem como a passagem de parâmetros, que será vista a seguir. As três linhas que executam a conexão propriamente dita com o servidor de aplicações remoto caso o objeto tenha sido corretamente criado, requisitando alguma informação, são importantes de entender, ainda que elas devam ser pouco mexidas no futuro: • A primeira linha, “req.onreadystatechange = alerta_resultado;” indica qual função dentro da página deve ser chamada assim que o servidor devolver a requisição feita com o valor correto (repare que esse comportamento está associado ao objeto req que acabou de ser configurado. • A segunda linha, “req.open("GET", url, true);” abre a conexão AN02FREV001/REV 4.0 9 com o servidor a partir de uma dada URL passada como argumento para esta função. Além disso, existe a indicação do método de envio dos dados (os valores possíveis são GET ou POST) e o terceiro argumento indica se a chamada deve ser assíncrona ou não. Passando o valor true indica que ela é assíncrona e não precisa aguardar o processamento para disparar outra chamada. • Por fim, a terceira linha, “req.send("");”, faz o disparo da requisição. No momento, está sendo passada uma string vazia, mas caso a função no servidor espere receber parâmetros para realizar algum processamento, é neste ponto que eles devem ser definidos. A execução dessa função deve acontecer apenas uma vez para cada carregamento da página, criando apenas um objeto por vez, evitando o desperdício de recursos ou que sejam mantidas muitas conexões abertas com o servidor, o que pode tornar o sistema mais lento como um todo. Para continuar o exemplo completo deste código em AJAX, considere que o código escrito acima foi colocado em um arquivo chamado entrada.html. Veja que neste momento não estamos interessados em processamento dinâmico usando o PHP diretamente e sim o conteúdo retornado pela chamada ao servidor, o que nos permite usar apenas Javascript para alterar esta página. 1.4 JUNTANDO O CLIENTE E O SERVIDOR Por enquanto, os dois arquivos mostrados nas seções anteriores são independentes, não possuindo qualquer relação que os faça interagir. Será necessário, portanto, alterar algum ponto dos códigos para que isso possa ser feito. A parte servidora, por hora, está finalizada, pois ela simplesmente irá retornar uma cadeia de caracteres sempre que uma requisição do servidor assim a invocar. Por conta disso, seria natural supor que a alteração aconteça na parte cliente, que de alguma forma precisará invocar o arquivo PHP para ele AN02FREV001/REV 4.0 10 devolver o resultado desejado, mas tenha em mente que o arquivo original não será trocado, como normalmente aconteceria em uma requisição ao servidor para buscar uma nova página PHP. Já a parte cliente precisa ser alterada para incluir agora o tratamento que será feito no momento que o servidor retornar alguma informação. O bloco exemplificado no exemplo anterior mostra a parte de conexão e disparo da requisição, mas ainda não traz qual o comportamento da função Javascript que irá tratar o retorno e nem de que forma a chamada assíncrona será disparada. Em geral, é necessário associar a chamada assíncrona a algum evento dos objetos do navegador, como o onclick() (quando um elemento é clicado) ou o onfocus() (quando algum elemento recebe o foco do cursor). Para a continuação deste exemplo, iremos modificar o arquivo entrada.html para que ele receba um botão que dispara a chamada da função AJAX e receba o comportamento que deve ser disparado no retorno. <html> <head> <script language="javascript"> var req; function carrega_http_request(url) { req = false; if (window.XMLHttpRequest && !(window.ActiveXObject)) { try { req = new XMLHttpRequest(); } catch(e) { req = false; } } else if(window.ActiveXObject) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } } AN02FREV001/REV 4.0 11 if (req) { req.onreadystatechange = alerta_resultado; req.open("GET", url, true); req.send(""); } } function alerta_resultado() { if (req.readyState == 4) { alert(req.responseText); } } </script> </head> <body> <input type="button" value="Apertar" onclick="carrega_http_request('pega_data.php')" /> </body> </html> A primeira parte do exemplo não muda, aquela que faz a conexão com o servidor e dispara a requisição para o cliente. O que foi acrescentado neste novo exemplo foi o comportamento da função alerta_resultado() que agora ao ser chamada verifica o código do estado da requisição e caso possua o estado 4, que significa que a requisição foi corretamente processada, exibe uma mensagem de alerta, com o conteúdo, em forma de texto, retornado pelo servidor. Nada desses blocos é executado a menos que o trecho logo abaixo seja invocado, que faz aparecer na tela um botão com o texto “Apertar” escrito nele. O evento onclick() é definido nele de tal forma que chame a função carrega_http_request() que, por sua vez, passa como argumento o nome do arquivo PHP que desejamos invocar, no caso é o mesmo arquivo definido há algumas seções, o pega_data.php. O resultado pode ser visto na próxima imagem: AN02FREV001/REV 4.0 12 FIGURA 1 - EXEMPLO FUNCIONANDO DE AJAX FONTE: Arquivo pessoal do autor. É mostrada uma mensagem de alerta do tipo Javascript, com um texto e mais a data e hora do servidor de aplicações web, segundo a formatação do arquivo PHP. 1.5 ESTADOS DE RETORNO DE UMA REQUISIÇÃO Como observado no exemplo acima, o objeto XMLHttpRequest foi testado em termos do valor 4 para a propriedade readyState, pois é esse o valor que indica que o processamento foi finalizado corretamente. Caso não fosse colocado esse teste, seriam disparadas quatro chamadas para a função, pois para cada mudança de estado, uma chamada diferente é avocada. Os possíveis estados existentes e disponíveis são: AN02FREV001/REV 4.0 13 • Valor 0: O processamento ainda não foi iniciado, indicando que o objeto foi criado mas o método open() não foi chamado ainda. • Valor 1: Ainda carregando, sendo que o método open() foi chamado mas a requisição não foi enviada ainda. • Valor 2: A requisição foi enviada. • Valor 3: Processamento ainda incompleto, pois apenas uma parte da resposta do servidor foi recebida. • Valor 4: Processamento completo, pois todas as informações foram recebidas e a conexão foi fechada com sucesso. Cada um deles possui um momento de execução, sendo que em geral estaremospreocupados apenas com o estado de valor 4, pois é ele que indica que todos os dados foram retornados e podem ser processados corretamente. Existem situações em que pode ser necessário o tratamento dos outros estados, mas isso deve acontecer apenas em situações bem específicas. 1.6 PROCESSANDO PARÂMETROS O exemplo anterior é básico, com o objetivo de mostrar todas as tecnologias envolvidas e componentes necessários para montar uma solução completa que use AJAX. Tanto é assim que nem foram enviados parâmetros para o servidor para que a consulta fosse modificada, sendo apenas necessário chamar o arquivo que retorna a data. Uma atividade normal que acaba acontecendo quando se trabalha com sistemas de informática é o envio de parâmetros para que algum código retorne informações baseada nela, assim iremos modificar o exemplo para que ele receba como parâmetro uma informação que retorne a data do servidor dentro de um formato desejado: em português (DD/MM/AAAA) ou em inglês (AAAA/MM/DD). O primeiro passo é alterar o servidor: AN02FREV001/REV 4.0 14 <?php $formato = 'por'; if (isset($_GET['formato'])) { $formato = $_GET['formato']; } $mascara = "d-m-Y"; if ($formato == 'ing') { $mascara = "Y-m-d"; } echo "data requisicao: " . date($mascara); ?> Novamente, o código no lado servidor é simples. Verifica-se se um parâmetro chamado formato foi enviado para o arquivo e caso tenha sido, ele é armazenado na variável $formato. Em seguida, testa-se se o conteúdo da variável é ing, indicando formato em inglês. Adota-se como padrão que a não informação da variável ou o não preenchimento dela, que a data será retornada em formato português. Agora é necessário alterar o lado do cliente, começando pela interface gráfica. O arquivo será alterado para que ele contenha um formulário e dois campos do tipo radio, indicando qual o idioma será escolhido: AN02FREV001/REV 4.0 15 <body> <form name="f" method="get" action=""> Formato da data: Português: <input type="radio" name="idioma" value="por" checked="checked"> Inglês: <input type="radio" name="idioma" value="ing"> <input type="button" value="Apertar" onclick="carrega_http_request('pega_data.php')" /> </form> </body> O exemplo acima omitiu a parte do Javascript, concentrando nas alterações de interface. O código continua a ser basicamente HTML, sem grandes modificações. O resultado do código é a seguinte tela: AN02FREV001/REV 4.0 16 FIGURA 2 - INTERFACE GRÁFICA MODIFICADA, COM AS DUAS OPÇÕES DE IDIOMA FONTE: Arquivo pessoal do autor. Dois campos são mostrados, sendo que o idioma português é marcado como sendo o valor padrão. Todo o restante por enquanto está igual, sendo que agora é necessário mudar a passagem de parâmetro do cliente para o arquivo PHP conseguir fazer o seu processamento. Será necessário alterar apenas um trecho da função carrega_http_request(): AN02FREV001/REV 4.0 17 // ... if (req) { req.onreadystatechange = alerta_resultado; envio = url + "?formato=" + get_idioma_escolhido(); req.open("GET", envio, true); req.send(""); } } function get_idioma_escolhido() { for (i = 0; i < document.forms[0].idioma.length; ++i) { if (document.forms[0].idioma[i].checked) { return document.forms[0].idioma[i].value; } } } Foi criada uma nova função Javascript chamada X, que retorna o valor da opção selecionada pelo usuário. Esse valor é concatenada na URL que é enviada para o servidor, montando uma query string, com a indicação do valor que deve ser passado como parâmetro (reveja que a variável é recuperada usando o supervetor GET, pois ele estará tratando requisições do tipo GET). A função open() é alterada para receber como argumento a nova URL, agora com um valor concatenado. O resultado pode ser observado na seguinte imagem: FIGURA 3 - MESMO RESULTADO, SÓ QUE EM INGLÊS FONTE: Arquivo pessoal do autor. AN02FREV001/REV 4.0 18 Caso mais de um parâmetro precise ser passado desta forma, eles podem ser concatenados usando o símbolo &. 1.7 TRATAMENTO DE EXCEÇÕES Toda tentativa de requisição pode gerar um problema caso o navegador não ofereça suporte à tecnologia empregada (isso acontece com maior frequência em versões mais antigas), ou quando o servidor está indisponível ou por algum problema na rede. Em todas essas situações, é uma boa prática incluir algum tratamento de exceção, informando ao usuário que algum problema aconteceu. Isso pode ser facilmente feito colocando mensagens de alerta nos blocos catch ou no final do tratamento da chamada da requisição. Algo seguindo a seguinte linha: // ... if (req) { req.onreadystatechange = alerta_resultado; envio = url + "?formato=" + get_idioma_escolhido(); req.open("GET", envio, true); req.send(""); } else { alert("Houve um erro ao estalecer uma conexao."); } // ... Repare que agora, sempre que uma requisição for disparada, mas por qualquer razão ela não for concluída, será mostrada uma mensagem para o usuário indicando que um problema aconteceu. FIM DO CONTEÚDO AN02FREV001/REV 4.0 19 REFERÊNCIAS BIBLIOGRÁFICAS IMASTER. Disponível em: <http://www.imaster.com.br>. Acesso em: 25.10.2010. JQUERY. Disponível em: <http://jquery.com/)>. Acesso em: 25.10.2010. PHP. Disponível em: <http://www.php.net>. Acesso em: 25.10.2010. WEC. Disponível em: <http://www.w3c.org>. Acesso em: 25.10.2010. WIKIPEDIA. Disponível em: <http://pt.wikipedia.org/wiki/AJAX_(programa%C3%A7%C3%A3o)>. Acesso em: 25.10.2010. WIKIPEDIA. Disponível em: <http://pt.wikipedia.org/wiki/Internet_rica)>. Acesso em: 25.10.2010. FIM DO MÓDULO III
Compartilhar