webmaster webmastering webdesign

Jesteś tutaj: webmade.org >> porady >> php + mysql

Mechanizm prywatnych wiadomości w php

autor: Marcin 'loganek' Kolny, ostatnia modyfikacja: 2008-03-16

szukaj: prywatne wiadomości prywatne wiadomości PHP PHP

Pewnie nie jeden z webmasterów chciałby udostępnić swoim użytkownikom swojej strony możliwość komunikacji między sobą. Możliwości takie dają liczne CMSy lub fora internetowe. Co jednak, jeśli nie chcemy instalować na serwerze rozbudowanego skryptu CMSów lub forum? Najlepszym rozwiązaniem jest napisanie własnego skryptu dającego taką możliwość. Wbrew pozorom nie jest to skomplikowane. Nasza przykładowa strona będzie opierała się na sesjach, które miałem okazje już opisywać.

Utworzenie bazy danych

Wiadomości, loginy oraz hasła będą przechowywane w bazie danych MySQL. Stwórzmy więc przykładową bazę danych(np. o nazwie „test”) oraz 2 tabele. Jedna, o nazwie wiadomości będzie przechowywała wszystkie wiadomości przesyłane przez użytkowników, druga będzie przechowywała informacje o zarejestrowanych użytkownikach. Obie tabele możemy utworzyć poprzez wykonanie poniższych zapytań:

CREATE TABLE `users` (`user_id` INT NOT NULL AUTO_INCREMENT ,
`user_login` VARCHAR( 30 ),
`user_haslo` VARCHAR( 30 ),
PRIMARY KEY ( `user_id` ) 
);

CREATE TABLE `wiadomosci` (
  `wiad_id` int(11) NOT NULL auto_increment,
  `wiad_tresc` text,
  `wiad_od` int(11),
  `wiad_do` int(11),
  `wiad_przeczytane` tinyint(1),
  `wiad_data` datetime,
  `wiad_temat` varchar(30),
  `wiad_czyj` tinyint(1),
  PRIMARY KEY  (`wiad_id`)
);

Jak widać tabela „users” nie różni się niczym od tabeli utworzonej podczas artykułu o sesjach. Druga tabela wymaga jednak wyjaśnienia. Pole wiad_id przechowywuje identyfikator wiadomości, wiad_tresc – treść wiadomości, wiad_od – identyfikator nadawcy, wiad_do – identyfikator odbiorcy, wiad_przeczytane – czy wiadomość była już przeczytana(jeśli tak, przyjmuje wartość 1, jeśli nie, 0), wiad_data – date i czas wysłania wiadomości, wiad_temat – temat wiadomości, a wiad_czyj – właściciela rekordu; jeśli jest to własność nadawcy, przyjmuje wartość jeden, jeśli odbiorcy, 0. Przeznaczenie tego pola wyjaśni się w dalszej części artykułu.

Formularz rejestracyjny

Tak jak w artykule o sesjach, tak i teraz powinniśmy stworzyć formularz rejestracyjny. Jest on taki sam jak w artykule dotyczącym sesji, więc nie będę go tu tłumaczył.

<?php
mysql_connect("localhost", "root", "")or die("Nie można nawiązać połączenia z bazą"); //połączenie z bazą danych
mysql_select_db("test")or die("Wystąpił błąd podczas wybierania bazy danych");

function ShowForm($komunikat=""){	//funkcja wyświetlająca formularz rejestracyjny
	echo "$komunikat<br>";
	echo "<form action='rejestruj.php' method=post>";
	echo "Login: <input type=text name=login><br>";
	echo "Hasło: <input type=text name=haslo><br>";
	echo "<input type=hidden value='1' name=send>";
	echo "<input type=submit value='Zarejestruj mnie'>";
	echo "</form>";
}
?>
<!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" xml:lang="pl" lang="pl">
<head>
	<title>Formularz rejestracyjny</title>
