Cómo crear una aplicación de chat usando PHP y HTML en solo unos pocos pasos | |
En este artículo intentaré explicar de una manera más sencilla la parte de implementación de nuestra aplicación de chat (usando PHP) que había mostrado en la canal de Youtube. | |
Puede descargar el proyecto completo aquí Descargar este proyecto | |
Nuestra aplicación consta de 3 partes: | |
Paso 1 - | |
Comencemos con la base de datos, supongamos que el nombre de nuestra base de datos es chat. | |
Necesitamos cuatro mesas | |
Ver la estructura de las tablas en la siguiente figura | |
Supongamos que se ha instalado XAMPP, si no, descárguelo y vea cómo instalarlo. | |
Abra el navegador y escriba https://localhost/dashboard/ | |
Y luego haga clic en phpmyadmin, veremos nuestras tablas creadas en el chat de la base de datos | |
Para crear las tablas necesitas el siguiente script sql | |
Tabla de usuarios | |
CREATE TABLE `user` ( `iduser` int(11) NOT NULL, `nickname` varchar(30) NOT NULL, `email` varchar(50) NOT NULL, `password` text NOT NULL, `idimage` int(11) DEFAULT NULL, `state` int(11) NOT NULL DEFAULT 0, `insertdate` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `updatedate` timestamp NOT NULL DEFAULT current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ALTER TABLE `user` ADD PRIMARY KEY (`iduser`); ALTER TABLE `user` MODIFY `iduser` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=37; |
Tabla de imágenes | |
CREATE TABLE `images` ( `id` int(11) NOT NULL, `name` varchar(100) NOT NULL, `content` blob NOT NULL, `type` varchar(20) NOT NULL, `size` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ALTER TABLE `images` ADD PRIMARY KEY (`id`); ALTER TABLE `images` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=158; |
sendedmessage table | |
CREATE TABLE `sendedmessage` ( `idsender` int(11) NOT NULL, `idreceiver` int(11) NOT NULL, `message` varchar(500) NOT NULL, `message_read` int(11) NOT NULL DEFAULT 1, `sound` int(11) NOT NULL DEFAULT 1, `insertdate` timestamp NOT NULL DEFAULT current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
session table | |
CREATE TABLE `session` ( `iduser` int(11) NOT NULL, `ip` varchar(30) NOT NULL, `insertdate` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
Paso 2 - | |
Ahora pasemos a la parte PHP Backend | |
En todos los archivos de la aplicación utilicé la clase 'DBClass' declarada en el archivo db.dzo.class.php |
<?php class DBClass { private $conn;// The database connection variable public function __construct($con) { $this->conn =$con; } public function DBClass() { } // the methods which I will show later .... .... .... } ?> |
En esta clase he agrupado todos los métodos que necesito como inserción en la base de datos. | |
Primero para conectar al usuario con apodo y contraseña necesitamos el método ConnectUser | |
<?php function connectUser($nickname,$password){ $this->conn->query("SET NAMES UTF8"); $this->conn->query('SET CHARACTER SET utf8'); $query = "select iduser,password from user where nickname='".$nickname."'"; $result = $this->conn->query ( $query ); $iduser=0; if ($result){ if (mysqli_num_rows ( $result ) > 0) { $row = @mysqli_fetch_row ( $result ); $iduser=$rowΎ]; if (!password_verify($password, $rowΏ])) { return "Wrong password"; } else { $msgerr= $this->updSessionTable($iduser); if(!empty($msgerr)) { return $msgerr; } } } else { return "User not found !"; } } else { return mysqli_error(); } return "id".$iduser; } //get the user email from the user ID function GetUserFromId($iduser) // return the user email { $email=""; $query = 'select email from user where iduser='.$iduser; $result = $this->conn->query ( $query ); if ($result){ if (mysqli_num_rows ( $result ) > 0){ $row = @mysqli_fetch_row ( $result ); $email=$rowΎ]; } } return $email; } //delete the user session from the database function DeleteSessionTable($email)// When the user logout , we delete his session from the database { $query = "delete from session where iduser in "; $query.= "(select iduser from user where email='".$email."')"; $result = $this->conn->query ( $query ); if (! $result) { return mysqli_error (); } return ""; } //create a user session function UpdSessionTable($iduser) { $query = ""; $email=$this->GetUserFromId($iduser); $msgerr=$this->DeleteSessionTable($email); if(!empty($msgerr)) return $msgerr; $query = "INSERT INTO session (`iduser`,`ip`,`insertdate`) VALUES ($iduser,'".$this->getIp()."',now())"; $result = $this->conn->query ( $query ); if (! $result) { return mysqli_error (); } $_SESSION[$email]=$email; // Update the user state (online state) when connected. $this->UpdUserState($iduser,1); return ""; } ?> |
Para agregar el avatar, necesitamos este método AddAvatar para agregar la imagen en la base de datos |
<?php function AddAvatar($fileName, $fileSize, $fileType, $content) { $query = "INSERT INTO images (name, size, type, content) "; $query.= "VALUES ('$fileName', '$fileSize', '$fileType', '$content')"; $retval = $this->conn->query ( $query ); if (! $retval) { return mysqli_error (); } return ''; } ?> |
En cambio, el siguiente método elimina el avatar de la base de datos. | |
<?php function RemoveAvatar($id) { if ($id) { if($id==0) return; // don't remove the defualt picture $query = "DELETE FROM images WHERE id = $id"; $result = $this->conn->query ( $query ); if (! $result) { return mysqli_error (); } return "The avatar is deleted "; } return "Unexpected error"; } ?> |
Para ver el avatar, utilice esta función que devuelve el código html al cliente | |
Las clases css photoprofileonline, photoprofileaway están definidas en el archivo css, | |
el primero le permite mostrar el estado del usuario en línea y el segundo mostrar el estado del usuario fuera | |
desde el teclado |
<?php function ShowAvatar($id,$state,$count) { $html = ''; if($id==null) //When id is null the default avatar is shown. { $id=0; } $query = "SELECT * FROM images where id =" . $id; $result = $this->conn->query ( $query ); $class_state="photoprofileoffline"; $row = null; while ( $row = @mysqli_fetch_array ( $result ) ) { $img = $row ['content']; $type = $row ['type']; if($state==1) { $class_state="photoprofileonline"; } else{ if($state==0) { $class_state="photoprofileaway"; } } if($count==0) { $count=""; } $html ='<img class="'.$class_state.'" id="Photo" src="data:' . $type . ';base64,' $html.='base64_encode( $img ).'" style="widtht:100px; height:100px" ><div class="centered">'; $html.='<b><font size="5" color="red">'.$count.'</font></b></div>'; } return $html; } ?> |
El método ShowProfile con los dos parámetros le permite ver el perfil completo | |
El primer parámetro es la identificación de la imagen, el segundo es la identificación del usuario. | |
Este método devuelve el código html al cliente |
<?php function ShowProfile($id,$iduser) { $html = ""; if($id==null || empty($iduser)) //We take the default avatar { $id=0; } $query = "SELECT * FROM images where id =" . $id; $result = $this->conn->query ( $query ); $class_state="photoprofileoffline"; $row = null; while ( $row = @mysqli_fetch_array ( $result ) ) { $img = $row ['content']; $type = $row ['type']; if(empty($iduser)) { $html= '<br/><table style="width:100%;height:150px;" ><tr><'; $html.='td align="center">'; $html.= '<img class="photoprofileoffline" id="PhotoUser" src="data:' . $type; $html.=';base64,' . base64_encode ( $img ) . '" style="width:140px; height:140px" >'; $html.= '</td></tr></table>'; }else { $html = '<br/><table style="width:100%;height:150px;" '; $html.='cellspacing="0px" cellpadding="0px">'; $html.='<tr><td align="center">'; $html.= '<div id="profileonline"><img class="'.$class_state.'"'; $html.='id="PhotoExit" src="data:' . $type; $html.=';base64,' . base64_encode ( $img ) . '" style="width:100px; height:100px" ></div>'; $html.='</td></tr>'; $html.='<tr><td style="text-align:center;height:10px;" class="titleProfile widthbtnprof"><br/>'; $html.='ucfirst($this->GetNickNameFromId($iduser)).'</td></tr>'; $html.='<tr><td>'; $html.=' '; $html.='</td></tr>'; $html.='<tr><td>'; $html.='<button id="btnupdprofile" onclick='; $html.='"update_user(' .$iduser.'); return false;">'; $html.=' Profile</button>'; $html.='</td></tr>'; $html.='<tr><td>'; $html.='<button id="btnlogout" onclick="exitChat();return false;'; $html.='"> Logout</button>'; $html.='</table>'; } $html .= '<input type="hidden" id="idimage" value="'.$id.'">'; $html .= '<input type="hidden" id="sender" value="'.$iduser.'">'; $html .= '<input type="hidden" id="reciever" value="">'; } return $html; } ?> |
Para obtener o cambiar el estado del usuario necesitamos estos métodos | |
<?php function getState($iduser) { $query = "select state from user where iduser=".$iduser; $result = $this->conn->query ( $query ); $row = mysqli_fetch_row($result); return $rowΎ]; } function updUserState($iduser,$state) { $query = "update user set state=".$state." where iduser=".$iduser; $result = $this->conn->query ( $query ); } ?> |
Para agregar un nuevo usuario o actualizar un usuario existente, necesitamos estos métodos: | |
El primer método muestra el cuadro de diálogo a nivel de cliente que permite al usuario ingresar sus datos, | |
en lugar del segundo, agregue los datos del usuario en la base de datos. |
<?php function ShowUserDialog($id,$password) { $this->conn->query("SET NAMES UTF8"); $this->conn->query('SET CHARACTER SET utf8'); $found=0; $query = "select nickname, email,idimage from user where iduser =" . $id; $result = $this->conn->query ( $query ); $row = null; for($i=0;$i<10;$i++) { $row[$i] = ""; } if ($result) { if (mysqli_num_rows ( $result ) > 0) { $row = @mysqli_fetch_row ( $result ); } } $html = '<table style="width:100%;border-spacing:2px;padding:2px;">'; $html .= '<tr><td width="60%"><td align="right">'; $html .= '<img src="image/close16.jpg" style="cursor: pointer;" onclick="closedlguser();" />'; $html .= '</td></tr>'; $html .= '<tr><td width="50%">'; $html .= '<table style="width:100%;border-spacing:2px;padding:2px;"><tr>'; $html .= '<td class="tdlabel" >Email<font color="red"> *</font></td><td >'; $html .= '<input type="text" size="30" id="email" maxlength="50" value="'.$row Ώ].'"></td></tr>'; $html .= '<td class="tdlabel">Nickname<font color="red"> *</font></td><td >'; $html .= '<input type="text" size="30" id="nickname" maxlength="30" value="'.$rowΎ].'"></td></tr>'; $html .= '<td class="tdlabel">Password<font color="red"> *</font></td><td>'; $html .= '<input type="password" size="10" id="password" maxlength="10" value="'.$password.'"></td></tr>'; $html .= '</table>'; $html .= '</td><td style="width:50%;vertical-align:top;"> '; $html .= '<form method="post" id="formimage" name="formimage" enctype="multipart/form-data">'; $html .= '<table style="width:100%;border-spacing:1px;padding:1px;" class="box">'; $html .= '<tr>'; $html .= '<td>'; $html .= '<input type="hidden" name="paramimage">'; $html .= '<input type="hidden" name="MAX_FILE_SIZE" value="2000000">'; $html .= '<input type="file" id="userfileUser" style="display: none" '; $html .= 'onChange="HandlechangeUser();"/>'; $html .= '</td>'; $html .= '</tr>'; $html .= '<tr>'; $html .= '<td style="text-align:center;">'; $html .= '<a class="action-button" onclick="HandleBrowseClickUser();">Avatar</a>'; $html .= '</td>'; $html .= '<td style="text-align:center;">'; $html .= '<a class="action-button" onclick="transfererImage(' . $id . ');">Load</a>'; $html .= '</td>'; $html .= '<td style="text-align:center;">'; $html .= '<a class="action-button" onclick="elimphotoprofile(' . $id . ');">Delete</a></td>'; $html .= '</tr>'; $html .= '</table>'; $html .= '<table style="width:100%;border-spacing:5px;padding:5px;">'; $html .= '<tr>'; $html .= '<td style="text-align:center;">'; $html .= '<input type="text" id="filenameUser" readonly="true" style="display: none"/>'; $html .= '<div id="divimaprofile">'; $html .= $this->ShowAvatar($row ΐ],0,""); $html .= '</div>'; $html .= '</form>'; $html .= '</td></tr></table><br/>'; $html .= '<table style="width:100%;"><tr><td style="text-align:right;"><div id="err"></div>'; $html .= '</td></tr>'; $html .= '<tr><td style="text-align:right;"><button id="saveuserid" class="action-button" '; $html .= 'onclick="saveuser(' . $id .'); return false;">Save</button>'; $html .= '</td></tr></table>'; echo $html; } function AddUser($iduser,$nickname, $email,$password, $idimage) { $this->conn->query("SET NAMES UTF8"); $this->conn->query('SET CHARACTER SET utf8'); $query = ""; $hash=password_hash($password, PASSWORD_DEFAULT); $nickname=str_replace("'","''",$nickname); if ($iduser == 0) { $query = "INSERT INTO user ( `nickname`, `email`, `password`, `idimage`, `state`, `insertdate`) VALUES ('$nickname','$email','$hash',$idimage,1,now())"; } else { $query = "UPDATE user SET nickname='$nickname',password='$hash', idimage=$idimage, updatedate=now() where email='$email'"; } $result = $this->conn->query ( $query ); if (!$result) { return mysqli_error (); } return ""; } ?> |
Para enviar un mensaje de un usuario a otro, necesitamos el método enviar mensaje | |
Necesitamos también el método RefreshMessage que permite mostrar el mensaje a nivel de cliente |
<?php function SendMessage($iduser_from,$iduser_to,$message) { $query = "INSERT INTO `messages` (message,iduser_from,iduser_to,inserdate,state) VALUES "; $query.=('$message',$iduser_from,$iduser_to, now(),0)"; $result = $this->conn->query ( $query ); if (! $retval) { return mysqli_error (); } return $message; } function RefreshMessage($from,$to) { $html= '<table border="0" width="100%" height="90%">'; $sql="SELECT idsender,idreceiver ,message FROM sendedmessage where (idsender=$from and idreceiver=$to)"; $sql="or (idsender=$to and idreceiver=$from) order by insertdate asc"; $result = $this->conn->query ( $sql ); if ($result) { while($row = @mysqli_fetch_row ( $result )) { if($rowΎ]==$to) { $html .= '<tr><td style="text-align:right;" ><div class="containerChatFrom">'.$rowΐ].'</td></tr>'; } else { $html .= '<tr><td style="text-align:left;"><div class="containerChatTo">'.$rowΐ].'</td></tr>'; } } } $html .= '</table>'; return $html; } ?> |
Para ver todos los usuarios registrados, necesitamos el siguiente método: | |
Puede notar que también gestionamos el pitido en cada nuevo mensaje que llega. | |
el valor de la variable 'sonido' es 1 cuando se envía el mensaje, si el receptor abre el mensaje | |
el sonido se establece en 0. | |
Veremos como reproducir el sonido a nivel de cliente con Javascript |
<?php function ShowUsers($iduser) { $html = '<table border="0" width="80%" height="100%" cellspacing="2px" cellpadding="2px">'; $html.= '<tr><td><div style ="overflow:auto;">'; $query = "select idimage,iduser,nickname,state from user where iduser<>".$iduser; $result = $this->conn->query ( $query ); $i=1; $sound =0; $sql="select count(*) as sdcount from sendedmessage where idreceiver=$iduser and sound=1"; if($retval= $this->conn->query ( $sql )) { if($rowCountSound = @mysqli_fetch_array ( $retval )) { $sound=$rowCountSoundΎ]; } } while ( $row = @mysqli_fetch_array ( $result ) ) { $sql="select count(message) as mscount from sendedmessage where idsender=$rowΏ]"; $sql.="and idreceiver=$iduser and message_read=1"; $messageNotReadYet=""; if($retval= $this->conn->query ( $sql )) { if($rowCountMess = @mysqli_fetch_array ( $retval )) { $messageNotReadYet=$rowCountMessΎ]; } } $html .='<table style="width:100%;"><tr><td style="width:20%;text-align:center;cursor:pointer;">'; $html .='<div id="divimaprofile'.$i.'" class="containerCount" '; $html .= 'onclick="StartChat('.$iduser.','.$rowΏ].'); return false;"'; $html .= 'onmouseover="OverUser(\''.$rowΐ].'\','.$i.'); return false;" '; $html .= 'onmouseleave="LeaveUser(\''.$rowΐ].'\','.$i.');'; $html .= 'return false;">'; $html .= $this->ShowAvatar($row Ύ],$rowΐ],$messageNotReadYet); $html .= '</div></td></tr><tr><td style="text-align:center;" colspan="2"><div id="selectedUser'.$i.'"><span><b>' $html .= $rowΐ].'</b></span></div></td></tr></table>'; $i++; } if($sound>0) { $sound=1; } $html .= '<input type="hidden" id="sound_mess" value="'.$sound.'"/>'; $html .= '</div></td></tr>'; $html .= '</table>'; return $html; } ?> |
Para detener el sonido necesitamos el siguiente método |
<?php function StopSound($iduser) { $sql="update sendedmessage set sound=0 where idreceiver=$iduser"; $this->conn->query( $sql ); } ?> |
Necesitamos también los siguientes archivos php donde llamamos a todos los métodos definidos en nuestra clase DBClass | |
1- chatUser.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init();// Initialize the MySQL database connection if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) // Connect to the database chat { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con);// get the instance of DBClass $to = $_REQUEST['to']; // read the parameter 'to' from the request where to is the user ID $from= $_REQUEST['from']; // read the parameter 'from' from the request where from is the user ID $html=$dbconnect->RefreshChat($from,$to,"");// call the RefreshChat method echo $html; // Write the html code returned by the method ?> |
2- sendMessage.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $from = $_REQUEST['from']; $to= $_REQUEST['to']; $message= $_REQUEST['message']; $html=""; $query="INSERT INTO `sendedmessage`(`idsender`, `idreceiver`, `message`) VALUES ($from,$to,'$message')"; $con->query ( $query ); $html=$dbconnect->RefreshChat($from,$to,""); echo $html; ?> |
3- refreshChat.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $from= $_REQUEST['from']; $to = $_REQUEST['to']; $inputText = $_REQUEST['inputText']; $html=$dbconnect->RefreshChat($from,$to,$inputText); echo $html; ?> |
4- stopSound.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $iduser = $_REQUEST['iduser']; echo $dbconnect->StopSound($iduser); ?> |
5- updUser.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $nickname = $_REQUEST['nickname']; $email = $_REQUEST['email']; $password = $_REQUEST['password']; $idimage = $_REQUEST['idimage']; $iduser = $_REQUEST['iduser']; $msgerr=""; $msgerr=$dbconnect->CheckMailIfExist($email,$iduser); if(empty($msgerr)) { $msgerr=$dbconnect->CheckNicknameIfExist($nickname,$iduser); if(empty($msgerr)) { $msgerr=$dbconnect->AddUser($iduser,$nickname, $email,$password, $idimage); } } else { echo $msgerr; } if(!empty($msgerr)) { echo $msgerr; } else { echo 'OK'; } ?> |
6- addAvatar.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $iduser=""; $html =""; if(isset($_REQUEST['iduser'])) { $iduser=$_REQUEST['iduser']; } $fileName = ""; $tmpName = ""; $fileSize = ""; $fileType = ""; $colore='#D13921'; if(isset($_FILES['userfile'])){ $fileName = $_FILES['userfile']['name']; $tmpName = $_FILES['userfile']['tmp_name']; $fileSize = $_FILES['userfile']['size']; $fileType = $_FILES['userfile']['type']; } else { if(isset($_FILES['userfileUser'])){ $fileName = $_FILES['userfileUser']['name']; $tmpName = $_FILES['userfileUser']['tmp_name']; $fileSize = $_FILES['userfileUser']['size']; $fileType = $_FILES['userfileUser']['type']; }else $msgerr="Overflow"; } $msgerr=""; if($fileSize==0) $msgerr= "No Image"; elseif ($fileSize>0) { if($fileSize>6400000) { $msgerr= "File !!"; } else{ $fp = fopen($tmpName, 'r'); $content = fread($fp, filesize($tmpName)); $content = addslashes($content); fclose($fp); $fileName = addslashes($fileName); $msgerr.=$dbconnect->AddAvatar($fileName,$fileSize,$fileType,$content); if(empty($msgerr)) { $query = "select * from images order by id desc limit 1"; $result = $con->query( $query ); $row=@mysqli_fetch_array ( $result ); $classon="photoprofileoffline"; $img = $row ['content']; $type = $row ['type']; $html ='<img class="'.$classon.'" id="Photo" src="data:' . $type . ';base64,' . base64_encode ( $img ) . '; $html.=" style="width:100px; height:100px" >'; $html .='<input type="hidden" id="vidimage" value="'.$rowΎ].'"/>'; } else { $html = $msgerr; } } echo $html; } ?> |
7- getUser.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $idUser = $_REQUEST['iduser']; $password=""; if(isset($_COOKIE["password"]) && !empty($_COOKIE["password"])) { $password=$_COOKIE["password"]; } $dbconnect->ShowUserDialog($idUser, $password); ?> |
8- updStateUser.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $iduser = $_REQUEST['iduser']; $state = $_REQUEST['state']; $idimage = $_REQUEST['idimage']; if($dbconnect->getState($iduser)!=3) { $dbconnect->updUserState($iduser,$state); } $query="select state from user where iduser=$iduser"; $result = $con->query ( $query ); if ($result) { $row = @mysqli_fetch_row ( $result ); } $html = ""; if($idimage==null || empty($iduser)) $idimage=0; $query = "SELECT * FROM images where id =" . $idimage; $result = $con->query ( $query ); $class_state="photoprofileoffline"; if($state==1) { $class_state="photoprofileonline"; }else { if($state==0) { $class_state="photoprofileaway"; } } if ( $row = @mysqli_fetch_array ( $result ) ) { $img = $row ['content']; $type = $row ['type']; $html ='<img class="'.$class_state.'" id="Photo" src="data:' . $type . ';base64,' . base64_encode ( $img )'; $html.='" style="width:100px; height:100px" >'; } echo $html; ?> |
9- refreshUsers.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $from= $_REQUEST['from']; $html=$dbconnect->ShowUsers($from); echo $html; ?> |
10- connectTosite.php | |
<?php session_start(); require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $nickname = $_REQUEST['nickname']; $password = $_REQUEST['password']; $msgerr=$dbconnect->connectUser($nickname,$password); if(!empty($msgerr) && substr($msgerr,0,2)!="id") { echo $msgerr; } else { $iduser=intval(substr($msgerr,2)); setcookie('iduser', $iduser, time()+3600*24); setcookie('password', $password ,time()+3600*24); echo "CONNECTED"; } ?> |
11- logout.php | |
<?php require "db.dzo.class.php"; $con=mysqli_init(); if (!$con) { die("mysqli_init failed"); } if(!mysqli_real_connect($con,"127.0.0.1","root","","chat")) { die("Connect Error: " . mysqli_connect_error()); } $dbconnect = new DBClass($con); $iduser=""; if(isset($_COOKIE["iduser"])) $iduser=$_COOKIE["iduser"]; else { $iduser= $dbconnect->CheckUserLogged(); } $dbconnect->updUserState($iduser,3); $email = $dbconnect->getUserFromId($iduser); $dbconnect->deleteSessiontable($email); setcookie("iduser", "", time()-3600); ?> |
Ahora pasemos a la parte del cliente. | |
Usé AJAX, que es el sueño de un desarrollador, porque puedes: | |
.Leer datos de un servidor web: después de que se haya cargado la página | |
.Actualizar una página web sin recargar la página | |
.Enviar datos a un servidor web - en segundo plano | |
The javascript file chat.js | |
La función más importante es sendData, tiene como parámetros | |
data : de tipo FormData | |
acción: el archivo php que contiene la acción | |
encabezado: 1 para establecer el tipo de contenido del encabezado | |
divinnerHtml: el código html devuelto después de la ejecución de la acción (archivo php) | |
Ejemplo: | |
Este código javascript nos permite enviar un mensaje de remitente a destinatario, los datos a enviar son: | |
el ID de usuario del remitente, el ID de usuario del receptor y el mensaje | |
la acción es sendMessage.php que hemos visto antes, y el resultado (divinnerHtml) se devolverá en el div | |
tener el id 'usuarios'. | |
function sendMessageTo() { var from=document.getElementById("sender").value; var to=document.getElementById("reciever").value; document.getElementById("message").value.trim(); if(document.getElementById("message").value!="") { var data = new FormData(); data.append("from", from); data.append("to", to); data.append("message", document.getElementById("message").value); sendData(data,"sendMessage.php",0,"users"); } } |
function sendData(data,action,header,divinnerHtml) { var location = window.location; var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari, ... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE 8 and older xhr = new ActiveXObject("Microsoft.XMLHTTP"); } if (xhr) { xhr.open("POST", action, true); if(header==1) { xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;text/html; charset=utf-8"); } xhr.send(data); xhr.onreadystatechange = display_data; } else { alert('Sorry, your browser does not support this.;'); } function display_data() { if (xhr.readyState == 4) { if (xhr.status == 200) { endProgress(); if(divinnerHtml=="head"){ document.getElementById(divinnerHtml).innerHTML = document.getElementById(divinnerHtml).innerHTML+ xhr.responseText; return; } else { if(divinnerHtml=="disconnect") { window.location = "http://localhost/CHAT/"; } else { if(divinnerHtml!="sound") { document.getElementById(divinnerHtml).innerHTML = xhr.responseText; } } } if(action=="updUser.php") { var t=xhr.responseText.trim(); var j='OK'; if(t==j) { goToHome(); } else { document.getElementById(divinnerHtml).style.display="block"; } } else { if (divinnerHtml=="dlguser") // to create new user or update user data { document.getElementById(divinnerHtml).style.display="block"; } if(action=="sendMessage.php" || action=="chatUser.php" || action=="refreshChat.php") { var objDiv = document.getElementById("divChat"); objDiv.scrollTop = objDiv.scrollHeight; if(action=="sendMessage.php") { document.getElementById("message").focus();//set focus on input text message } } if(action=="refreshUsers.php") { var iduser=document.getElementById("sender").value; var elm=document.getElementById("sound_mess"); if(elm) { if(elm.value=="1") { var snd = new Audio("audio/notify.mp3"); //sound snd.play(); var data = new FormData(); data.append("iduser", iduser); sendData(data,"stopSound.php",0,"sound"); } } } } } } } return; } |
function OverUser(user,indice) //On Mouse Over the user avatar { document.getElementById("selectedUser"+indice).innerHTML ="<font color=\"blue\"><span><b>"+user+"</b></span></font>"; } function LeaveUser(user,indice) // On Mouse Leave user avatar { document.getElementById("selectedUser"+indice).innerHTML ="<font color=\"black\"><span><b>"+user+"</b></span></font>"; } |
//Reload the page function goToHome() { location.reload(); } function sendMessageToKeydown() //Send message with 'return' key { if(event.keyCode==13) { sendMessageTo(); } } function sendMessageTo() { var from=document.getElementById("sender").value; var to=document.getElementById("reciever").value; document.getElementById("message").value.trim(); if(document.getElementById("message").value!="") { var data = new FormData(); data.append("from", from); data.append("to", to); data.append("message", document.getElementById("message").value); sendData(data,"sendMessage.php",0,"users"); } } |
function StartChat(from,to) / Start the chat with other user { startProgress(); document.getElementById("reciever").value=to; var data = new FormData(); data.append("from", from); data.append("to", to); sendData(data,"chatUser.php",0,"users"); } function exitChat() // End chat { startProgress(); sendData(null,"logout.php",0,"disconnect"); } function New_User() // Create new user { startProgress(); var data = new FormData(); data.append("iduser", 0); sendData(data,"getUser.php",0,"dlguser"); } function transfererImage(iduser) // Upload the picture on server to store it in the database { startProgress(); var fichier= document.getElementById("userfileUser").filesΎ]; var formdata = new FormData(); formdata.append("iduser", iduser); formdata.append("userfile", fichier); sendData(formdata,"addAvatar.php",0,"divimaprofile"); } function closedlguser() { document.getElementById("dlguser").style.display="none"; } //-------------------------------------------------- function closediv(ediv){ document.getElementById(ediv).style.display="none"; } function elimphotoprofile(id){ var formdata = new FormData(); formdata.append("id", id); sendData(formdata,"delPhoto.php",0,"divimaprofile"); } function HandleBrowseClickUser() //To load user avatar { var fileinput = document.getElementById("userfileUser"); fileinput.click(); } function HandlechangeUserHandlechangeUser() { var fileinput = document.getElementById("userfileUser"); var textinput = document.getElementById("filenameUser"); textinput.value = fileinput.value; } function saveuser(id) // Save user data { if(document.getElementById("email").value=="") { document.getElementById("err").innerHTML='<font color="red">Email required</font>'; return; } if(document.getElementById("nickname").value=="") { document.getElementById("err").innerHTML='<font color="red">Nickname required</font>'; return; } if(document.getElementById("password").value=="") { document.getElementById("err").innerHTML='<font color="red">Password required</font>'; return; } startProgress(); var fdata=new FormData(); fdata.append("email",document.getElementById("email").value); fdata.append("nickname",document.getElementById("nickname").value); fdata.append("password",document.getElementById("password").value); if(!document.getElementById("vidimage")) { fdata.append("idimage",document.getElementById("idimage").value);// Avatar id } else { fdata.append("idimage",document.getElementById("vidimage").value); } fdata.append("iduser",id); sendData( fdata,"updUser.php",0,"err"); } //-------------------------------------- function update_user(iduser){ // Show the user dialog startProgress(); var data = new FormData(); data.append("iduser", iduser); sendData(data,"getUser.php",0,"dlguser"); } function login()// Connect { var formdata = new FormData(); formdata.append("nickname", document.getElementById("nicknameLogin").value); formdata.append("password", document.getElementById("passwordLogin").value); startProgress(); var xhr; if (window.XMLHttpRequest) { // Mozilla, Safari, ... xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE 8 and older xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.open("POST", "connectTosite.php", true); xhr.send(formdata); xhr.onreadystatechange = display_data; function display_data() { if (xhr.readyState == 4) { if (xhr.status == 200) { endProgress(); var t=xhr.responseText.trim(); var j="CONNECTED"; if(t==j) { location.reload(); return; } else { document.getElementById("errlogin").innerHTML=xhr.responseText; return; } } } return; } } function startProgress()// Show then Progress gif animated { document.body.style.cursor="progress"; document.getElementById("idprogress").style.display="block"; } function endProgress(){ // Hide the progress gif animated document.body.style.cursor="auto"; document.getElementById("idprogress").style.display="none"; document.body.scrollTop = 0; document.documentElement.scrollTop = 0; } |
chat.css file | |
html,body { padding: 5px; margin: 5px; font-family:sans-serif; font-size:14px; background-color: #FFFFFF; color: #000000; margin-top: 1px; margin-left:1px; height: 100%; overflow-y: scroll; } input[type="text"] { font-size:14px; } span { font-size: 14px; } .action-button { position: relative; padding: 3px 5px; margin: 0px 5px 5px 0px; border-radius: 5px; color: #000; width:100px; text-decoration: none; border: 1px solid #3498db; background-image: linear-gradient(to bottom, #fff,#fff); font-family: arial,verdana,helvetica,sans-serif; font-size:12px; cursor: pointer; } .email { background: #1C1C1C url('../image/email2.png') no-repeat 2px; } .nickname { background: #1C1C1C url('../image/user_red.png') no-repeat 2px; } .password { background: #1C1C1C url('../image/pass.png') no-repeat 2px; } .action-button:active { transform: translate(0px,5px); -webkit-transform: translate(0px,5px); border:none; background-image: linear-gradient(to bottom, #3498db, #3498db); } .action-button:hover { color:#fff; background-image: linear-gradient(to bottom, #3498db, #3498db); -webkit-box-shadow:3px 3px 2px #c0c0c0; box-shadow:2px 2px 2px #c0c0c0; } .hdiv { display: none; } .vdiv { display: block; } .img-rounded { border-radius: 6px; } .center { left: 20%; top: 20%; border-radius: 20px; background-color: #fff; border-left: 1px solid gray; border-right: 1px solid gray; border-top: 1px solid gray; border-bottom: 1px solid gray; border-color: #5D6961 #5D6961 #5D6961 #5D6961; padding:10px; font-size:100%; opacity: 1; filter: alpha(opacity=100); /* For IE8 and earlier */ overflow:auto; } .centerprogress{ position:absolute; left: 35%; top: 35%; width: 50px; height: 50px; z-index: 999; } .zindexdiv{ z-index:20; width: 20%; position: absolute; } .photoprofileaway{ -moz-box-shadow:5px 5px 2px #FC932A; -webkit-box-shadow:5px 5px 2px #FC932A; box-shadow:8px 8px 4px #FC932A; border-radius: 80px; } .photoprofileonline{ -moz-box-shadow:5px 5px 2px #0ABC16; -webkit-box-shadow:5px 5px 2px #0ABC16; box-shadow:8px 8px 4px #0ABC16; border-radius: 80px; } .photoprofileoffline{ -moz-box-shadow:5px 5px 2px #8D948D; -webkit-box-shadow:5px 5px 2px #8D948D; box-shadow:8px 8px 4px #8D948D; border-radius: 80px; } .divuser { left: 50%; top: 50%; height: 150px; width: 100px; z-index: 12; position: absolute; overflow-x:hidden; } .users{ top: 0%; left: 0%; height: 600px; width: 350px; z-index: 11; padding: 25px; overflow-x:hidden; overflow-y:auto; position: relative; border-radius: 20px; background-color: #fff; border-left: 1px solid gray; border-right: 1px solid gray; border-top: 1px solid gray; border-bottom: 1px solid gray; border-color: #5D6961 #5D6961 #5D6961 #5D6961; padding:10px; font-size:100%; opacity: 1; filter: alpha(opacity=100); /* For IE8 and earlier */ } .divChat{ height: 300px; width: 350px; overflow-x:hidden; overflow-y:auto; } .userChat{ top: 10%; left: 15%; height: 100px; width: 350px; z-index: 11; padding: 25px; overflow: auto; overflow-x:hidden; position: absolute; border-radius: 20px; background-color: #fff; border-left: 1px solid gray; border-right: 1px solid gray; border-top: 1px solid gray; border-bottom: 1px solid gray; border-color: #5D6961 #5D6961 #5D6961 #5D6961; padding:10px; font-size:100%; opacity: 1; filter: alpha(opacity=100); /* For IE8 and earlier */ overflow:auto; } .containerChatFrom { border: 2px solid #dedede; background-color: #f1f1f1; border-radius: 5px; padding: 10px; margin: 10px 0; display: inline-block; } .containerChatTo { border: 2px solid #dedede; background-color: #808080; border-radius: 5px; padding: 10px; margin: 10px 0; display: inline-block; } .chatmess { margin: auto; width: 60%; border: 3px solid #73AD21; padding: 10px; } .heightdiuserinfo{ left: 0%; top:0%; border-color: #fff #fff #fff #fff; padding:0px; font-size:100%; height: 250px; width: 150px; z-index: 11; padding: 10px; overflow: hidden; position: relative; } .heightdivuser{ height: 300px; width: 650px; z-index: 11; padding: 25px; overflow: hidden; position: absolute; } .heightdivuserlogin{ height: 270px; width: 400px; z-index: 11; padding: 25px; overflow: hidden; position: relative; } .messageErr{ z-index:999; color: #df0000; } #btnNewUser, #btnForgotPass, #btnupdprofile, #btnlogout { font-family: Verdana, sans-serif; float: left; background:none!important; border:none; padding:0!important; color:#3498db; font-size:14px; cursor: hand; cursor: pointer; text-decoration:none; } label, input, textarea { color: #000; float: left; font-family: Verdana, sans-serif; margin: 15px 0; } label { display: block; line-height: 10px; width: 150px; } input, textarea { background: #1C1C1C; border: 1px solid #323232; color: #fff; height: 30px; line-height: 20px; width: 300px; padding: 0 10px; } input { padding-left: 30px; textarea { background: #1C1C1C url('images/social_balloon.png') no-repeat 235px 95px; font-size: 12px; height: 200px; width: 320px; overflow: hidden; } input { padding-left: 30px; } /* The container */ .container { display: block; position: relative; padding-left: 35px; margin-bottom: 12px; cursor: pointer; font-size: 22px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } /* Hide the browser's default checkbox */ .container input { position: absolute; opacity: 0; cursor: pointer; height: 0; width: 0; } .containerCount { font-size: 22px; position: relative; text-align: center; color: red; } .centered { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } |