Atualmente quase todas aplicações web utilizam requisições AJAX em suas aplicações, pois ela nos permite fazer transações de dados sem a necessidade de reenviar a página, ou seja, mantendo o estado atual da página sem a necessidade de qualquer alteração.
Recursos de auto complete, validação em tempo real com a base de dados, auto save e outros recursos são muito utilizados em aplicações web.
Para este artigo, será explicado como fazer as requisições, tanto para enviar dados par ao servidor quanto para receber uma string JSON.
Neste artigo não será abordado a parte teórica sobre o AJAX, como sua origem, significado entre outros, mas caso queria saber, confira estas e outras informações no seguinte endereço https://pt.wikipedia.org/wiki/AJAX_(programa%C3%A7%C3%A3o).
Nosso projeto está organizado da forma como mostra a imagem a seguir.
Vamos entender qual a responsabilidade destes diretórios, confira a explicação abaixo.
Action: Diretório no qual contém todos os arquivos que será requisitado pelo AJAX.
Controller: Controladora do projeto, ela é chamada pela Action e requisita as informações do diretório DAL, em especifico os arquivos DAO.
DAL: Contém os arquivos que fazem toda interação com o banco de dados.
Model: Contém todos os modelos do nosso exemplo, os arquivos armazenam a estrutura dos objetos.
Util: Arquivos extra, como arquivo de configurações, funções de validações entre outros.
Js: Contém os arquivos de Javascript.
Pois bem, agora já sabemos a responsabilidade dos diretórios. Agora será explicado o que cada arquivo faz, sendo que Javascript contendo o Jquery/AJAX está nos arquivos index.php e consulta.php, que serão os últimos a serem explicados, até por que precisamos entender o que acontece no servidor.
/Action/UsuarioAC.php
<?php
$req = filter_input(INPUT_GET, "req"); //Obtemos o valor de REQ que é passado através da URL
if ($req) {
require_once("../Controller/UsuarioController.php");
$usuarioController = new UsuarioController();
if ($req == "1") {
//Cadastrar
require_once("../Model/Usuario.php");
$usuario = new Usuario();
$usuario->setNome(filter_input(INPUT_POST, "txtNome"));
$usuario->setEmail(filter_input(INPUT_POST, "txtEmail"));
$usuario->setTelefone(filter_input(INPUT_POST, "txtTelefone"));
echo $usuarioController->Cadastrar($usuario);
}
if ($req == "2") {
//Retornar todos
echo $usuarioController->RetornarTodos();
}
}
Este arquivo recebe por Query String o valor req, que serve para indicar que tipo de requisição estamos fazendo e desta forma executar e chamar os respectivos métodos. Alguns usuários criam um arquivo para cada requisição, mas para este exemplo foi mantido tudo em um único arquivo.
Neste caso se o valor for 1, então estamos querendo cadastrar, desta forma instanciamos o modelo Usuario e passamos seus respectivos valores para a controladora que nos retorna uma informação, esta informação é exibida no arquivo de Action, e o AJAX retorna para a interface este resultado.
/Controller/UsuarioController.php
<?php
require_once("../DAL/UsuarioDAO.php");
class UsuarioController {
private $usuarioDAO;
public function __construct() {
$this->usuarioDAO = new UsuarioDAO();
}
function Cadastrar(Usuario $usuario) {
if ($usuario->getNome() != "" && $usuario->getEmail() != "" && $usuario->getTelefone() != "") {
return $this->usuarioDAO->Cadastrar($usuario);
} else {
return "invalido";
}
}
public function RetornarTodos() {
return $this->usuarioDAO->RetornarTodos();
}
}
?>
Este é o arquivo responsável por ligar a interface com a DAL sem fazer uma requisição Interface X DAL. A controladora tem por responsabilidade armazenar a regra de negócio do sistema e se tudo for válido, então faz a requisição na DAL para retornar na interface.
Neste caso temos apenas dois métodos, um para cadastro que valida se as informações que está recendo não é vazio e outro para retornar todos os usuários.
/DAL/UsuarioDAO.php
<?php
require_once("../Util/ClassSerialization.php");
require_once("../Model/Usuario.php");
class UsuarioDAO {
private $serialize;
public function __construct() {
$this->serialize = new ClassSerialization();
}
public function Cadastrar(Usuario $usuario) {
try {
return "Cadastrado. Nome: {$usuario->getNome()} E-mail: {$usuario->getEmail()} Telefone: {$usuario->getTelefone()}";
} catch (Exception $ex) {
return $ex->getMessage();
}
}
public function RetornarTodos() {
sleep(1); //Pausa proposital para explicação do beforeSend e complete do AJAX.
try {
$listaUsuario = [];
for ($i = 0; $i < 10; $i++) {
$usuario = new Usuario();
$usuario->setNome("Nome: {$i}");
$usuario->setEmail("mail@dominio.com");
$usuario->setTelefone("(18) 998{$i}");
$listaUsuario[] = $usuario;
}
return $this->serialize->serialize($listaUsuario);
} catch (Exception $ex) {
return $ex->getMessage();
}
}
}
DAL nada mais é do que a abreviação de Data Access Layer, ou seja, um diretório que irá armazenas as DAO, que é abreviação de Data Access Object. Os arquivos em PHP têm o Sufixo DAO, por representar um objeto.
Pois bem, este arquivo DAO tem por responsabilidade se comunicar com uma base de dados, seja arquivos XML, TXT ou até mesmo bancos de dados, tais como MySQL, SQLServer entre outros.
Para este exemplo não foi realizado nenhuma conexão com banco de dados, o método de cadastro apenas retorna os valores que chegou até ele de forma organizada, neste ponto você pode implementar seu método de Insert, Update ou Delete com o banco.
O método de retorno é um pouco sofisticado, pois criamos uma lista de objetos, na qual foi populado com informações aleatórias e fictícias. Por fim, foi utilizado uma classe que obtém um array de objetos e converte para uma string JSON, esta classe está disponível para Download em https://github.com/victortassinari/PhpClassSerialization.
/Model/Usuario.php
<?php
class Usuario {
private $nome;
private $email;
private $telefone;
function getNome() {
return $this->nome;
}
function getEmail() {
return $this->email;
}
function getTelefone() {
return $this->telefone;
}
function setNome($nome) {
$this->nome = $nome;
}
function setEmail($email) {
$this->email = $email;
}
function setTelefone($telefone) {
$this->telefone = $telefone;
}
}
O arquivo de modelo Usuario armazena e retorna as informações de um determinado usuário, de acordo com a sua estrutura, normalmente de acordo com o banco dados.
/Util/ClassSeralization.php
Este arquivo contém o método Serialize(), que recebe por parâmetro um array de objeto e os converte para uma string JSON.
/js/jquery-3.0.0.min.js
Para a utilização das requisições com AJAX, será utilizado o Jquery, ele contém e implementa de forma fácil as sintaxes de transação.
/index.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Requisições Ajax com PHP</title>
<style>
*{
margin:0 auto;
padding: 0;
font-family: "Segoe UI";
}
body{
background-color: #EEE;
}
h1{
font-weight: 300;
text-align: center;
}
ul{
list-style: none;
}
.centro{
max-width: 600px;
width:100%;
background-color: #FFF;
border:2px solid #CCC;
box-shadow: 0 0 5px #000;
}
.texto{
font-weight: bold;
}
.break{
margin-bottom:10px;
}
#dvForm{
padding:10px;
}
input[type=text]{
padding: 5px;
width:100%;
max-width:550px;
outline-color: pink;
}
input[type=button]{
padding: 5px;
outline: none;
}
</style>
</head>
<body>
<div id="dvCentro" class="centro">
<h1>Requisições com Ajax - Cadastro</h1>
<br />
<hr />
<div id="dvForm">
<ul>
<li class="texto">Nome: </li>
<li class="break"><input type="text" placeholder="Gunnar Correa" id="txtNome" /></li>
<li class="texto">E-mail:</li>
<li class="break"><input type="text" placeholder="gunnar@site.com" id="txtEmail" /></li>
<li class="texto">Telefone:</li>
<li class="break"><input type="text" placeholder="(18) 99800-0000" id="txtTelefone" /></li>
<li class="texto" id="resultado"></li>
<li class="break"><input type="button" id="btnCadastrar" value="Cadastrar" /></li>
</ul>
</div>
</div>
<script src="js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
$("#btnCadastrar").click(function () {
//Abaixo é montado um obejto com o mesmo nome do campo, pois no Action programamos para reeber estes nomes;
//O nome do formulário do HTML não interfere no nome dado aos itens do Objeto, porém tando na Action quando no Objeto devem ter os mesmos nomes.
//Documentação: http://api.jquery.com/jquery.ajax/
var dados = {
txtNome: $("#txtNome").val(),
txtEmail: $("#txtEmail").val(),
txtTelefone: $("#txtTelefone").val()
};
$.ajax({
url: "Action/UsuarioAC.php?req=1",
type: "post",
dataType: "html",
data: dados,
success: function (result) {
$("#resultado").html(result);
},
error: function (result) {
console.log(result);
}
});
});
});
</script>
</body>
</html>
Finalmente chagamos no ponto do nosso artigo, note que este arquivo contém um formulário HTML sem a utilização da tag <form>, porém cada elemento input contém um ID correspondendo a sua responsabilidade.
É necessário que importe para o HTML o arquivo do Jquery, acho que isto é obvio.
Dentro da instrução <script> temos a sintaxe $(document).ready(function () {});, ela é chamada quando toda a página HTML for montada, pois não faz sentido tentar acessar uma informação de um elemento sendo que ele não foi montado. É dentro dele que vamos fazer as requisições.
A instrução $("#btnCadastrar").click(function () {}); é chamada quando o elemento que contém o id btnCadastrar foi clicado. Dentro dele que será enviado as informações para a UsuarioAC.php.
A instrução $.ajax({}); é a responsável por fazer as requisições com um determinado endereço, passando ou revendo informações. Esta instrução implementa um recurso de chave valor, que está explicado abaixo.
url: Devemos informar o endereço de onde será feita a requisição, para este exemplo foi setado Action/UsuarioAC.php?req=1, note que o valor de req é 1, pois dentro da Action projetamos para cadastrar um usuário quando o valor for 1.
type: tipo da requisição, neste caso o tipo é POST, mas você pode usar o GET ou PUT por exemplo.
dataType: está é uma chave muito importante, nela definíamos qual será o tipo de valor retornado, podemos usar html, xml, json ou um script. Neste exemplo usamos html, mas para a requisição foi utilizado json.
data: recebe um objeto que será enviado para o servidor, antes da instrução do ajax, foi montado um objeto literal, que se chama dados e contém as chaves e valores, perceba que o valor da chave é o mesmo valor que requisitamos no UsuarioAC.php. Para montar este objeto literal, foi utilizado as chaves com o mesmo nome dos campos html, porém isto é opcional, porém onde você for fazer a requisição destes valores terá que ter o mesmo nome das chaves do objeto literal.
success: se a requisição foi realizada sem nenhum erro, então ela chama uma função, na qual pode ser implementado três valores por parâmetro, Neste exemplo foi implementado apenas um, que retorna a mensagem do arquivo UsuarioAC.php. $("#resultado").html(result); exibe no elemento resultado o valor retornado.
error: se houver algum erro na requisição, está chave chama uma função que podemos passar também três valores por parâmetro, mas neste exemplo foi utilizado apenas o primeiro, que retorna a mensagem do erro. Se houver algum erro será exibido no console do navegador.
/consulta.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Requisições Ajax com PHP</title>
<style>
*{
margin:0 auto;
padding: 0;
font-family: "Segoe UI";
}
body{
background-color: #EEE;
}
h1{
font-weight: 300;
text-align: center;
}
ul{
list-style: none;
}
.centro{
max-width: 600px;
width:100%;
background-color: #FFF;
border:2px solid #CCC;
box-shadow: 0 0 5px #000;
}
.texto{
font-weight: bold;
}
.break{
margin-bottom:10px;
}
#dvForm{
padding:10px;
}
table{
width:100%;
}
table tbody tr:nth-child(even){
background-color:#ADD8E6;
}
</style>
</head>
<body>
<div id="dvCentro" class="centro">
<h1>Requisições com Ajax - Consulta</h1>
<br />
<hr />
<!--http://satellasoft.com/?materia=zebrar-tabela-usando-css-->
<p id="load"></p>
<table>
<thead>
<tr>
<th>Nome</th>
<th>E-mail</th>
<th>Telefone</th>
</tr>
</thead>
<tbody id="tbody"></tbody>
</table>
</div>
<script src="js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
//Documentação: http://api.jquery.com/jquery.ajax/
//https://api.jquery.com/Ajax_Events/
$.ajax({
url: "Action/UsuarioAC.php?req=2",
dataType: "json",
beforeSend: function () {
//beforeSend é executado antes da chamada da requisição, pode ser usada para mostrar uma barra de carregameto
$("#load").html("Carregando");
},
complete: function () {
//complete é executado quando a chamada é finalizada e seus dados retornados, pode ser usada para ocultar uma barra de carregameto
$("#load").html("");
},
success: function (result) {
//Se não houve nenhum erro na requisição, então esta função é executada.
//https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
//var data = JSON.parse(result);//Como é retornado uma string JSON, convertemos ela para um objeto
var tbody = document.getElementById("tbody");//Armazenamos o elemento a variável tbody
tbody.innerHTML = ""; //Limpamos todo o conteúdo do elemento tbody
for (i = 0; i < Object.keys(result).length; i++) {
var tr = document.createElement("tr");//Criamos o elemento TR
var tdNome = document.createElement("td"); //Criamos o elemento TD para armazenar o nome
tdNome.innerHTML = result[i].Nome; //Para o valor da coluna, será o atribuido o valor nome da posiçã i no array de objetos
tr.appendChild(tdNome); //Inserimos o elemento TD dentro do elemento TR
var tdEmail = document.createElement("td"); //Criamos o elemento TD para armazenar o e-mail
tdEmail.innerHTML = result[i].Email;
tr.appendChild(tdEmail); //Inserimos o elemento TD dentro do elemento TR
var tdTelefone = document.createElement("td"); //Criamos o elemento TD para armazenar o telefone
tdTelefone.innerHTML = result[i].Telefone;
tr.appendChild(tdTelefone); //Inserimos o elemento TD dentro do elemento TR
tbody.appendChild(tr);
}
},
error: function (result) {
//Se houve erro na requisição, então esta função é executada.
console.log(result);
}
});
});
</script>
</body>
</html>
Este arquivo está bem mais simples do que você pensa, ele contém uma tabela com um elemento tbody cujo id é o mesmo nome do elemento. Com os dados retornado do servidor, criamos os elementos HTML com Javascript e adicionamos ao elemento tbody, caso não saiba criar elementos com Javascript, leia o artigo http://satellasoft.com/?materia=criando-elementos-com-javascript e em seguida retorne a este post.
Para o $.ajax({}), a explicação é a mesma para o cadastro, a diferença que aqui na url passamos o valor de req para 2 e no dataType ao invés de retornar um html, é retornado um JSON, porém o Jquery já converte este JSON para um objeto sem a necessidade de fazermos isto manualmente.
Para montar a tabela, foi feito um for com os dados atuais da lista de objeto. Para saber quantidade de itens de um objeto, basta utilizar Object.keys(result).length.
Foi implementado duas novas chaves, que não foram utilizadas no cadastro, mas que poderiam ser implementadas, são elas apresentadas abaixo.
beforeSend: é executado antes de fazer a requisição.
complete: ocorre quando a requisição é finalizada.
Você pode conferir toda documentação sobre o Ajax com Jquery através do seguinte endereço http://api.jquery.com/jquery.ajax.
Caso houverem dúvidas, deixe nos comentários, até a próxima!