chevron-left chevron-right

[PHP] Prosty czat (shoutbox).

W dzisiejszym artykule mam zamiar Tobie sposób na zbudowanie prostego czatu na bazie PHP i bazy danych MySQL. Jako uzupełnienie tego poradnika przedstawię także przykładowy styl dla takiej aplikacji.

Czego potrzebujemy do budowy takiej aplikacji?
Na pewno potrzebujemy następujących rzeczy:

  • własny serwer (wykupiony lub postawiony u siebie na komputerze, np. za pomocą programu XAMPP)
  • adres bazy danych (np. localhost)
  • login do bazy danych
  • hasło do bazy danych
  • nazwa bazy danych
Taki zestaw informacji wystarczy nam by uzyskać połączenie z bazą danych, w której to musimy stworzyć tabelę o nazwie "czat" za pomocą następującego polecenia SQL:
CREATE TABLE 'czat' (
  'id' INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  'nazwa' VARCHAR(100) NOT NULL,
  'email' VARCHAR(100) NOT NULL,
  'tresc' TEXT NOT NULL,
  'ip' VARCHAR(45) NOT NULL,
  PRIMARY KEY ('id')
);
Następnie musimy przygotować folder "czat" z następującymi plikami:
  • index.php
  • db.php
  • styl.css
  • folder "img", dla plików graficznych, które mamy zamiar użyć w naszej aplikacji

Teraz pora stworzenie kodu dla naszego pliku db.php, który odpowiada za przechowywanie danych do połączenia się z bazą danych na serwerze.
Kod wygląda następująco:

	<?php
        $host = 'localhost'; //adres serwera bazy danych, zazwyczaj localhost
        $username = 'login'; //login do bazy danych
        $password = 'haslo'; //hasło do bazy danych
        $database = 'demo'; //nazwa bazy danych do ktorej będziemy się odnosić
    ?>
Nadszedł moment, aby zacząć tworzyć plik index.php, który na początek wygląda następująco:
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Czat by Piotr Nalepa | Blog.piotrnalepa.pl</title>
        <link rel="stylesheet" href="styl.css" type="text/css" />
    </head>
    <body>
        <div id="strona">
            <h1>Czat</h1>
            <h5><a href="http://www.piotrnalepa.pl" title="Piotr Nalepa">Piotr Nalepa</a> | <a href="https://blog.piotrnalepa.pl" title="Blog webmasterski">Blog webmasterski</a></h5>
            <div id="boxtop">
            </div>
            <div id="content">
Następnie należy wstawić kod uzyskujący połączenie z bazą danych do pliku index.php:
    <?php
        $self = $_SERVER['PHP_SELF']; //pobiera nazwę tego pliku do zmiennej
        $adres_ip = $_SERVER[REMOTE_ADDR]; //pobiera adres IP użytkownika
        include ('db.php'); // pobiera dane dostępowe do bazy danych
        $connect = mysql_connect($host, $username, $password) or die('<p class="blad">Nie można się połączyć z bazą!</p>');
        mysql_select_db($database, $connect) or die('<p class="blad">Błąd połączenia z bazą danych</p>');
Sprawdzamy czy coś zostało przesłane:
    if(isset($_POST['send']))
    {
        if(empty($_POST['name']) || empty($_POST['email']) || empty($_POST['post']))
        {
            echo('<p class="blad">Nie wypełniłeś wszystkich wymaganych pól.</p>');
        } 
        else
        {
Jeśli nic nie zostało wysłane, to zostaje sprawdzone, czy wymagane pola zostały wypełnione. Jeśli nie są, to wyświetla stosowny komunikat. Kolejnym krokiem jest wpisanie następującego kodu:
            $nazwa = htmlspecialchars(mysql_real_escape_string($_POST['nazwa'])); 
            $email = htmlspecialchars(mysql_real_escape_string($_POST['email'])); 
            $tresc = htmlspecialchars(mysql_real_escape_string($_POST['tresc']));
            $sql = "INSERT INTO czat SET nazwa='$nazwa', email='$email', tresc='$tresc', ip='$adres_ip';";
            if (@mysql_query($sql))
            {
                echo('<p class="brawo">Dodano nowy wpis!</p>');
            } 
            else
            {
                echo('<p class="blad">Wystąpił niespodziewany błąd, spróbuj jeszcze raz.</p>');
            }
        }
    }