</head>
<body>
<?php
if($_POST["send"]==1){	//sprawdzanie czy formularz został wysłany
	if(!empty($_POST["login"]) && !empty($_POST["haslo"])){	//oraz czy uzupełniono wszystkie dane
		if(mysql_num_rows(mysql_query("select * from users where user_login='".htmlspecialchars($_POST["login"]."'"))))ShowForm("Użytkownik o podanym loginie już istnieje!!!"); // sprawdzanie czy użytkownik o podanej nazwie już istnieje
		else{
			mysql_query("insert into users values(NULL, '".htmlspecialchars($_POST["login"])."', '".htmlspecialchars($_POST["haslo"])."')"); // zapisywanie rekordu do bazy
			echo "Rejestracja przebiegła pomyślnie. Możesz teraz przejść do <a href='index.php'>strony głównej</a> i się zalogować.";
			}
	}
	else ShowForm("Nie uzupełniono wszystkich pól!!!");
}
else ShowForm();
mysql_close(); //zamykanie połączenia z bazą
?>
</body>
</html>

Strona obsługująca sesje

W naszej witrynie stworzymy osobny plik, w którym będzie znajdował się kod odpowiedzialny za sesje. Dołączymy go do każdego pliku(poza plikem rejestruj.php, gdyż nie było takiej potrzeby). Stwórzmy więc plik sesje.php i wpiszmy tam kod:

<?php
session_start();
session_register("zalogowany");

mysql_connect("localhost", "root", "");
mysql_select_db("test");

if(!isset($_SESSION["zalogowany"]))$_SESSION["zalogowany"]=0;

if($_POST["haslo"] && $_POST["login"]){
	$wynik=mysql_query("select * from users where user_login='".$_POST["login"]."' and user_haslo='".$_POST["haslo"]."'");
	if(!mysql_num_rows($wynik))Header("Location: index.php?err=1");
	else{
		$rekord=mysql_fetch_array($wynik);
		$_SESSION["zalogowany"]=$rekord["user_id"];
		Header("Location: index.php");
	}
}

if($_GET["ak"]=="wyl"){$_SESSION["zalogowany"]=0;Header("Location: index.php");}

function logowanie_okno($komunikat=""){
	if($komunikat)echo "<br>$komunikat<br>";
	echo "<form action='sesje.php' method=post>";
	echo "Login: <input name=login>";
	echo "<br>Hasło: <input type=password name=haslo>";
	echo "<br><input type=submit value='zaloguj'>";
	echo "</form>";
	echo "Nie masz jeszcze konta? <a href='rejestruj.php'>Zarejestruj się!</a>";
}
?>

Na początku pliku znajduje się wywołanie funkcji rozpoczynającej lub wznawiającej sesje. Następnie deklarujemy zmienną zalogowany, w której będziemy przechowywali identyfikator zalogowanego użytkownika. Po połączeni z bazą danych umieszczamy instrukcje warunkową, która sprawdza, czy zmienna sesyjna już istnieje. Jeśli nie, przypisujemy jej wartość 0, co oznacza że użytkowik nie jest zalogowany.

Kolejna instrukcja warunkowa sprawdza czy istnieją zmienne $_POST[„login”] i $_POST[„haslo”], czyli czy użytkownik próbuje się zalogować. Sprawdzamy te dane, jeśli są one poprawne, użytkownik zostaje zalogowany i przeniesiony na strone główną, w przeciwnym razie również zostanie przeniesiony do strony index.php, ale ze zmienną err przechowywującą numer błędu. Następna instrukcja warunkowa sprawdza czy w tablicy $_GET zmienna ak ma wartość wyl, co oznacza wylogowanie użytkownika. Na końcu mamy deklarację funkcji wyświetlającej formularz logowania.

Pliki pomocnicze

Nasze pliki pomocnicze to naglowek.php i stopka.php. Nazwa wskazuje na ich przeznaczenie. Oto one:

<!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" xml:lang="pl" lang="pl">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2" />
	<title>podstrona</title>
