Descriere: Cum sa faci un chat fara refresh ( folosind PHP si Ajax)?
Download:
Autor: Anonim
Sursa (Link-ul oficial): Propria parere: Folositor.
Tutorialul:
Observăm o creştere şi o dezvoltare tot mai mare a proiectelor web încercând să ajungă toate pe noul “web 2.0″. Această dorinţă întâlneşte una nouă şi anume cea de a updata anumite porţiuni din pagină fără ca utilizatorul să fie nevoit să facă acest lucru.Un bun exemplu în acest caz este bine-cunoscutul Twitter. Acesta are posibilitatea de a adăuga ciripiturile fără a fi nevoie de un refresh al paginii. De asemenea multe din acţiuni sunt similare: căutarea, autentificarea etc etc. Toate aceste lucruri crează o viteză şi experienţă de navigare placută utilizatorului.
Astăzi noi vom încerca să reproducem o acţiune simplă asemănătoare cu cea de la Twitter, însă nu vom încerca să reproducem nici una dintre acestea.
Practic vom avea o mică bază de date şi un formular HTML în care vom simula discuţiile avute într-un chat. Acest chat va face cereri regulate la o bază de date încercând să extragă noile comentarii ce au apărut în chat. El va modifica un div şi va adăuga noile discuţii deasupra celor deja existente.
Este unul din cele mai bune exemple de aprofundare a acestui principiu dinamic al paginilor web.
Ce tehnologii web folosim?
Prima tehologie web de care vom avea nevoie este bătrânul HTML. Acesta ne va ajuta la crearea unei interfeţe suficient de intuitivă şi de simplă pentru a nu ridica probleme nici unui începător ce a studiat HTML-ul 2-3 zile. Vom avea nevoie de o bază de date ce va conţine un tabel pentru a stoca informaţiile ce le primim de la cei ce vor purta discuţiile în chat. Vom folosi o bază de date ce o găsim pe orice server decent şi anume o bază de date MySQL. Interogările la care vom supune baza de date sunt basice şi vor include selecţii, ştergeri, adăugări de “linii” în baza de date. Aceste interogări precum şi alte prelucrări le vom face în câteva fişiere PHP. Până aici, practic am prezentat doar tehnologiile ce sunt clasice într-un website obişnuit. Pentru a prelua şi a reîncărca o anumită secţiune cu conţinut nou provenit din baza de date, va trebui să introducem o tehnologie nouă ce are la baza JavaScript: Ajax. Această tehnologie va face cereri regulate la anumite fişiere PHP şi va edita conţinutul anumitor taguri HTML, actualizând conţinutul acestora.
Rezultat
Am pregătit două imagini făcute în paralel, una din Mozilla Firefox iar cealaltă din Chrome pentru a vedea care va fi rezultatul la care se va ajunge în urma acestui articol.


