Data dodania: 2 wrzesień 2011r.
Ostatnie poprawki: 15 wrzesień 2011r.
W tym artykule chciałbym zaprezentować Wam napisany przeze mnie system komentarzy, na potrzeby tej strony. Jednak starałem się, aby był uniwersalny i dobry na każdą. System opiera się oczywiście o bazy danych MySQL. Celem tego systemu komentarzy była wygoda i prostota użytkowania. Rozwiązałem to w ten sposób, że w pliku, gdzie chcemy mieć możliwość skomentowania np. artykuły, wystarczy tylko wywołać jedną funkcję. Cały silnik systemu jest w tejże funkcji. Skrypt rozpoznaje, które komentarze ma wyświetlić na podstawie nazwy pliku, gdzie jest wywoływana funkcja. Ma to taką wadę, że na jednej podstronie możemy tylko jedną rzecz komentować. Z drugiej strony, nie wymyśliłem, jak inaczej można by identyfikować artykuł bez potrzeby przekazywania parametru do funkcji (mogłyby się zdarzyć duble etc.).
Na początku trzeba oczywiście utworzyć tabele w bazie danych. W pierwszej z nich przechowywać będziemy wszystkie komentarze, a w drugiej adresy IP, aby ochronić nasz skrypt przed spamem. Trzecia tabela zawiera login i hasło admina.
Listing 1.1 – stworzenie potrzebnych tabel w bazie danych
CREATE TABLE komentarze ( id int(11) NOT NULL auto_increment PRIMARY KEY, podstrona tinytext NOT NULL, nick char(40) NOT NULL, email tinytext, www tinytext, tresc text NOT NULL, data int(11) NOT NULL ); CREATE TABLE komentarze_ip ( id int UNSIGNED NOT NULL auto_increment PRIMARY KEY, numer char(20) NOT NULL, podstrona tinytext NOT NULL, ostatni_wpis int(10) unsigned NOT NULL ); CREATE TABLE admin ( id int(10) unsigned NOT NULL auto_increment PRIMARY KEY, login tinytext NOT NULL, haslo char(40) NOT NULL );
Trzeba także wprowadzić dane administratora, abyśmy mogli zarządzać komentarzami – usuwać je, tudzież edytować. Polecenie jest chyba oczywiste, ale podam:
Listing 1.2 – wprowadzenie przykładowych danych administratora do bazy danych
INSERT INTO admin VALUES(NULL, 'Testowy', sha1('haslo'));
W każdym pliku, gdzie używamy tego systemu komentarzy, musimy połączyć się z bazą danych MySQL. Najlepiej stworzyć plik, gdzie będą wszystkie polecenia, i includować go na każdej z podstron. W paczce do pobrania na końcu artykułu ten plik nosi nazwę mysql_connect.php. Ten kod może wyglądać np. tak:
Listing 2 – utworzenie połączenia z bazą danych
<?php
$db = mysql_connect("localhost", "root", "") or die ("Nie można połączyć się z bazą danych...");
mysql_select_db("cms") or die ("Nieznana baza danych!");
mysql_query("SET NAMES utf8");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET collation_connection = utf8_polish_ci");
?>
W pliku config.php znajdują się podstawowe informacje dla skryptu, które trzeba indywidualnie uzupełnić wedle nazw tabel stworzonych przed chwilą (być może, ktoś nadał im inne nazwy, niż ja). Tutaj także ustawiamy jak długi ma być czas między wysłaniem komentarzy przez użytkownika w jednym artykule, aby uniemożliwić spam.
Listing 3 – konfiguracja ważnych danych
<?php // nick administratora $nick_admin = 'Testowy'; // nazwa tabeli z komentarzami $tabela_komentarze = 'komentarze'; // nazwa tabeli z adresami IP $tabela_adresyip = 'komentarze_ip'; // nazwa tabeli z danymi admina $tabela_admin = 'admin'; // na ile minut ma byc nalozony filtr czasu $ilosc_minut = 10; // adres email administratora $email_admin = 'twoj96@email.pl'; ?>
Teraz przyjrzyjmy się funkcjom, które umieściłem w pliku funkcje.php. Na samym jego początku includujemy plik config.php, a następnie pobierane są dane o aktualnej podstronie. Pamietajmy, aby wszędzie, gdzie uzywamy tego skryptu, includować plik z funkcjami – na każdej podstronie, gdzie korzystamy z tej funkcji oraz w każdym pliku tego systemu (pliku logowania, dodawania komentarza itd.).
Listing 4.1 funkcje.php – pobieranie danych o aktualnej podstronie
<?php
include('config.php');
// dane o aktualnej podstronie
$podstrona = pathinfo($_SERVER['SCRIPT_FILENAME']);
$nazwa = $podstrona['filename'];
$plik = $podstrona['basename'];
Następnie tworzone są funkcje Error() i Correct(), które będą potem bardzo często używane podczas powodzenia i niepowodzenia. Funkcje te przybierają dwa parametry – pierwszy to ciąg, który ma zostać wyświetlony po jej wywołaniu, a drugi, opcjonalny, to numer, zależnie od którego link powrotny przybiera inny adres. Domyślnie jest to numer 0 i odnośnik do podstrony na której przebywamy, jednak podczas używania skryptu komentarzy najczęściej będziemy używać numeru 2, czyli przenosin do poprzedniej podstrony, gdzie wyświetlane są komentarze (zmienna $_SESSION['poprzednia'] będzie inicjowana podczas wywoływania funkcji Komentarze(), o czym dalej).
Listing 4.2 funkcje.php – deklarowanie funkcji Error i Correct
function Error($tekst, $podstrona = 0)
{
global $plik;
if($podstrona == 0)
{
$odsylacz = $plik;
}
else if($podstrona == 1)
{
$odsylacz = 'index.php';
}
else if($podstrona == 2)
{
$odsylacz = $_SESSION['poprzednia']."#komentarze";
}
echo "\n\n<p class=\"error\">".$tekst." <a href=\"".$odsylacz."\">Powrót</a></p>\n\n";
// wyswietlenie przed zakonczeniem skryptu stopki strony
include('foot.php');
exit;
}
function Correct($tekst, $podstrona = 0)
{
global $plik;
if($podstrona == 0)
{
$odsylacz = $plik;
}
else if($odsylacz == 1)
{
$odsylacz = 'index.php';
}
else if($podstrona == 2)
{
$odsylacz = $_SESSION['poprzednia']."#komentarze";
}
echo "<p class=\"correct\">".$tekst." <a href=\"".$odsylacz."\">Powrót</a></p>";
// wyswietlenie przed zakonczeniem skryptu stopki strony
include('foot.php');
exit;
}
Teraz musimy przygotować funkcję, która będzie odpowiedzialna o niedopuszczenie do zbyt częstych komentarzy tego samego artykułu z tego samego numeru IP, aby zabezpieczyć nasz system komentarzy przed spamem.
Listing 4.2 funkcje.php – filtrCzasu() – funkcja mająca na celu powstrzymanie spamu
function filtrCzasu()
{
global $tabela_adresyip;
global $ilosc_minut;
$aktualna = $_SESSION['aktualna'];
$adres_ip = $_SERVER['REMOTE_ADDR'];
$zapytanie = "SELECT * FROM $tabela_adresyip WHERE numer='$adres_ip' AND podstrona='$aktualna'";
$wynik = mysql_query($zapytanie);
$wpis = mysql_fetch_assoc($wynik);
// jesli dodano do tego artykulu z tego samego numeru ip wpis przed uplywem okreslonego czasu to wyrzuc blad
if($wpis['ostatni_wpis'] > time())
{
// obliczanie ile czasu trzeba jeszcze odczekac by dodac komentarz
$ilosc = $wpis['ostatni_wpis'] - time();
$czas = $ilosc / 60;
$czas = (integer)$czas;
Error("Nie możesz dodać tak szybko drugiego wpisu. Poczekaj ".$czas." minut(y) i spróbuj ponownie.", 2);
}
else
{
// jesli nie, towybierz odpowiednie zapytanie i wlslij je do bazy danych
$ile = mysql_num_rows($wynik);
$czas = time() + ($ilosc_minut * 60);
if($ile > 0)
{
// jesli w bazie danych jest juz ten numer IP z ta podstrona to nadpisz tylko czas dodawanego wpisu
$query = "UPDATE $tabela_adresyip set ostatni_wpis='$czas' WHERE numer='$adres_ip' AND podstrona='$aktualna'";
}
else
{
// jesli w bazie danych nie ma tego numeru IP z ta podstrona to dodaj go
$query = "INSERT INTO $tabela_adresyip VALUES (NULL, '$adres_ip', '$aktualna', '$czas')";
}
if(!mysql_query($query))
{
Error("Wystąpiły problemy podczas dodawania komentarza, spróbuj ponownie później.", 2);
}
}
}
Wydaje mi się, że w komentarzach jest wystarczająco szczegółowo ta funkcja opisana. Zajmijmy się teraz wyświetlaniem komentarzy.
Aby link do zewnętrznej strony internetowej 'działał', musi mieć prefiks http://. Gdy komentujący podał stronę internetową, ale nie wpisał przed nią tego prefiksu, ta funkcja go doda.
Listing 4.3 funkcje.php – funkcja dodająca prefiks 'http://' do linków, gdy go nie podano
function dodajPrefiks($www)
{
$pos = strpos($www, 'http://');
if($pos !== 0)
{
$www = 'http://'.$www;
}
return $www;
}
Wszystko starałem się opisać w komentarzach do kodu, ale może streszczę tylko co po kolei się dzieje. Najpierw funkcja tworzy odpowiednie zmienne, potrzebne do dalszej pracy. Tutaj widać dwie zmienne sesji – 'poprzednia' i 'aktualna'. Nazwy może trochę mylące, jednak nie do końca. W 'poprzedniej' mamy nazwę pliku, w którym wywołujemy funkcję (z rozszerzeniem), potrzebną, gdy faktycznie wyszliśmy z tego artykułu i chcemy do niego wrócić. 'Aktualna' jest w zasadzie dla admina. Gdy przechodzimy do innego pliku by usunąć bądź zedytować plik, to faktycznie jest to aktualnie obrabiana podstrona, tyle, że bez rozszerzenia, bo w bazie danych właśnie w takiej postaci przypisujemy komentarze do właściwej podstrony. Następnie, jeśli użytkownik chce dodać komentarz, wyświetlany jest formularz jego dodania. Na końcu pobierane są wszystkie komentarze do tego właśnie artykułu i są one wyświetlane. Jeśli nie ma żadnych komentarzy do wyświetlenia, echowana jest stosowna informacja.
Listing 4.4 funkcje.php – główny silnik systemu – funkcja Komentarze()
function Komentarze()
{
// korzystanie ze zmiennych globalnych, utworzonych na poczatku tego pliku
global $nazwa;
global $plik;
global $tabela_komentarze;
global $nick_admin;
// przekazanie do zmiennej sesji nazwy ostatniego pliku, gdzie uzyto tej funkcji
$_SESSION['poprzednia'] = $plik;
// przekazanie do zmiennej sesji nazwy tego pliku bez .php
$_SESSION['aktualna'] = $nazwa;
if($_GET['id'] == 'add')
{
echo "
<form id=\"dodaj_komentarz\" action=\"dodaj.php\" method=\"post\">
<fieldset>
<legend>Dodaj komentarz</legend>
<div id=\"left\">
<label>Nick: <span>*</span>
<input type=\"text\" name=\"nick\" />
</label>
<label>Email: <span class=\"hover\">(nie będzie wyświetlany)</span>
<input type=\"text\" name=\"email\" />
</label>
<label>Strona internetowa:
<input type=\"text\" name=\"www\" />
</label>
</div>\n
<div id=\"right\">
<label>Treść: <span>*</span>
<textarea name=\"tresc\"></textarea>
</label>
</div>
<input class=\"wyslij\" type=\"submit\" value=\"OK\" />
<a id=\"zwin\" href=\"".$plik."#komentarze\">⇓</a>
</fieldset>
</form>";
}
$zapytanie = "SELECT * FROM $tabela_komentarze WHERE podstrona='$nazwa' ORDER BY id DESC";
$komentarze = mysql_query($zapytanie);
$ile = mysql_num_rows($komentarze);
// jesli sa jakies komentarze to je wysiwtl, w porzadku malejacym
if($ile > 0)
{
echo "\n\n<a id=\"dodajKomentarz\" href=\"".$plik."?id=add#dodaj_komentarz\">Dodaj komentarz</a>\n\n";
echo "<ul id=\"komentarze\">";
for($i = 0; $i < $ile; $i++)
{
$komentarz = mysql_fetch_assoc($komentarze);
$data = date('d F Y, H:i', $komentarz['data']);
echo "<li id=\"k".$komentarz['id']."\"";
// jesli to komentarz admina, to wyroznij go
if($komentarz['nick'] == $nick_admin)
{
echo " class=\"ja\"";
}
echo " >";
// jesli jestes zalogowany to pokaz opcje usuwania i edycji komentarza
if(isset($_SESSION['prawdziwy']))
{
echo "<ul id=\"admin\">\n<li>\n<a href=\"usun.php?id=".$komentarz['id']."\">Usuń komentarz</a>\n</li>\n<li>\n<a href=\"edytuj.php?id=".$komentarz['id']."\">Edytuj komentarz</a></li>\n</ul>\n\n";
}
echo "<ul id=\"dane\">\n<li class=\"nick\">".stripslashes($komentarz['nick'])."</li>\n";
echo "<li class=\"data\">".$data."</li>\n";
// jesli admin jest zalogowany to pokaz email (normalnie niewidoczny)
if(isset($_SESSION['prawdziwy']))
{
if(strlen($komentarz['email']) > 5)
{
echo "<li><a href=\"mailto:".$komentarz['email']."\">".$komentarz['email']."</a></li>\n";
}
}
// jesli strona internetowa zostala podana to ja wyswietl
if(strlen($komentarz['www']) > 10)
{
echo "<li><a href=\"".$komentarz['www']."\">Strona internetowa</a></li>\n";
}
echo "\n</ul>\n\n";
echo "<p>".stripslashes($komentarz['tresc'])."</p>\n\n";
echo "</li>";
}
echo "</ul>";
}
// jesli nie ma zadnych komentarzy to wyswietl stosowna informacje
else
{
echo "<p id=\"pusto\">Nie ma jeszcze komentarzy. <a href=\"".$plik."?id=add#dodaj_komentarz\">Dodaj komentarz</a></p>\n\n";
}
}
?>
Formularz dodawania komentarza prowadzi nas do pliku dodaj.php, gdzie odbywa się dodawanie komentarza. Jeśli przyszły jakieś dane metodą POST, to skrypt rozpoczyna właściwe działanie. Najpierw filtruje, czy użytkownik uzupełnił wszystkie obowiązkowe pola (tutaj nick i treść), a gdy wszystko jest w porządku, sprawdza jeszcze funkcją filtrCzasu(), czy upłynął określony czas, po którym można dodać drugi komentarz pod tym samym artykułem. Gdy wszystko jest w porządku tworzone jest odpowiednie zapytanie do bazy danych, po czym zostaje ono wykonane. Jeśli zapytanie wykonało się poprawnie to otrzymujemy pomyślny komunikat. Jeśli nie, to skrypt oczywiście informuje, że coś poszło nie tak.
Listing 5 dodaj.php – kod, który dodaje komentarz, o ile przyszły jakieś dane metodą $_POST
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
$nick = mysql_real_escape_string(htmlspecialchars(trim($_POST['nick'])));
$email = trim($_POST['email']);
$www = trim($_POST['www']);
$tresc = mysql_real_escape_string(nl2br(htmlspecialchars(trim($_POST['tresc']))));
if(strlen($nick) < 1)
{
Error("Przedstaw się.", 2);
}
if(strlen($nick) > 40)
{
Error("Sorry, ale nick może mieć maksymalnie 40 znaków, ze względów czysto estetycznych...", 2);
}
// jeśli administrator nie jest zalogowany, nie można się podpisywac jego nickkiem
if(!isset($_SESSION['prawdziwy']) && $nick == $nick_admin)
{
Error("Nie podszywaj się pod administratora!", 2);
}
if(!ereg('^[a-zA-Z0-9_]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$', $email) && strlen($email) > 0)
{
Error("Niepoprawny adres e-mail", 2);
}
else if(strlen($email) < 5)
{
$email = '';
}
if(!ereg('^[a-zA-Z0-9\-\.]+\.[a-zA-Z0-9]+$', $www) && strlen($www) > 0)
{
Error("Niepoprawny adres strony internetowej.", 2);
}
else if(strlen($www) < 5)
{
$www = '';
}
else
{
$www = dodajPrefiks($www);
}
if(strlen($tresc) < 10)
{
Error("Napisz coś treściwszego...", 2);
}
// pobieranie nazwy podstrony, na której dodano komentarz
$nazwa = $_SESSION['aktualna'];
filtrCzasu();
$zapytanie = "INSERT INTO $tabela_komentarze VALUES(NULL, '$nazwa', '$nick', '$email', '$www', '$tresc', ".time().")";
if(mysql_query($zapytanie))
{
// jesli to admin dodal komentarz - nie wysylaj powiadomienia
if($nick != $nick_admin)
{
mail($email_admin, 'Nowy komentarz!', "$nick skomentowal artykuł na podstronie $nazwa!\n\nTresc komentarza:\n$tresc");
}
Correct("Poprawnie dodano komentarz!", 2);
}
else
{
Error("Wystąpiły problemy podczas dodawania komentarza, spróbuj ponownie później.", 2);
}
}
?>
System komentarzy wyposażony jest, oczywiście, w możliwość kasowania i edycji komentarzy. Aby móc z nich skorzystać trzeba się oczywiście zalogować. W tym celu należy przejść do pliku, gdzie umieścimy sobie formularzyk logowania, u mnie to jest zaloguj.php. Kod jest bardzo prosty, jednak wydaje mi się, że wystarczająco bezpieczny.
Listing 6 zaloguj.php – skrypt pozwalający na zalogowanie się do systemu komentarzy
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
$login = mysql_real_escape_string(trim($_POST['login']));
$haslo = sha1($_POST['haslo']);
$zapytanie = "SELECT * FROM $tabela_admin WHERE login='$login' AND haslo='$haslo'";
$wynik = mysql_query($zapytanie);
$ile = mysql_num_rows($wynik);
if($ile > 0)
{
$_SESSION['prawdziwy'] = $login;
Correct("Zalogowano poprawnie", 2);
}
else
{
Error("Nieprawidłowe dane logowania...");
}
}
else
{
echo "
<form id=\"logowanie\" action=\"zaloguj.php\" method=\"post\">
<fieldset>
<legend>Logowanie</legend>
<h2>Logowanie</h2>
<label>
Login:
<input type=\"text\" name=\"login\" />
</label>
<label>
Hasło:
<input type=\"password\" name=\"haslo\" />
</label>
<input type=\"submit\" class=\"wyslij\" value=\"OK\" />
<a id=\"powrot\" href=\"index.php\"><< Powrót</a>
</fieldset>
</form>";
}
?>
Jeśli już się zalogowaliśmy to oczywiście musi być też możliwość wylogowania. Oto potrzebny, krótki kod (u mnie jest on w pliku wyloguj.php):
Listing 7 wyloguj.php – kod, dzięki któremu można się wylogować
<?php
$stary = $_SESSION['prawdziwy'];
unset($_SESSION['prawdziwy']);
session_destroy();
if(!empty($stary))
{
Correct("Wylogowano poprawnie.", 2);
}
?>
Zawsze znajdzie się jakiś jegomość który albo napisze coś głupiego, wulgarnego, tudzież nic, a raczej coś w stylu „kjfdskfj kl;fjkl js kfklkl sjdfsd klfjkl”. Admin ma oczywiście możliwość usuwania takich „komentarzy”. Po zalogowaniu, przy każdym wpisie są dwa linki: usuń komentarz i edytuj komentarz. Zajmijmy się teraz usuwaniem komentarzy. Link prowadzi nas do osbnego pliku, usun.php. Kod usuwania komentarza wygląda następująco:
Listing 8 usun.php – przechodząc na tą podstronę można usunąć komentarz o id przesyłanym metodą $_GET
<?php
if(isset($_SESSION['prawdziwy']))
{
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
if($_POST['wybor'] == 'tak')
{
$zapytanie = "DELETE FROM $tabela_komentarze WHERE id=".$_GET['id']."";
if(mysql_query($zapytanie))
{
Correct("Poprawnie usunięto komentarz", 2);
}
}
}
else
{
$id = $_GET['id'];
echo "
<form id=\"usuwanie\" action=\"$plik?id=$id\" method=\"post\">
<fieldset>
<legend>
Na pewno chcesz usunąć ten komentarz?
</legend>
<h2>Na pewno chcesz usunąć ten komentarz?</h2>
<input type=\"hidden\" name=\"wybor\" value=\"tak\" />
<button type=\"submit\">Tak</button>
<a id=\"nie_usuwaj\" href=\"".$_SESSION['poprzednia']."\">Nie</a>
</fieldset>
</form>
";
}
}
else
{
Error("Nie masz uprawnień by usuwać komentarze", 2);
}
?>
Nie będę się rozpisywać, bo zasada działania jest podobna jak podczas dodawania komentarza, tyle, że nie ma tak rygorystycznych filtrów (w końcu to strona admina, więc…). Skrypt wyrzuca nam formularzyk z zawartością, którą możemy dowolnie modyfikować.
Listing 9 edytuj.php – dzięki poniższemu kodowi, o ile jest się zalogowanym, można edytować komentarze
<?php
if(isset($_SESSION['prawdziwy']))
{
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
$nick = mysql_real_escape_string(trim($_POST['nick']));
$email = trim($_POST['email']);
$www = trim($_POST['www']);
$tresc = mysql_real_escape_string(nl2br(trim($_POST['tresc'])));
if(strlen($www) > 5)
{
$www = dodajPrefiks($www);
}
$zapytanie = "UPDATE $tabela_komentarze set nick='$nick', email='$email', www='$www', tresc='$tresc' WHERE id=".$_GET['id'];
if(mysql_query($zapytanie))
{
Correct("Poprawnie zmodyfikowano komentarz", 2);
}
else
{
Error("Wystąpił błąd podczas edycji komentarza", 2);
}
}
else
{
$id = $_GET['id'];
$zapytanie = "SELECT * FROM $tabela_komentarze WHERE id=".$id;
$wynik = mysql_query($zapytanie);
$edytuj = mysql_fetch_assoc($wynik);
echo "
<form id=\"dodaj_komentarz\" action=\"$plik?id=$id\" method=\"post\">
<fieldset>
<legend>Edytuj komentarz</legend>
<h2>Edytuj komentarz</h2>
<div id=\"left\">
<label>Nick: <span>*</span>
<input type=\"text\" name=\"nick\" value=\"".stripslashes($edytuj['nick'])."\" />
</label>
<label>Email: <span class=\"hover\">(nie będzie wyświetlany)</span>
<input type=\"text\" name=\"email\" value=\"".$edytuj['email']."\" />
</label>
<label>Strona internetowa:
<input type=\"text\" name=\"www\" value=\"".$edytuj['www']."\" />
</label>
</div>\n
<div id=\"right\">";
$tresc = stripslashes($edytuj['tresc']);
$tresc = str_replace("<br />", "", $tresc);
echo "<label>Treść: <span>*</span>
<textarea name=\"tresc\">".$tresc."</textarea>
</label>
</div>
<input class=\"wyslij\" type=\"submit\" value=\"OK\" />
<a id=\"powrot\" href=\"".$_SESSION['poprzednia']."#komentarze\"><< Powrót</a>
</fieldset>
</form>";
}
}
else
{
Error("Nie masz uprawnień by edytować komentarze.", 2);
}
?>
Arkusz stylów CSS pod moją stronę wygląda następująco. Jednak każdy musi go sobie dostosować pod własną.
Listing 10 style.css – plik z domyślnymi stylami CSS dla tego systemu komentarzy
* {
margin: 0;
padding: 0;
}
html {
background: url('img/tlo_top.png') repeat-x #2e2e2e;
}
body {
width: 700px;
margin: 30px auto;
font-size: 12px;
font-family: Verdana;
color: #eee;
}
a {
color: #c4c4c4;
text-decoration: none;
font-weight: bold;
}
a:hover {
color: #db7f13;
}
h1 {
font-family: Times New Roman;
font-weight: normal;
letter-spacing: 2px;
text-align: center;
font-size: 40px;
color: #c4c4c4;
margin: 0 0 40px 0;
}
h2 {
text-align: center;
font-size: 34px;
font-weight: normal;
font-family: Times New Roman;
letter-spacing: 2px;
}
h3 {
text-align: center;
font-size: 26px;
font-weight: normal;
font-family: Georgia;
letter-spacing: 2px;
margin: 5px 0 0 0;
}
p {
text-indent: 40px;
text-align: justify;
line-height: 18px;
margin: 20px 0;
}
.error, .correct {
text-indent: 0;
padding: 20px;
width: 600px;
margin: 50px auto;
}
.error {
border: 5px solid #900;
}
.correct {
border: 5px solid #090;
}
#foot {
text-align: center;
margin: 30px 0 0 0;
line-height: 18px;
}
#foot a#wykonanie {
background: url('img/wykonanie.png') no-repeat;
padding: 1px 0 2px 28px;
}
#pusto {
width: 400px;
padding: 40px;
text-align: center;
background: #222;
border: 1px solid #000;
clear: both;
margin: 50px auto 0 auto;
}
/***** FORMULARZE *****/
#dodaj_komentarz legend,
#logowanie legend,
#usuwanie legend {
display: none;
}
#dodaj_komentarz fieldset,
#logowanie fieldset,
#usuwanie fieldset {
display: block;
overflow: hidden;
width: 550px;
margin: 20px auto;
padding: 20px 30px;
border: 1px solid #000;
background: #292929;
position: relative;
}
#dodaj_komentarz label,
#logowanie label,
#usuwanie label {
display: block;
margin: 15px 0;
clear: both;
}
#dodaj_komentarz input, #dodaj_komentarz textarea,
#logowanie input,
#usuwanie input, #usuwanie textarea {
display: block;
margin: 5px 0 0 0;
padding: 2px;
background: #2e2e2e;
border: 1px solid #050505;
color: #eee;
}
#dodaj_komentarz input,
#logowanie input,
#usuwanie input {
width: 194px;
}
#dodaj_komentarz textarea,
#logowanie textarea,
#usuwanie textarea {
height: 130px;
width: 320px;
}
form #left {
float: left;
}
form #right {
float: right;
}
#dodaj_komentarz input:focus, #dodaj_komentarz textarea:focus,
#logowanie input:focus, #logowanie textarea:focus,
#usuwanie input:focus, #usuwanie textarea:focus {
background: #222;
border-color: #050505;
}
#dodaj_komentarz span {
color: #900;
}
#dodaj_komentarz span.hover {
color: #444;
visibility: hidden;
}
#dodaj_komentarz label:hover #dodaj_komentarz span.hover {
visibility: visible;
}
#dodaj_komentarz input.wyslij,
#logowanie input.wyslij {
background: url('img/button.png') repeat-x top left;
border: 1px solid #050505;
margin: 30px auto 0 auto;
font-size: 15px;
font-family: Georgia;
font-style: italic;
color: #c4c4c4;
width: 100px;
letter-spacing: 3px;
display: block;
padding: 0;
height: 32px;
line-height: 32px;
text-align: center;
font-weight: bold;
clear: both;
}
input.wyslij:hover, input.wyslij:focus {
background-position: 0 -30px;
background-color: #222;
cursor: pointer;
}
#dodaj_komentarz h2,
#logowanie h2,
#usuwanie h2 {
margin: 0 0 20px 0;
}
#usuwanie fieldset {
width: 350px;
}
#usuwanie h2 {
font-size: 20px;
}
#usuwanie button {
float: left;
clear: none;
}
#usuwanie #nie_usuwaj {
float: right;
clear: none;
}
button, #nie_usuwaj {
display: block;
background: url('img/button.png') repeat-x top left;
border: 1px solid #050505;
margin: 0 auto 0 auto;
font-size: 15px;
color: #c4c4c4;
width: 100px;
letter-spacing: 3px;
display: block;
padding: 0;
height: 30px;
line-height: 30px;
text-align: center;
font-weight: bold;
clear: both;
}
button:hover, button:focus, #nie_usuwaj:hover, #nie_usuwaj:focus {
background-position: 0 -30px;
background-color: #222;
cursor: pointer;
}
#logowanie fieldset {
width: 350px;
}
#logowanie label {
width: 200px;
margin: 20px auto;
}
/***** LINKI *****/
#zwin {
font-size: 12px;
position: absolute;
bottom: -20px;
right: 40px;
}
#dodajKomentarz {
display: block;
text-align: right;
margin: 0 40px -15px 0;
}
/***** AKAPITY *****/
.error, .correct {
text-indent: 0;
padding: 20px;
width: 600px;
margin: 50px auto;
}
.error {
border: 5px solid #900;
}
.correct {
border: 5px solid #090;
}
#pusto {
width: 400px;
padding: 40px;
text-align: center;
background: #222;
border: 1px solid #000;
clear: both;
margin: 50px auto 0 auto;
text-indent: 0;
}
/***** LISTY *****/
ul#komentarze li {
list-style-type: none;
background: #2a2a2a;
border: 1px solid #1a1a1a;
padding: 20px;
margin: 20px auto;
overflow: hidden;
width: 620px;
}
ul#komentarze li.ja {
background: #222;
border: 1px solid #000;
margin: 20px 0;
}
ul#komentarze li p {
float: right;
width: 410px;
text-indent: 40px;
margin: 0;
text-align: justify;
line-height: 18px;
font-size: 11px;
}
ul#komentarze li ul#dane {
float: left;
width: 200px;
}
ul#komentarze li ul#dane li {
background: none;
border: 0;
padding: 0;
margin: 10px 0;
overflow: auto;
}
ul#komentarze li ul#dane li.nick {
font-size: 14px;
font-weight: bold;
color: #ddd;
margin: 0 0 5px 0;
}
ul#komentarze li ul#dane li.data {
color: #444;
font-size: 9px;
margin: 0 0 15px 0;
}
ul#komentarze a {
font-weight: normal;
color: #6a6a6a;
font-size: 11px;
}
ul#komentarze a:hover {
color: #eee;
}
ul#admin {
margin: -10px 0 5px 0;
}
ul#admin li {
border: 0;
background: none;
margin: 0;
padding: 0;
}
Na początku każdego pliku musimy wywołać sesję i ew. jej zabezpieczenie. Najlepiej includować odpowiedni kod na początku każdego pliku. Przykładowa podstrona z użyciem tego systemu komentarzy może wyglądać np. tak:
Listing 11 – tak może wyglądać plik z uzyciem tego systemu komentarzy
<!-- czesc includowana z pliku np. head.php-->
<?php session_start();
if (!isset($_SESSION['inicjuj']))
{
session_regenerate_id();
$_SESSION['inicjuj'] = true;
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
}
if($_SESSION['ip'] != $_SERVER['REMOTE_ADDR'])
{
die('Próbowano przejąc sesję, co się nie udało.!');
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>System komentarzy MySQL</title>
<link rel="stylesheet" href="komentarze.css" type="text/css" />
</head>
<body>
<!-- koniec czesci includowanej z pliku np. head.php-->
<h1>Lorem Ipsum</h1>
<h2>What is Lorem Ipsum?</h2>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
<h2>Why do we use it?</h2>
<p>
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
</p>
<h2>What does it come from?</h2>
<p>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
</p>
<p>
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
</p>
<h2>Where can I get some?</h2>
<p>
There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
</p>
<h2>Komentarze</h2>
<?php
include('mysql_connect.php');
include('funkcje.php');
Komentarze();
?>
<!-- czesc includowana z pliku np. foot.php-->
<p id="foot">
<a id="wykonanie" href="http://filipmarkiewicz.boo.pl">Filip Markiewicz</a>.<br />
<?php
if(isset($_SESSION['prawdziwy']))
{
echo "Zalogowany jako ".$_SESSION['prawdziwy']." (<a href=\"wyloguj.php\">Wyloguj</a>)";
}
else
{
echo "<a href=\"zaloguj.php\">Zaloguj</a>";
}
?>
</p>
</body>
</html>
<!-- koniec czesci includowanej z pliku np. foot.php-->
Mam ogromną nadzieję, że komuś przyda się ten artykuł, albo chociaż pojedyncze jego fragmenty. Zdaję sobie sprawę, że kod PHP/MySQL nie jest idealny, jednak dopiero się uczę. Wszystkie pliki mozna ściągnąc stąd. Demo możecie obejrzeć i przetestować poniżej, do czego zachęcam.
A powinno przyjmować tak zapisany adres strony?
Popraw sprawdzanie adresu strony, bo w stylu http://(www.)strona.pl nie przyjmuje. BTW sam do swojego komentarza dałeś błędny adres ;)
Na razie nie testowałem, ale na pewno to zrobię ;) Teraz męczę się z systemem newsów na moją stronę, potem wypróbuję te Twoje komentarze ;)
Dzięki za komentarze :). Tay, w wakacje wreszcie było trochę czasu, to przysiadłem ;). A tak w ogóle to artykuł jest w miarę zrozumiały?
Btw. Testowaliście to może u siebie na local'u, albo na jakiejś swojej stronie? Nie wiem czy wszystkie pliki dobrze zgrałem/czy kody dobrze wkleiłem do artykułu etc.
PS. Dodałem informowanie o nowych komentarzach na maila.
Siwy, podziwiam Cię ;) Ja nie mam siły, aby przysiąść nad PHP i porządnie się czegoś nauczyć, a Ty już takie rzeczy robisz! Dobra robota ;)
Łał, naprawdę niezła robota. Oby tak dalej!
© Filip Markiewicz Mapa strony Spis moich monet II RP XHTML 1.0 CSS 2.1