Witryna zrzeszająca ludzi o podobnych zainteresowaniach, czyli witryna tematyczna, obecnie nie może obejść się bez systemu, służącego do komunikacji pomiędzy użytkownikami. W tym artykule, pokażę jak stworzyć proste, a zarazem użyteczne narzędzie, obsługujące wiadomości prywatne.
Czym jest i do czego może nam się przydać?
Mówiąc “system wiadomości prywatnych”, mam na myśli zestaw skryptów obsługujących wiadomości, które użytkownicy mogą przesyłać między sobą, w obrębie naszego serwisu. Naturalnie nasuwa się pytanie, w jakim celu mamy wzbogacać naszą witrynę w takowy.
Odpowiedzi może być wiele, jedną z nich, tą, która posłużyła mi za motywację do napisania skryptów, jest chęć umożliwienia łatwiejszej komunikacji między użytkownikami. Oczywiście taki zabieg ma sens zazwyczaj wtedy, kiedy nasz serwis porusza konkretne, tematyczne zagadnienia i zrzesza ludzi chcących wymieniać ze sobą jakiekolwiek informacje lub poglądy. Pierwszym nieodłącznym elementem tego typu witryny jest forum dyskusyjne, a drugim, moim zdaniem, właśnie narzędzie do komunikacji prywatnej – nie wszystko przecież chcemy przedstawiać ogółowi. Jeśli więc zdecydujemy się napisać tego typu system, powinniśmy rozważyć, jakie wymagania musi spełniać nasz serwis.
W zasadzie nie jest ich wiele i są one oczywiste. Mianowicie musi on być stroną WWW generowaną dynamicznie, opartą na bazie danych lub systemie zapisu danych do plików. Serwis powinien także umożliwiać personalizację ustawień dla wielu użytkowników.
Jak to będzie działać?
Na pozór, stworzenie takich skryptów może wydawać się bardzo skomplikowane. Bo przecież każdy użytkownik musiałby mieć własną skrzynkę, adres i tak dalej. Nic bardziej mylnego! W wersji, którą przedstawię w poniższym przykładzie, użyjemy trzech plików i opcjonalnie czwartego: newmail.php, mymail.php, sentmail.php oraz onlynewmail.php. Oczywiście, wszystko to można by zawrzeć w jednym pliku, a następnie metodą GET informować nasz system czy aktualnie ma wywołać skrzynkę nadawczą, czy odbiorczą itp., ale uznałem, że takie rozwiązanie niepotrzebnie skomplikowałoby kod i utrudniło wprowadzanie ewentualnych modyfikacji w przyszłości.
Poza samymi skryptami, potrzebować będziemy tabeli bazy danych (lub ewentualnie katalogu plików, jednak w tym przykładzie zdecydowałem się użyć bazy danych, z uwagi na prostotę wykorzystania oraz bezpieczeństwo, jakie niesie ze sobą takie rozwiązanie) i właśnie od jej struktury zaczniemy tworzyć nasz system.
Na dobry początek – tabela bazy danych.
Jako, że MySQL jest obecnie najpopularniejszym systemem baz danych, właśnie jego użyjemy jako podstawy dla naszych skryptów. Tabela powinna składać się z siedmiu kolumn: służącej za index mail_id oraz: temat, tresc, nadawca, odbiorca, stan a także data_dodania. Kolumna “mail_id”, będzie przechowywała nieedytowalny, identyfikator każdej wiadomości, powinna być automatycznie inkrementowana, z każdym rekordem.
Pozostałe, poza “tresc”, która przyjmie typ TEXT oraz “data_dodania” (tutaj typ DATETIME) proponuje pozostawić jako VARCHAR. Szybkie stworzenie takiej tabeli, umożliwi nam następujące zapytanie SQL:
CREATE TABLE `maile` ( `mail_id` int(10) unsigned NOT NULL auto_increment, `tytul` varchar(100) NOT NULL default '', `tresc` text NOT NULL, `nadawca` varchar(100) NOT NULL default '', `odbiorca` varchar(100) NOT NULL default '', `stan` varchar(100) NOT NULL default '', `data_nadania` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`mail_id`));
Wysyłamy nową wiadomość – newmail.php
Gdy nasza tabela jest gotowa i cierpliwie czeka na wprowadzenie doń jakichkolwiek danych, my zajmiemy się napisaniem skryptu umożliwiającego uczynienie jej zadość:-). Kod osadzamy w nowym pliku php, dla wygody formularz napiszemy, jak i obsłużymy, w jednym pliku, docelowo nasz skrypt powinien wyglądać tak:
<center><b>Redagowanie nowej wiadomości:</b><br />Wpisz poniżej temat i treść, a następnie określ adresata, aby wysłać wiadomość.</center><br /><br /><? if (isset($_POST['wyslij'])) {@mysql_connect ('localhost' , 'użytkownik, 'nasze_haslo'); @mysql_select_db ('baza_danych);$zapytanie = "INSERT INTO maile (mail_id, tytul, tresc, nadawca, odbiorca, stan, data_nadania)VALUES (0, '{$_POST['temat']}', '{$_POST['tresc']}', '{$_POST['nadawca']}', '{$_POST['odbiorca']}', 'nadana', Now())";if (empty($_POST['temat']) && empty($_POST['tresc']) && empty($_POST['odbiorca']) && empty($_POST['nadawca'])){print '<center><font color="red"><h6>BŁĄD: Pola treść, temat, nadawca oraz adresat nie mogą być puste!<br /><br /></h6>'; print '<a href="newmail.php">Wróć do formularza wysyłania wiadomości.</a></center></font>'; die;}if (@mysql_query ($zapytanie)) {print "<center>Wiadomość została wysłana.</center>";} else {print '<font color=red><b>BŁĄD: <center></b>Nie można wysłać wiadomości!</font></center>';}mysql_close();}else{print '<form action="newmail.php" method="post"><p>Temat: <input type="text" name="temat" size="40" maxsize="100" /></p> <p>Treść: <textarea name="tresc" columns="80" rows="5" ></textarea></p> <p>Adresat: <input type="text" name="odbiorca" maxsize="50" /> <input type="text" name="nadawca" maxsize="50" /> <input type="submit" name="wyslij" value="Wyślij wiadomość"/></form>';}?>
Pierwsze trzy linijki kodu, to tytuł pisany w HTMLu, nim nie będziemy się zajmować. Znacznik <? Rozpoczyna sesję PHP, pierwszym zadaniem, jakie wykona nasz skrypt, będzie sprawdzenie czy formularz został już przesłany, odpowiada za to instrukcja:
if (isset($_POST['wyslij']))
Jeśli został, uruchamiane zostaje połączenie z serwerem baz danych, a następnie wybierana jest konkretna baza, za pomocą poleceń:
{@mysql_connect ('localhost' , 'użytkownik' , 'nasze_haslo'); //połączenie@mysql_select_db ('baza_danych); //wybór
Kolejnym krokiem, będzie zdefiniowanie zapytania, odpowiedzialnego za wstawienie wysyłanej wiadomości do tabeli bazy danych (właśnie tej, która obecnie się niecierpliwi;-) ):
$zapytanie = "INSERT INTO maile (mail_id, tytul, tresc, nadawca, odbiorca, stan, data_nadania)VALUES (0, '{$_POST['temat']}', '{$_POST['tresc']}', '{$_POST['nadawca']}', '{$_POST['odbiorca']}', 'nadana', Now())";
Zauważmy, iż zapytanie przekazywane jest do zmiennej, która później zostanie wykorzystana w funkcji mysql_query. Robimy tak, by maksymalnie uprościć konstrukcję if, która będzie odpowiedzialna za wywołanie zapytania, ale to za chwilę. Kolumna “mail_id”, jest automatycznie inkrementowana, w związku z tym, spokojnie możemy przekazać, do niej wartość 0, mając pewność, iż i tak z każdym wpisem, jej wartość będzie o jeden wyższa.
Następnie do kolejnych pól przekazujemy wartości z formularza, aż do kolumny “stan”, której wartość ustalamy na “nadana”, dla naszego skryptu będzie to oznaczać, że wiadomość została wysłana, aczkolwiek odbiorca jeszcze jej nie przeczytał. Natomiast wypełnienie kolumny “data_nadania”, pozostawiamy funkcji Now(), która zawsze podaje nam aktualny czas i datę.
Następną czynnością, jaką wykonuje nasz skrypt, jest sprawdzenie kompletności przesłanych danych, oczywiście, aby nasza wiadomość dotarła do adresata pomyślnie, wypełnione musza zostać wszystkie pola formularza, dlatego też poniższy kod przerwie działanie skryptu, jeśli będzie inaczej:
if (empty($_POST['temat']) && empty($_POST['tresc']) && empty($_POST['odbiorca']) && empty($_POST['nadawca'])){print '<center><font color="red"><h6>BŁĄD: Pola treść, temat, nadawca oraz adresat nie mogą być puste!<br /><br /></h6>'; print '<a href="newmail.php">Wróć do formularza wysyłania wiadomości.</a></center></font>'; die;}
W tym momencie nadszedł czas na obiecaną konstrukcję if, Właśnie ona wykonuje nasze zapytanie INSERT. Jak widzimy, funkcja mysql_query, uruchamiana jest jako warunek funkcji if, dzięki temu w razie pomyślnego wykonania zapytania, funkcja zwraca wartość TRUE, a w przypadku niepowodzenia – FALSE. Pozwala nam to w łatwy sposób wyświetlić komunikat o ewentualnym błędzie lub po prostu o powodzeniu operacji:
if (@mysql_query ($zapytanie)) {print "<center>Wiadomość została wysłana.</center>";} else {print '<font color=red><b>BŁĄD: <center></b>Nie można wysłać wiadomości!</font></center>';}mysql_close();} //zamykamy połączenie z bazą danych
Od tego momentu nasza wiadomość jest wysłana i czeka na odebranie, przez adresata, któremu umożliwi to kolejny skrypt, zanim jednak o nim powiemy, przyjrzyjmy się jeszcze klauzuli else, naszej pierwszej konstrukcji if. Jak pamiętamy, cały opisany wyżej kod, wykonywany jest w przypadku gdy formularz został już wysłany, nie trudno się więc domyśleć, że klauzula else, będzie odpowiedzialna za wyświetlenie rzeczonego formularza:
else{print '<form action="newmail.php" method="post"><p>Temat: <input type="text" name="temat" size="40" maxsize="100" /></p> <p>Treść: <textarea name="tresc" columns="80" rows="5" ></textarea></p> <p>Adresat: <input type="text" name="odbiorca" maxsize="50" /> <input type="text" name="nadawca" maxsize="50" /> <input type="submit" name="wyslij" value="Wyślij wiadomość"/></form>';}?>
Odbieramy pierwszą wiadomość – mymail.php
Podczas, gdy w tabeli “maile” oczekuje na nas pierwsza wiadomość, zajmiemy się napisaniem skryptu działającego jako nasza skrzynka odbiorcza. Naturalnie kod osadzamy w nowym pliku php, w naszym przykładzie plik przyjmie nazwę mymail.php, a skrypt, który w nim umieścimy powinien wyglądać tak:
<? {@mysql_connect ('localhost' , 'użytkownik, 'nasze_haslo'); @mysql_select_db ('baza_danych); $zapytanie = "SELECT * FROM maile ORDER BY data_nadania DESC"; if ($r = mysql_query ($zapytanie)){ while ($wiersz = mysql_fetch_array ($r)) { if($_SESSION['user'] == $wiersz['odbiorca']) { print "<table border=0 width=437><tr><td><font size=1><p align=left>Od: {$wiersz['nadawca']}</td> <td><p align=right>Wysłana: {$wiersz['data_nadania']}</align></font></td></tr><tr><td><p align=left><font size=1>Do: <font color="white">{$wiersz['odbiorca']}</font></td><td><b><p align=right>Temat: <font size=2 color="white"> {$wiersz['tytul']}</align></font></b></td></tr><tr><td colspan=2><br /> <font size=1 color=white>{$wiersz['tresc']}</align></font></td></tr></table><hr />";$user = $_SESSION['user'];$zapytanie2 = "UPDATE maile SET stan='przeczytana' WHERE odbiorca='$user'"; mysql_query($zapytanie2);} }}?>
I znów, zaczniemy od omówienia kodu krok po kroku. Na początek (po znaczniku otwierającym sesję – <?), znane nam już z wcześniejszego skryptu, dwie linijki odpowiedzialne za połączenie z bazą danych:
{@mysql_connect ('localhost' , 'użytkownik, 'nasze_hasło'); @mysql_select_db ('baza_danych);
Następnie definicja zapytania SELECT, odpowiedzialnego za pobranie z bazy danych wszystkich rekordów, jakie są w niej zapisane:
$zapytanie = "SELECT * FROM maile ORDER BY data_nadania DESC";
Zauważmy, iż tak jak wcześniej, tak i teraz zapytanie przekazujemy do zmiennej $zapytanie, osobiście uważam to za dobry zwyczaj, którego trzyma się wielu programistów i który w znacznym stopniu poprawia czytelność kodu. Jako takiej składni zapytania nie będę tutaj przedstawiał, dodam tylko, że klauzula ORDER BY, decyduje o tym, według jakiego kryterium rekordy będą porządkowane, natomiast DESC (ang. Descending – malejąco), określa ich kolejność. Następnym krokiem jest oczywiście wykonanie powyższego zapytania, również przy pomocy instrukcji warunkowej if:
if ($r = mysql_query ($zapytanie))
A kolejna linijka, w której używamy pętli while, odpowiada za przeniesienie wyniku zapytania do tabeli, służy temu oczywiście funkcja mysql_fetch_array:
while ($wiersz = mysql_fetch_array ($r))
Użycie pętli while w tym konkretnym przypadku, ma na celu odczytanie każdego rekordu z tabeli. Pętla while działa do momentu, w którym jej warunek przestaje zwracać wartość TRUE (być prawdziwy), dlatego też w momencie wyczerpania się zawartości tabeli, instrukcja ta kończy pracę. W tym momencie, nasuwa się oczywiste pytanie, po co nam wszystkie wiadomości, przecież w ten sposób każdy będzie mógł przeczytać wiadomość adresowaną do konkretnego użytkownika.
Z pomocą przychodzi doskonale znana, instrukcja warunkowa, która dokona sprawdzenia tożsamości odbiorcy wiadomości. W tej chwili ważne jest, aby system był w stanie jednoznacznie zidentyfikować zalogowanego użytkownika. W moim przykładzie posłużymy się identyfikacją na podstawie danych przechowywanych w sesji, jeśli jednak konkretny system autoryzacji, działający na Twojej stronie przechowuje te dane w innym miejscu, powinieneś odpowiednio dostosować kod. Ale przejdźmy do sedna sprawy, rzeczona instrukcja if, przyjmie oczywiście następującą postać:
if($_SESSION['user'] == $wiersz['odbiorca'])
Kolejne linijki naszego skryptu, odpowiadają za wyświetlenie żądanej wiadomości, w naszym przykładzie, użyjemy do tego celu instrukcji print oraz tabeli HTML:
print "<table border=0 width=437><tr><td><font size=1><p align=left>Od: {$wiersz['nadawca']}</td> <td><p align=right>Wysłana: {$wiersz['data_nadania']}</align></font></td></tr><tr><td><p align=left><font size=1>Do: <font color="white">{$wiersz['odbiorca']}</font></td><td><b><p align=right>Temat: <font size=2 color="white"> {$wiersz['tytul']}</align></font></b></td></tr><tr><td colspan=2><br /> <font size=1 color=white>{$wiersz['tresc']}</align></font></td></tr></table><hr />";
Jeszcze jedną, ostatnią już czynnością, do jakiej wykorzystamy skrypt “skrzynki odbiorczej” będzie ustawienie statusu wiadomości na przeczytaną. W jakim celu? Oczywiście, wszystko dla wygody użytkownika. Jeśli będziemy posiadać informacje na temat tego, czy w jego “skrzynce” znajdują się nieprzeczytane wiadomości, będziemy mogli go o tym poinformować, a tym samym, zachęcić do jej odwiedzenia. Stan wiadomości zmienimy za pomącą zapytania UPDATE, sformułowanego w następujący sposób:
$user = $_SESSION['user'];$zapytanie2 = "UPDATE maile SET stan='przeczytana' WHERE odbiorca='$user'"; mysql_query($zapytanie2);
Najpierw, dla porządku, przerzucamy login użytkownika do zmiennej $user, a następnie za pomocą klauzuli WHERE ograniczamy zapytanie tak, aby zmieniało wartości kolumny “stan”, jedynie dla wiadomości, które zaadresowane są do użytkownika zalogowanego.
Skrzynka nadawcza – sentmail.php
Teraz, gdy nasz system jest już zdolny do wysyłania i odczytywania wiadomości, możemy jeszcze umożliwić użytkownikom przeglądanie wysłanych przez nich wiadomości. Kodu odpowiedzialnego za tę czynność, nie będę opisywał, ponieważ jest on analogiczny do kodu “skrzynki odbiorczej”. Jedyną różnicą jest konieczność porównania loginu użytkownika ze zmienną “nadawca” a nie jak w przypadku poprzedniego skryptu – “odbiorca”. Zmianę wprowadzamy oczywiście w odpowiednim warunku, instrukcji if:
if($_SESSION['user'] == $wiersz['nadawca'])
Naturalnie, nasza “skrzynka nadawcza” powinna być również pozbawiona fragmentu kodu odpowiedzialnego za zmianę statusu wiadomości z “nadana” na “przeczytana”.
Opcjonalny plik czwarty – onlynewmail.php
Jak wskazuje już sama nazwa pliku, ten skrypt będzie odpowiadał za wyświetlanie tylko najnowszych wiadomości, to znaczy takich, które nie zostały jeszcze przeczytane, a więc (przenosząc to na język naszej bazy danych), takich, które w polu “stan” posiadają wartość “nadana”. Podobnie jak dla skrzynki nadawczej i odbiorczej, tak i w tym przypadku różnica pomiędzy tym skryptem, a skryptem mymail.php nie będzie zbyt duża i polegać będzie jedynie, na zmianie warunku konstrukcji if, odpowiedzialnej za wyświetlanie odczytanych z tabeli rekordów. W przeciwieństwie do “skrzynki nadawczej”, w tym skrypcie pozostawimy polecenie zmieniające stan wiadomości na “przeczytana”, w końcu każda wiadomość nową jest tylko raz:. Jak pamiętamy skrypt skrzynki odbiorczej korzystał z warunku:
if($_SESSION['user'] == $wiersz['odbiorca'])
Podobnie będzie i tym razem, jednak konieczne jest dodanie jeszcze jednego kryterium, które ograniczy wyświetlane wiadomości tylko do tych, wcześniej nieczytanych. Oczywiście nasz nowy warunek przyjmie następującą postać:
if($_SESSION['user'] == $wiersz['odbiorca'] && $wiersz['stan'] == 'nadana')
Menu główne – czyli łączymy wszystko w jedną całość
Na koniec, kiedy wszystko jest już gotowe, pozostaje nam tylko stworzenie menu, udostępniającego użytkownikowi stworzone przez nas pliki. Menu powinno być umieszczone na stronie dostępnej jedynie po załogowaniu się użytkownika oraz oczywiście w maksymalnie przystępnym miejscu. Właściwie możemy się ograniczyć do czterech prostych linków w HTMLu i nadać naszemu menu postać:
<a href=onlynewmail.php><b></b><font color="green">Czytaj NOWE wiadomości</font></b></a><br /><a href=newmail.php>Nowa wiadomość</a><br /><a href=mymail.php>Skrzynka Odbiorcza</a><br /><a href=sentmail.php>Wiadomości Wysłane</a><br />
Jeśli jednak, zakładaliśmy, iż chcemy poinformować użytkownika o tym czy czekają na niego nowe wiadomości, należałoby to założenie zrealizować. Będziemy do tego celu potrzebowali małego skryptu PHP, który połączy się z baza danych, określi ilość nieprzeczytanych wiadomości i oczywiście, jeśli takowe się znajdą, zadecyduje o wyświetleniu odpowiedniego hiperłącza. Skrypt umieszczamy rzecz jasna w tym samym pliku gdzie umieszczone zostanie menu, a jego docelowa postać, może przyjąć taką formę:
$user = $_SESSION['user'];@mysql_connect ('localhost' , 'użytkowink' , 'nasze_haslo');@mysql_select_db ('baza_danych');$Zapytanie = "SELECT * FROM maile WHERE stan='nadana' and odbiorca='$user'";$w = mysql_query($Zapytanie);$liczba_nowych = mysql_num_rows($w);if ($liczba_nowych >= 1) {print'<font color="green">»</font> <a href=onlynewmail.php><b></b><font color="green">Czytaj NOWE wiadomości</font></b></a><br />';};print '» <a href=newmail.php>Nowa wiadomość<br /></a>» <a href=mymail.php>Skrzynka Odbiorcza</a><br />» <a href=sentmail.php>Wiadomości Wysłane</a><br />';}
Pierwsza linijka, powyższego kodu to znów “porządkowe” zrzucenie loginu użytkownika, do zmiennej $user. Kolejne dwie, to równie dobrze nam znane polecenia, łączące nasz skrypt z bazą danych. Czwarta linijka natomiast, stanowi zapytanie SELECT, które wydobędzie z naszej tabeli, wiadomości przeznaczone właśnie dla użytkownika zalogowanego (and odbiorca=’$user’), a jednocześnie wiadomości nieodczytane (WHERE stan=’nadana’):
$Zapytanie = "SELECT * FROM maile WHERE stan='nadana' and odbiorca='$user'";
Piąta linijka to naturalnie wykonanie zapytania SELECT oraz przeniesienie jego wyniku do zmiennej $w. Kolejny fragment to właściwie serce skryptu – funkcja mysql_num_rows() odpowiedzialna za zliczenie ilości wierszy zwróconych przez zapytanie i przekazanie tej liczby do zmiennej $liczba_nowych:
$liczba_nowych = mysql_num_rows($w);
Na samym końcu wyświetlamy właściwe menu, dzięki funkcji if, sprawdzającej czy liczba nieprzeczytanych wiadomości jest większa lub równa 1, link “Czytaj NOWE wiadomości” wyświetli się tylko wtedy, jeśli zajdzie taka potrzeba:
if ($liczba_nowych >= 1) {print'<font color="green">»</font> <a href=onlynewmail.php><b></b><font color="green">Czytaj NOWE wiadomości</font></b></a><br />';};print '» <a href=newmail.php>Nowa wiadomość<br /></a>» <a href=mymail.php>Skrzynka Odbiorcza</a><br />» <a href=sentmail.php>Wiadomości Wysłane</a><br />';}
W ten oto sposób stworzyliśmy proste, ale użyteczne narzędzie do komunikowania się użytkowników naszego serwisu, nic oczywiście nie stoi na przeszkodzie by później wzbogacić je o kolejne funkcje, które jeszcze bardziej poprawią jego funkcjonalność. Dobrym przykładem byłoby tutaj, porcjowanie wiadomości na stronach, czy też skrypt do zarządzania otrzymaną “pocztą”.