Cod: Selectaţi tot
<html>
<head>
<title>Chat Box - Tutorial in care invatam cum sa aplicam Ajax si PHP pentru o pagina dinamica </title>
</head>
<body text="#66FF33" OnLoad="trimiteCMD('arata');">
<table align="center" width="50%" border="1" cellspacing="0" cellpadding="0">
<tr>
<td>
<div id="msg"> </div>
</td>
</tr>
<tr>
<td align="center">
<form name="chatbox" method="post" onSubmit="return false">
<textarea id="msgtext" name="mesaj" cols="50" rows="3"
onFocus="verif_msg(this.value);" onBlur="clr_msg(this.value);">
Mesajul tau aici.</ textarea><br><br>
<button id="send" onClick="trimiteCMD('trimite',
document.getElementById('msgtext').value);">Trimite </button>
</form>
</td>
</tr>
</table>
</body>
</html> Acest tabel trebuie pus într-o bază de date MySQL de care vom avea nevoie la stocarea tuturor mesajelor primite de la cei care chătuiesc.
Cod: Selectaţi tot
CREATE TABLE `mesaje` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`nume` CHAR( 255 ) NOT NULL ,
`mesaj` TEXT NOT NULL ,
`timp` INT NOT NULL
) ENGINE = MYISAM ; Fişierul config.php
În acest fişier vor trebui făcute singurele modificări pentru a putea lucra pe serverul dumneavoastră. Trebuie să configuraţi accesul la baza de date MySQL creată anterior. De asemenea au loc şi deschiderea de sesiune precum şi crearea unei variabile ce ne asigură că suntem unde trebuie!
Cod: Selectaţi tot
session_start();
if(!defined('INTERN')) {
define('INTERN',TRUE);
mysql_connect('server','user','parola') or die('Nu m-am putut conecta la serverul MySQL.');
mysql_select_db('baza de date') or die('Nu m-am putut conecta la baza de date MySQL.');
}
?> Acest fişier va adăuga un mesaj nou $_GET['mesaj'] provenind de la $_GET['user'] şi va returna ultimile mesaje noi din baza de date.
Cod: Selectaţi tot
<?php
include('config.php');
if(!defined('INTERN')) die();
if(isset($_GET['CMD']) && $_GET['CMD'] == 'trimite' && isset($_GET['nume'],$_GET['mesaj'])) {
header("Expires: Mon, 26 Jul 2999 05:00:00 GMT" );
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" );
header("Cache-Control: no-cache, must-revalidate" );
header("Pragma: no-cache" );
header("Content-Type: text/xml; charset=utf-8");
$user = htmlentities($_GET['nume'],ENT_QUOTES);
$mesaj = htmlentities($_GET['mesaj'],ENT_QUOTES);
$query = mysql_query('INSERT INTO `mesaje` (`nume`,`mesaj`,`timp`) VALUES
("'.$user.'","'.$mesaj.'","'.time().'")');
$result = ($query) ? '1' : '0';
?>
<root>
<cmd><?php echo $_GET['CMD'];?></cmd>
<status><?php echo $result; ?></status>
<?php include('ultimile.php'); ?>
</root>
<?php
}
?> Acesta returnează ultimile mesaje ale cititorului curent.
Cod: Selectaţi tot
<?php
include('config.php');
if(isset($_GET['CMD']) && $_GET['CMD'] == 'arata') {
header("Expires: Mon, 26 Jul 2999 05:00:00 GMT" );
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" );
header("Cache-Control: no-cache, must-revalidate" );
header("Pragma: no-cache" );
header("Content-Type: text/xml; charset=utf-8");
?>
<root>
<cmd> <?php echo $_GET['CMD'];?> </cmd>
<status>1 </status>
<?php include('ultimile.php'); ?>
</root>
<?php
}
?>
Fişierul ultimile.php este de fapt cel care stabileşte care mesaje să le afişeze. Dacă e prima cerere va returna ultimile 10 mesaje, în caz contrar va afişa doar ce a apărut nou de la ultima cerere. Acest ultim moment la care s-a făcut verificarea este stocat într-o variabilă globală de tip SESSION.
Cod: Selectaţi tot
<?php
if(!defined('INTERN')) die();
$time = time();
$time = isset($_SESSION['lastcheck']) && is_numeric($_SESSION['lastcheck']) ?
$_SESSION['lastcheck'] : 0;
$_SESSION['lastcheck'] = time();
if($time == 0) {
$query = "SELECT * FROM `mesaje` ORDER BY `timp` DESC LIMIT 0,10";
}
else {
$query = "SELECT * FROM `mesaje` WHERE timp >=".$time." ORDER BY `timp` DESC";
}
$int = @mysql_query($query);
$result = ($query) ? '1' : '0';
?>
<statusMesaje><?php echo $result; ?></statusMesaje>
<mesaje>
<?php
while($row = @mysql_fetch_array($int)) {
?>
<mesaj id="<?php echo $row['id']; ?>">
<nume><?php echo $row['nume']; ?></nume>
<msg><?php echo $row['mesaj']; ?></msg>
<timp><?php echo gmdate('D, d M Y H:i:s',$row['timp']); ?></timp>
</mesaj>
<?php
}
?>
</mesaje>
Cod: Selectaţi tot
//verifica daca avem vreun mesaj
function verif_msg(data) {
if(data=='Mesajul tau aici.') {
document.getElementById('msgtext').value='';
}
}
//curata mesajul
function clr_msg(data) {
if(data == '') {
document.getElementById('msgtext').value='Mesajul tau aici.';
}
}
//cream un obiect Http(acesta ne va ajuta sa lucram cu cereri Ajax)
//el incearca sa creeze obiectul pentru diverse versiuni de Browser
function creazaObiectHttp() {
if (window.XMLHttpRequest) return new XMLHttpRequest();
else if(window.ActiveXObject) return new ActiveXObject("Microsoft.XMLHTTP");
else {
document.getElementById('msg').innerHTML='Status: Nu am putut crea obiectul XML Http.' +
'Va rugam frumos schimbati browserul.';
}
}
var mTimer; //timerul ce face regulat cereri de noi mesaje
var receiveReq = creazaObiectHttp(); //cream obiectul
var randomUser = Math.floor((Math.random() * (2000-1000+1))+1000); //numele utilizatorului
//functia principala ce trimite mesajele catre diverse fisiere php
function trimiteCMD(cmd, data) {
if(cmd=='trimite' && data=='Mesajul tau aici.') {
alert('Te rog scrie un mesaj!')
}
else {
//daca nu este trimis nici un pachet acum si nu este nici unul in decurs
if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
var file,param;
if(cmd=='trimite') {
file = 'adauga.php'; //fisierul ce trebuie prelucrat + parametri
param = 'CMD=trimite&nume=user' + randomUser + '&mesaj=' + data;
clearTimeout(mTimer);//inchidem toate cererile existente
document.getElementById('msgtext').value='Mesajul tau aici.';
}
else if(cmd=='arata') {
file = 'last.php';
param = 'CMD=arata';
clearTimeout(mTimer); //deschidem o noua cerere peste 5 secunde sa vedem daca mai exista mesaje noi
mTimer = setTimeout("trimiteCMD('arata', '');",5000);
}
receiveReq.open("POST", file, true); //facem cererea
receiveReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');//setam headere
receiveReq.onreadystatechange = handleCMD;//functia ce va procesa cererile
receiveReq.send(param); //trimitem parametrii
}
}
}
//functie ce returneaza true daca pagina curenta a fost descarcata corect si complet
function check_state() {
if (receiveReq.readyState == 4)
if (receiveReq.status == 200)
return "True";
}
//procesam mesajele primite de la fisierele PHP
function handleCMD() {
var resultState = check_state();
if (resultState == "True") {
var chat_div = document.getElementById('msgtext');
xmldoc = receiveReq.responseXML;
var cmd = xmldoc.getElementsByTagName('cmd');
var status = xmldoc.getElementsByTagName('status');
if(cmd[0].firstChild.nodeValue == 'trimite') {
//daca s-a adaugat mesajul nou afisam asta utilizatorului
if(status[0].firstChild.nodeValue == '1') {
document.getElementById('err').innerHTML = 'Mesajul a fost trimis.';
}
else {
//in caz contrar afisam mesajul corespunzator
document.getElementById('err').innerHTML = 'Nu am putut trimite mesajul.';
}
//repornim cererile regulate o data la 5 secunde
mTimer = setTimeout("trimiteCMD('arata', '');",5000);
setTimeout('document.getElementById("err").innerHTML = "";',3000);
}
else if(cmd[0].firstChild.nodeValue == 'arata') {
//nimic
}
var status = xmldoc.getElementsByTagName('statusMesaje');
//daca avem mesajele trimise ok le procesam si le afisam utilizatorului
if(status[0].firstChild.nodeValue == '1') {
var msg = xmldoc.getElementsByTagName('mesaje');
var msgs_nodes = msg[0].getElementsByTagName('mesaj');
for(i = 0; i < msgs_nodes.length; i++) { //mesajul i
var userNode = msgs_nodes[i].getElementsByTagName('nume');
var bodyNode = msgs_nodes[i].getElementsByTagName('msg');
var timeNode = msgs_nodes[i].getElementsByTagName('timp');
var add = '<small>[ ' + timeNode[0].firstChild.nodeValue + ' ]</small>';
add += ' <strong>' + userNode[0].firstChild.nodeValue + '</strong> ';
add += ' ' + bodyNode[0].firstChild.nodeValue + '';
//il adaugam inaintea celor deja existente
document.getElementById('msg').innerHTML = add + document.getElementById('msg').innerHTML;
add = '';
}
}
else {//in caz contrar afisam o eroare
document.getElementById('err').innerHTML = 'Nu am putut primi noile mesaje.';
setTimeout('document.getElementById("err").innerHTML = "";',3000);
}
}
} Am creat o arhivă în care am unit toate aceste fişiere, pentru a face un sistem complet funcţionabil. Există şi un fişier sql.sql care conţine crearea bazei de date MySQL în cazul în care nu aveţi răbdare să o luaţi de aici. Descărcaţi arhiva, configuraţi fişierul config.php şi adăugaţi tabelul în baza de date şi după aceea puteţi testa. Fişierele nu sunt comentate, singurele comentarii fiind puse aici, aşa că veţi fi nevoiţi să nu săriţi peste pasul de a analiza codul în cazul în care doriţi să învăţaţi ce am făcut.
Pe scurt am interceptat pachetele sub forma de mesaje XML de la serverul PHP ce le-a generat cu ajutorul fişierelor ultimile.php şi adauga.php respectiv last.php. Am tratat obiectul ca unul HTML şi am extras din el pe rând noile mesaje, dacă acestea erau. Codul pare mare datorită faptului că am încercat să tratez şi majoritatea erorilor de bază, sperând că aşa nu veţi avea probleme.
Concluzii
Deşi, acest articol nu se referă neapărat la cum se lucrează cu Ajax şi PHP, acest tutorial este unul din cele mai bune exemple ce pot fi făcute de un începător. Nu trebuie să te sperii de marele cod, este doar o impresie, în browser acesta pare mai complex decât este. Dacă vei dori să înţelegi acest articol, îţi sugerez să-l descarci pe calculator şi să stai cu browserul lângă tine pentru a citi explicaţiile.
De asemenea, în acest “mic proiect”, am folosit doar cereri bazate pe POST, şi le-am omis intenţionat din discuţie pe celelalte. Dacă doriţi câteva exemple şi folosind cereri Ajax dar bazate pe argumente GET lăsaţi un comentariu şi voi încerca să revin cu explicaţiile şi exemplele necesare.