</head>
<body>
<?if(!$_SESSION["zalogowany"]){
$kom="";
if($_GET["err"]==1)$kom="Błędny login lub hasło";
logowanie_okno($kom);
require "stopka.php";
exit;
}
$ilew=mysql_num_rows(mysql_query("select wiad_id from wiadomosci where wiad_przeczytane=0 and wiad_do=".$_SESSION["zalogowany"]." and wiad_czyj=0"));
echo "<a href='odbiorcza.php'>Skrzynka odbiorcza($ilew nowych)</a> &bull; <a href='nadawcza.php'>Skrzynka nadawcza</a> &bull; <a href='newmsg.php'>Napisz nową wiadomość</a> &bull; <a href='sesje.php?ak=wyl'>Wyloguj</a>";
?>

w pliku naglowek.php widzimy nagłówek dokumentu html, oraz kod sprawdzający czy użytkownik jest zalogowany. Jeśli nie, zostanie wyświetlony formularz rejestracyjny i stopka, którą zaraz stworzymy. Jeśli jednak uzytkownik jest zalogowany, wyświetla się menu użytkownika. Na uwagę zasługuje kod:

$ilew=mysql_num_rows(mysql_query("select wiad_id from wiadomosci where wiad_przeczytane=0 and wiad_do=".$_SESSION["zalogowany"]." and wiad_czyj=0"));

Pobiera on z bazy danych liczbę nieprzeczytanych przez niego wiadomości. Plik stopka.php to bardzo prosty kod, myślę że nie potrzeba go tłumaczyć, możemy tam umieścić co nam się podoba:

<hr>
<center>stopka dokumentu</center>
</body>
</html>

Strona główna

Strona główna naszego serwisu jest bardzo prosta, składa się z kilku linijek:

<?
require "sesje.php";
require "naglowek.php";
require "stopka.php";
?>

Dołączamy tu pliki pomocnicze, oraz plik obsługujący sesje. UWAGA! Przed przyłączeniem pliku naglowek.php należy przed tym dołączyć plik sesje.php, gdyż tam znajduje się deklaracja funkcji wywołana w pliku nagłówka!

Wysyłanie wiadomości

Dodajmy teraz możliwość wysyłania wiadomości do zarejestrowanych użytkowników. Stwórzmy więc plik nadawcza.php i wpiszmy tam kod:

<?
require "sesje.php";
require "naglowek.php";

if($_POST["tresc"] && $_POST["do"] && $_POST["temat"]){
mysql_query("insert into wiadomosci values(NULL, '".$_POST["tresc"]."', ".$_SESSION["zalogowany"].", ".$_POST["do"].", 0, NOW(), '".$_POST["temat"]."', 0)");
mysql_query("insert into wiadomosci values(NULL, '".$_POST["tresc"]."', ".$_SESSION["zalogowany"].", ".$_POST["do"].", 0, NOW(), '".$_POST["temat"]."', 1)");
echo "<br><br>Wysłano wiadomość!<br>";
}
else if($_POST["submit"]){
echo "<br><br>Nie uzupełniono wszystkich pól!<br>";
}
echo "<form action='newmsg.php' method=post>";
echo "<br>Temat: <input name=temat size=30>";
echo "<br>Do kogo: <select name=do>";
$wynik=mysql_query("select user_login, user_id from users order by user_login");
while($rekord=mysql_fetch_array($wynik)){
echo "<option value=".$rekord["user_id"].">".$rekord["user_login"];
}
echo "</select><br>";
echo "Treść: <br>&lt;textarea name='tresc' rows=8 cols=50>&lt;/textarea>";
echo "<br><input type=submit value='wyślij wiadomość' name=submit>";
require "stopka.php";
?>