Jak widać skorzystaliśmy tutaj z funkcji PHP: htmlspecialschars() oraz mysql_real_escape_string(). Zapobiegają one wpisaniu złośliwego kodu do pól tekstowych, które po wywołaniu z bazy danych mogłyby uszkodzić całą aplikację.
Teraz pora na wywołanie tych wpisów czatu na okno przeglądarki. Domyślnie ustawiłem na 10 ostatnich wpisów.
	$query = "SELECT * FROM czat ORDER BY id DESC LIMIT 10;";
 
    $result = @mysql_query($query) or die('<p class="blad">Wystąpił błąd podczas pobierania wpisów z bazy.</p>'); ?>
    <ul>
    <?php
    	while ($row = mysql_fetch_array($result)) {
        $enazwa = stripslashes($row['nazwa']);
        $eemail = stripslashes($row['email']);
        $etresc = stripslashes($row['tresc']);
 
        $grav_url = "http://www.gravatar.com/avatar.php?gravatar_id=".md5(strtolower($eemail))."&size=70"; 
 
        echo ('
        <li>
        	<div class="meta">
            	<img src="%27.$grav_url.%27" alt="Gravatar">
        		<p>'.$enazwa.'</p>
            </div>
            <div class="wpis">
            	<p>'.$etresc.'</p>
           	</div>
        </li>');
    }
    ?></ul>
Tutaj wykorzystałem pobieranie obrazków na podstawie profilu z serwisu Gravatar.com.
W powyższym kodzie, pierwsza linia stara się sprawdzić czy są jakieś wpisy w bazie danych i jeśli są, to powinny być wyświetlone na stronie.
Natomiast funkcja stripslashes() usuwa wszystkie znaki "/" z tekstu zapisanego w bazie danych.

Ostatnim krokiem jest stworzenie formularza do wpisów na czacie.

	<form action="<?php $self ?>" method="post">
        <h2>Czatuj!</h2>
        <div class="fnazwa">
        	<label for="nazwa">
            	<p>Nazwa:</p>
            </label>
            <input name="nazwa" type="text" cols="20" />
        </div>
        <div class="femail">
        	<label for="email">
        		<p>Email:</p>
            </label>
            <input name="email" type="text" cols="20" />
        </div>
        <textarea name="tresc" rows="5" cols="40"></textarea>
        <input name="send" type="hidden" />
        <p><input type="submit" value="Wyślij" /></p>
	</form>
	</div>
    </div>
</body>
</html>
Jak widać, została tu wykorzystana zmienna $send w celu wstawienia adresu strony jako link. Poza tym, mamy do czynienia ze standardowym szablonem formularza. Należy też jakoś upięknić nasz czat. Więc stwórzmy plik styl.css, który bedzie wyglądał tak:
	* {
    margin: 0;
    padding: 0;
    }
    body {
    background: #323f66 top center url("images/tlo.png") no-repeat;
    color: #ffffff;
    font-family: Tahoma, sans-serif;
    }
    h1 {
    font-size: 22px;
    letter-spacing: -1px;
    background: url("images/czat.png") no-repeat;
    width: 303px;
    margin: 0 auto;
    text-indent: -500px;
    color: #33ccff;
    }
    h2 {
    font-size: 18px;
    letter-spacing: -1px;
    background: url("images/czatuj.png") no-repeat;
    width: 119px;
    text-indent: -500px;
    color: #33ccff;
    clear: both;
    margin: 15px 0;
    }
    h5 a:link, h5 a:visited {
    color: #ffffff;
    text-decoration: none;
    }
    h5 a:hover, h5 a:active, h5 a:focus {
    border-bottom: 1px solid #fff;
    }
    p {
    font-size: 14px;
    line-height: 16px;
    font-family: Tahoma, sans-serif;
    }
    p.blad {
    background-color: #603131;
    border: 1px solid #5c2d2d;
    width: 260px;
    padding: 10px;
    margin-bottom: 15px;
    }
    p.brawo {
    background-color: #313d60;
    border: 1px solid #2d395c;
    width: 260px;
    padding: 10px;
    margin-bottom: 15px;
    }
    #strona {
    width: 664px;
    margin: 20px auto;
    text-align: center;
    }
	#boxtop {
	margin: 30px auto 0px;
	background: url("images/top.png") no-repeat;
	width: 663px;
	height: 23px;
	}
 
	#boxbot {
	margin: 0px auto 30px;
	background: url("images/bot.png") no-repeat;
	width: 664px;
	height: 25px;
	}
	#content {
	margin: 0 auto;
	width: 664px;
	text-align: left;
	background: url("images/bg.png") repeat-y;
	padding: 15px 35px;
	}
 
    #content ul {
    margin-left: 0;
    margin-bottom: 15px;
    }
 
    #content ul li {
    list-style: none;
    clear: both;
    padding-top: 30px;
    }
 
    #content ul li:first-child {
    padding-top:0;
    }
 
    .meta {
    width: 85px;
    text-align: left;
    float: left;
    min-height: 110px;
    font-weight: bold;
    }
 
    .meta img {
    padding: 5px;
    background-color: #313d60;
    }
 
    .meta p {
    font-size: 12px;
    }
 
    .wpis {
    width: 500px;
    float: left;
    margin-left: 15px;
    min-height: 110px;
    padding-top: 5px;
    }
 
    form {
    clear: both;
    margin-top: 135px !important;
    }
 
    .fnazwa, .femail {
    width: 222px;
    float: left;
    }
 
    form p {
    font-weight: bold;
    margin-bottom: 3px;
    }
 
    form textarea {
    width: 365px;
    overflow: hidden;
    }
 
    form input, form textarea {
    background-color: #313d60;
    border: 1px solid #2d395c;
    color: #ffffff;
    padding: 5px;
    font-family: Tahoma, sans-serif;
    margin-bottom: 10px;
    }
