W tym wpisie przy pomocy PHP, Javascript/jQuery oraz AJAX pokażę Ci jak zrobić chat, na którym użytkownicy będą mogli wymieniać się wiadomościami. Zaczynajmy 🙂

Zacznijmy od napisania prostej struktury HTML w pliku index.php:

<!doctype html>
<html>
  <head>
  <meta charset="utf-8">
  <title>Chat</title>
  <link rel="stylesheet" type="text/css" href="reset.css" media="screen">
  <style type="text/css">

  </style>
  </head>
<body>

<div class="chatContainer">
   <div class="chatHeader">
      <h3>Witaj</h3>
   </div>

   <div class="chatMessages"></div>

   <div class="chatBottom">
      <form action="#" onSubmit='return false;' id="chatForm">
         <input type="hidden" id="name" value=""/>
         <input type="text" name="text" id="text" value="" placeholder="Wpisz wiadomość" />
         <input type="submit" name="submit" value="Wyślij" />
      </form>
   </div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
   $(document).ready(function(){

   });
</script>
</body>
</html>

W sekcji head podłączyłem arkusz stylów o nazwie reset.css. Resetuje on domyślne style narzucane przez przeglądarkę. Przykładowy reset stylów możesz pobrać tutaj, nie jest on jednak konieczny do działania chatu.

Wewnątrz body znajduje się div z klasą chatContainer. Jest to główny kontener, który obejmuje cały chat. Wewnątrz niego znajdują się trzy divy o klasach:

  • chatHeader – górna część chatu, która zawiera powitanie użytkownika (w dalszej części dodamy tam jeszcze nick)
  • chatMessages – kontener, do którego będą ładowane wiadomości
  • chatBottom – dolna część chatu, w której znajduje się formularz wysyłania wiadomości

Warto zwrócić uwagę na formularz, który posiada atrybut onSubmit ustawiony na return false. Dzięki temu żądanie nie zostanie wysłane a strona nie zostanie odświeżona. Żądanie wyślemy przy pomocy AJAX w jQuery.

Poniżej zostaje podpięta biblioteka jQuery. Poniżej znajdują się znaczniki <script>, wewnątrz których umieścimy cały kod JS.

Dodajmy teraz kilka reguł CSS wewnątrz znaczników <style> w sekcji head:

body {
		   font-family: 'Open Sans';
	}

	* {
		   box-sizing: border-box;
	}

	.chatContainer {
		   width: 100%;
		   height: 550px;
		   border: 3px solid #eee;
	}

	.chatContainer > .chatHeader {
		   width: 100%;
		   background: #fff;
		   padding: 5px;
		   border-bottom: 1px solid #ddd;
	}

	.chatContainer > .chatHeader h3 {
		   font-weight: 400;
		   color: #666;
	}

	.chatContainer > .chatMessages {
		   height: 470px;
		   border-bottom: 1px solid #ddd;
		   overflow-y: scroll;
	}

	.chatContainer > .chatBottom form input[type="submit"] {
		   padding: 6px;
		   background: #fff;
		   border: 1px solid #ddd;
		   cursor: pointer;
	}

	.chatContainer > .chatBottom form input[type="text"] {
		   width: 85%;
		   padding: 8px;
		   padding-left: 12px;
		   border: 1px solid #ddd;
		   border-radius: 5px;
		   margin: 5px;
		   height: 30px;
	}

	.chatMessages li:nth-child(2n) {
		   background: #eeeeee;
	}

	.msg {
		   list-style: none;
		   border-bottom: 1px solid #ddd;
		   padding: 5px;
		   color: #222222;
	}

Możesz użyć praktycznie dowolnych stylów. Ważne jest ustawienie jakiejś wysokości w divie z klasą chatMessages oraz overflow-y na scroll. Dzięki temu użytkownik będzie mógł przewijać wiadomości.

Zajmijmy się teraz bazą danych. Stwórzmy nową tabelę o nazwie messages:

tabela_messages

Możesz kliknąć na obrazek aby go powiększyć.

Tabela składa się z trzech kolumn:

  • id – unikalny identyfikator wiadomości
  • name – nazwa użytkownika, który napisał wiadomość
  • message – treść wiadomości

Klikamy Zapisz i tabela jest już gotowa.

Ale skąd będziemy pobierać nazwę użytkownika? W tym przykładzie pobierzemy ją z tablicy GET aby było szybciej. Możesz ją też pobrać np. z tablicy sesyjnej – pełna dowolność.

Link do chatu (w przypadku serwera lokalnego) będzie wyglądał następująco: http://localhost/chat/?u=nazwa_uzytkownika. W pliku index.php (na samym początku) pobierzmy tą nazwę:

<?php
   $user = $_GET['u'];
?>

Teraz zmienna $user przechowuje nazwę użytkownika. Wyświetlmy ją wewnątrz chatHeader:

<div class="chatHeader">
   <h3>Witaj <?php echo ucwords($user); ?></h3>
</div>

Funkcja ucwords zamienia pierwszą literę ciągu na wielką. Zmodyfikujmy też input o typie hidden:

<input type="hidden" id="name" value="<?php echo $user; ?>"/>

W ten sposób będziemy w stanie wysłać nazwę użytkownika do bazy danych.

Utwórzmy teraz w tym samym katalogu nowy plik o nazwie ChatPoster.php. To do niego zostanie przesłane żądanie z formularza. Oto jego zawartość tego pliku:

<?php

   $db = new PDO('mysql:host=127.0.0.1;dbname=chat','root','haslo');
   if(isset($_POST['text']) && isset($_POST['name'])) {

      $text = strip_tags(stripslashes($_POST['text']));
      $name = strip_tags(stripslashes($_POST['name']));
      if(!empty($text) && !empty($name)) {
         $insert = $db->prepare("INSERT INTO messages VALUES('', '".$name."', '".$text."')");
         $insert->execute();

         echo "<li class='msg'><b>".ucwords($name).":</b> ".$text."</li>";
      }
   }

 ?>

Na początku łączymy się z bazą przy pomocy PDO przy pomocy nazwy bazy danych (w moim przypadku chat), nazwy użytkownika (w moim przypadku root) oraz hasła (w moim przypadku haslo).

Następnie sprawdzamy czy wartości z formularza (text oraz name) zostały przesłane. Kolejno z obu wartości są wycinane ukośniki (stripslashes) oraz wyświetla tagi HTML oraz PHP jako string. Poniżej w instrukcji if sprawdzamy czy wartości nie są puste. Jeśli nie są to nazwa użytkownika i wiadomość są zapisywane do bazy danych.

Poniżej wyświetlany jest element listy li z klasą msg, nazwą użytkownika oraz treścią wiadomości. Wróćmy teraz do pliku index.php i wyślijmy żądanie do pliku ChatPoster.php. Pomiędzy znacznikami { } funkcji ready dodaj następujący kod:

$(document).on('submit', '#chatForm', function(){
   var text = $.trim($("#text").val());
   var name = $.trim($("#name").val());

   if(text != "" && name != "") {
      $.post('ChatPoster.php', {text: text, name: name}, function(data){
         $(".chatMessages").append(data);				
         $(".chatMessages").scrollTop($(".chatMessages")[0].scrollHeight);
         $("#text").val('');
      });
   } else {
        alert("Musisz wpisac wiadomość!");
     }
});

Po kliknięciu na przycisk Wyślij zostanie pobrana wartość obu pól. Za pomocą funkcji trim wycinamy białe znaki z obu stron ciągu. Następnie w instrukcji warunkowej if sprawdzamy, czy pola nie są puste. Jeśli są to wyświetlamy przy pomocy funkcji alert ostrzeżenie. Jeśli nie są puste to wysyłamy żądanie do pliku ChatPoster.php z wartościami obu pól formularza. Zmienna data przechowuje odpowiedź z pliku ChatPoster.php, czyli element li, który następnie jest dodawany przy pomocy funkcji append jako ostatnie dziecko diva .chatMessages. Następnie kontener zostaje przescrollowany na sam dół, aby zawsze była widoczna najnowsza wiadomość. Na końcu wartość pola o id text zostaje opróżniona.

W tym momencie użytkownik może już wysyłać wiadomości, jednak nie będą one wyświetlane po odświeżeniu strony. Stwórzmy więc plik o nazwie GetMessages.php, który wyświetli wiadomości.

<?php

$db = new PDO('mysql:host=127.0.0.1;dbname=chat','root','haslo');

$query = $db->prepare("SELECT * FROM messages");
$query ->execute();

while($fetch = $query->fetch(PDO::FETCH_ASSOC)){
   $name = $fetch['name'];
   $message = $fetch['message'];
   $id = $fetch['id'];

   echo "<li id='$id' class='msg'><b>".ucwords($name).":</b> ".$message."</li>";
}

?>

Po połączaniu z bazą danych zaznaczamy z bazy danych wszystkie wiadomości. Następnie w pętli while wyświetlamy je identycznie jak w pliku ChatPoster.php.

Wróćmy teraz naszego kodu JS  i dodajmy kod, który wyświetli wiadomości:

function getMessages() {
   $.get('GetMessages.php', function(data){
      var amountMsg = $(".chatMessages li:last-child").attr('id');
      $(".chatMessages").html(data);
      var countMsg = data.split('<li').length - 1;
      array = [countMsg, amountMsg];
   });
   return array;
}

setInterval(function(){
   var num = getMessages();
   if(num[0] > num[1]) {
   $(".chatMessages").scrollTop($(".chatMessages")[0].scrollHeight);
   }
},1000);

Funkcja getMessages wysyła żądanie do pliku GetMessages.php. Zmienna data przechowuje wszystkie wiadomości z bazy. Następnie do zmiennej amoutMsg zostaje pobrany identyfikator ostatniej wiadomości (a więc ilość wszystkich wiadomości, które już są wyświetlone). Następnie wyświetlane są wiadomości i ponownie sprawdzona jest ich ilość. Następnie obie te liczby trafiają do tablicy, która zostaje zwracana przez tą funkcję.

Poniżej przy pomocy setInterval ustawiony jest kod, który wykona się co sekundę. Najpierw do zmiennej num zostaje przypisana tablica, która zwraca funkcja getMessages. Następnie obie liczby są porównane i jeśli wiadomości po załadowaniu przybyło, to cała zawartość zostanie przescrollowana do najnowszej wiadomości. Jeśli ilość wiadomości nie uległa zmianie to nic się nie stanie.

Gotowy przykład możesz zobaczyć tutaj.

Paczkę możesz pobrać tutaj.

Bądź pierwszą osobą, która skomentuje ten wpis.