Na początku dołączamy niezbędny pliki. Dalej wpisujemy instrukcję warunkową sprawdzającą, czy poprawnie uzupełniono dane. Jeśli tak, wiadomość zostaje utworzona i wysłana, oraz na ekranie zostaje wyświetlony stosowny komunikat. Zwróćmy uwagę na to, że rekord z wiadomością jest tworzony dwukrotnie, i różnią się tylko ostatnią wartością, która określa właściciela wiadomości. Jest to niezbędne, jeśli chcemy stworzyć skrzynkę odbiorczą i nadawczą z opcją usuwania wiadomości. Jeśli nie dodalibyśmy pola wiad_czyj, po usunięciu wiadomości ze skrzynki odbiorczej przez odbiorce, nadawca nie miałby do niej późniejszego wglądu. Na końcu znajduje się formularz wysyłający wiadomość oraz stopka. Kod znajdujący się pomiędzy tagami <select> ułatwia odnalezienie potencjalnego odbiorce, ponieważ nazwy wszystkich użytkowników zostaną wyświetlone w liście.

Skrzynka odbiorcza

Kolejnym ważnym elementem naszego skryptu będzie skrzynka odbiorcza, w której będziemy przechowywać odebrane wiadomości, oraz odczytywać je i usuwać. W pliku odbiorcza.php zapiszmy:

<?
require "sesje.php";
require "naglowek.php";

if($_GET["id"]){
mysql_query("delete from wiadomosci where wiad_id=".$_GET["id"]);
echo "Usunięto wiadomość!<br>";
}

else if($_GET["co"]){
mysql_query("update wiadomosci set wiad_przeczytane=1 where wiad_id=".$_GET["co"]);
$wynik=mysql_query("select * from wiadomosci where wiad_id=".$_GET["co"]);
$rekord=mysql_fetch_array($wynik);
$nadawca=mysql_fetch_array(mysql_query("select user_login from users where user_id=".$rekord["wiad_od"]));
echo "<br><br><table><tr><td>Nadawca: ".$nadawca["user_login"]."</td><td>Data: ".date("d/m/Y H:i", strtotime($rekord["wiad_data"]))."</td><td><a href='odbiorcza.php?id=".$rekord["wiad_id"]."'>usuń</a></td></tr>";
echo "<tr><td colspan=3>".$rekord["wiad_temat"]."</td></tr>";
echo "<tr><td colspan=3>".$rekord["wiad_tresc"]."</td></tr>";
echo "</table>";
}

else{
$wynik=mysql_query("select * from wiadomosci where wiad_do=".$_SESSION["zalogowany"]." and wiad_czyj=0 order by wiad_data");

echo "<table><tr><td>Nadawca</td><td>Temat</td><td>Data</td><td>&nbsp;</td></tr>";
if(!mysql_num_rows($wynik))echo "<tr><td colspan=4 style='text-align:center'>Nie masz żadnych wiadomości!</td></tr>";
else while($rekord=mysql_fetch_array($wynik)){
$nadawca=mysql_fetch_array(mysql_query("select user_login from users where user_id=".$rekord["wiad_od"]));
$kw1="";$kw2="";
if(!$rekord["wiad_przeczytane"]){$kw1="<b>";$kw2="</b>";}
echo "<tr><td>".$nadawca["user_login"]."</td><td><a href='odbiorcza.php?co=".$rekord["wiad_id"]."'>$kw1".$rekord["wiad_temat"]."$kw2</td><td>".date("d/m/Y H:i", strtotime($rekord["wiad_data"]))."</td><td><a href='odbiorcza.php?id=".$rekord["wiad_id"]."'>usuń</a></td></tr>";
}
echo "</table>";
}
require "stopka.php";
?>

Pierwszy warunek sprawdza, czy zmienna $_GET[„id”] nie jest pusta. Przechowywuje ona identyfikator wiadomości do usunięcia. Jeśli nie jest ona pusta, następuje usunięcie wiadomości o podanym identyfikatorze i wyświetlenie komunikatu o wykonanej czynności. Kolejny warunke sprawdza, czy zmienna $_GET[„co”] przechowuje jakąś wartość. W zmiennej tej znajduje się identyfikator wiadomości, której treść należy wyświetlić. Wykonywany jest wtedy prawie ten sam kod, który jest wykonywany, jeśli żaden z warunków nie jest spełniony, z tą różnicą, że w drugim przypadku kod wykonywany jest tak długo, aż każda wiadomość zostanie wyświetlona. Kolejna różnica między kodami polega na tym, że w kodzie który wyświetla pojedynczą wiadomość, wyświetlana jest również treść wiadomości.