W ten sposób stworzyliśmy nasz własny czat.
Dziękuję za uwagę 🙂

  • Sobak

    Prosty, czysty i bezpieczny. Czego tu jeszcze chcieć?
    To samo się tyczy innych wpisów. Szkoda tylko, że tak mało komentarzy.

  • PixeL

    kod SQL u mnie nie działa, dopiero to zadziałało:

    CREATE TABLE `chat` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `nazwa` VARCHAR(100) NOT NULL,
    `email` VARCHAR(100) NOT NULL,
    `tresc` TEXT NOT NULL,
    `ip` VARCHAR(45) NOT NULL
    )

  • dzięki, że podzieliłeś się modyfikacją mojego kodu
    od siebie tylko dodam, że mój kod też działa 😉

  • Dominik

    Witam.
    Mam następujący problem w tej linii:

    $result = @mysql_query($query) or die(‚Wystąpił błąd podczas pobierania wpisów z bazy.’); ?>

    Mógłby ktoś pomoc ?

  • a co to za problem? bo sama linia kodu mi nic nie mówi, bo wygląda ok

  • Szalony Kefir

    Ale kilka rzeczy chyba popsułeś, w jednym miejscu jest „name” w innym „nazwa”, to samo z „post” i „treść”… w taki wypadku name i treść zawsze jest równe NULL więc żadne wpisy nie zostaną dodane…

    5 pole od góry

  • dzięki za zwrócenie uwagi
    rzeczywiście wkradło się tutaj moje niedopatrzenie

  • remiks

    Bardzo miły skrypt. Na pewno też każdy początkujący webmaster nie będzie miał z nim problemów jeśli chodzi o podłączenie go z własnym skryptem strony.

    Pozdrawiam.

  • Przemo

    Dominik:

    SELECT * FROM czat ORDER BY id DESC LIMIT 10;";

    powinno być

    SELECT * FROM chat ORDER BY id DESC LIMIT 10;";
  • Daro

    Witam, powiem w prost, nie wiem jak odpalić tego shoutbox’a w moim indexie (w mojej stronie), nie ma jakiegoś IFRAME, albo cos w tym stylu?  jaki kod mam wkleić do mojego INDEX’U ze stroną 
    Proszę o pomoc
    …………………………………………………
    chodzi mi o miejsce w którym ten Shoutbox ma być wyświetlany

  • Piotr Nalepa

    powinieneś wkleić wszystko po kolei tak jak leci w tym tutorialu.
    pamiętaj by style dać do osobnego pliku lub w sekcję HEAD

  • Marcin

    witam, zrobilem tak jak podajesz i index.php wyswietla :
    Wystąpił błąd podczas pobierania wpisów z bazy.

  • Sven

    Wielkie podziękowania.
    Świetny skrypt do nauki „od podstaw”. Wystarczy troszkę pokombinować i można sobie z niego stworzyć naprawdę fajne rozwiązanie. Szkoda tylko, że autor pominął kwestię skryptu do czyszczenia starych wpisów. Pozdrawiam Serdecznie!

  • Niezłe, ale po opublikowaniu wiadomości na czacie i wcisnięciu F5, wiadomość publikuje się jeszcze raz. I jeszcze raz jak się jeszcze raz wciśnie F5. czy ożna temu zapobiec? Pozdrawiam i dziękuję za interesujący materiał.

  • Foxconn

    Nie działa coś funkcja gravatara bo tylko pokzuje błąd obrazka (przełamana ikonka zdj
    )

  • Foxconn

    Ok naprawilem zamiast %27 powinno być ‚ nie wiem czy wina autora czy www po za tym świetne pozdrawiam 🙂