Skrzynka nadawcza

Kod strony która będzie wyświetlać wysłane przez nas wiadomości jest prawie identyczny jak kod skrzynki odbiorczej, więc nie będziemy go analizować, zwrócę tylko uwagę na różnice między dwoma kodami. Źródło pliku nadawcza.php

<?
require "sesje.php";
require "naglowek.php";

if($_GET["id"]){
mysql_query("delete from wiadomosci where wiad_id=".$_GET["id"]);
echo "Usunięto wiadomość!<br>";
}

else if($_GET["co"]){
$wynik=mysql_query("select * from wiadomosci where wiad_id=".$_GET["co"]." and wiad_czyj=1");
$rekord=mysql_fetch_array($wynik);
$odbiorca=mysql_fetch_array(mysql_query("select user_login from users where user_id=".$rekord["wiad_do"]));
echo "<br><br><table border=1><tr><td>Odbiorca: ".$odbiorca["user_login"]."</td><td>Data: ".date("d/m/Y H:i", strtotime($rekord["wiad_data"]))."</td><td><a href='odbiorcza.php?id=".$rekord["wiad_id"]."'>usuń</a></td></tr>";
echo "<tr><td colspan=3>Temat: ".$rekord["wiad_temat"]."</td></tr>";
echo "<tr><td colspan=3>".$rekord["wiad_tresc"]."</td></tr>";
echo "</table>";
}

else{
$wynik=mysql_query("select * from wiadomosci where wiad_od=".$_SESSION["zalogowany"]." and wiad_czyj=1 order by wiad_data ");
echo "<table><tr><td>Odbiorca</td><td>Temat</td><td>Data</td><td>&nbsp;</td></tr>";
if(!mysql_num_rows($wynik))echo "<tr><td colspan=4 style='text-align:center'>Nie masz żadnych wiadomości!</td></tr>";
else while($rekord=mysql_fetch_array($wynik)){
$odbiorca=mysql_fetch_array(mysql_query("select user_login from users where user_id=".$rekord["wiad_do"]));
echo "<tr><td>".$odbiorca["user_login"]."</td><td><a href='nadawcza.php?co=".$rekord["wiad_id"]."'>".$rekord["wiad_temat"]."</td><td>".date("d/m/Y H:i", strtotime($rekord["wiad_data"]))."</td><td><a href='nadawcza.php?id=".$rekord["wiad_id"]."'>usuń</a></td></tr>";
}
echo "</table>";
}
require "stopka.php";
?>

Różnica jest tylko jedna, polega ona na zmianie warunku

where wiad_czyj=0

na

wiad_czyj=1

, co spowoduje wyświetlenie wiadomości wysłanych.

Zakończenie

Tak dotarliśmy do końca. Stworzyliśmy system wysyłania prywatnych wiadomości. Teraz część na smutną wiadomość. Skrypt który stworzyliśmy praktycznie nie nadaje się do użytku. Możemy mieć wgląd do wszystkich wiadomości, nie znając hasła nadawcy ani odbiorcy. Jednak aby nasza praca nie poszła na marne, przygotowałem zabezpieczony skrypt. Pewnie teraz zapytacie, dlaczego od razu go nie zabezpieczałem? Powód: nie chciałem, żeby to przysłoniło główny temat tego artykułu. Zabezpieczony kod znajduje się w archiwum zip.

Marcin 'loganek' Kolny

Osoby czytające tę publikację przeglądały również:

Chcesz zostać programistą?

Poznaj 6 kroków do efektywnej
nauki programowania!

 

valid XHTML
valid CSS
© 2004-2008 copyright by webmade.org