Chyba każda odsłona kursu php w strefie omawiała budowę skryptu systemu do obsługi nowości na stronie, więc i ja nie będę się wyłamywał ;). Jak zwykle całość działa na plikach więc nie będzie problemów z obsługą baz danych. Do poprawnego działania wystarczy samo PHP i nieco chęci.
Struktóra pliku z newsami będzie bardzo prosta - jak na przykładzie:
dane 1||dane 2
Aby ułatwić odczytywanie danych postanowiłem użyć małego podstępu. Mianowicie php dostarcza dwie funkcje które umożliwiają zapis danych w postaci ciągu znaków. Dzięki funkcji serialize() można zapisać tablice i obiekty oraz wartości boolean. Funkcja unserialize() umożliwia odczytanie danych zapisanych poprzednim sposobem. Ot przykład ciągu uzyskanego funckją serialize:
a:5:{i:0;s:6:"News 1";i:1;s:7:"Splatch";i:2;s:15:"splatch@desk.pl";i:3;s:32:"To jest tresc pierwszego news'a.";i:4;i:1087073047;}
Po odczytaniu unserialize:
array( "News 1", "Splatch", "splatch@desk.pl", "To jest tresc pierwszego news'a.", 1087073047 );
1. Wyświetlanie
Wyświetlenie nowości będzie działało w następujący sposób.
a) otwarcie pliku z danymi
b) rozdzielenie poszczególnych danych
c) odczytanie przy pomocy unserialize
d) pokazanie nowości
Dodatkowo wiadomości dłuższe niz 255 znaków będą obcinane, a pod nimi będzie pokazywany link 'więcej'.
Cały kod - do analizy, tudzież przeglądnięcia.
<?php
//wczytuje schemat strony
$schemat = 'admin/tpl/page.tpl';
$fd = fopen( $schemat, 'r' );
$page = fread( $fd, filesize( $schemat ) );
fclose( $fd );
//jesli nie ma numerku nowosci
//to pokaż wszystkie
if( empty( $_GET['id'] ) )
{
//dane
$plik = 'news/dane.ht';
$fd = fopen( $plik, 'r' );
$tresc = fread( $fd, filesize( $plik ) );
fclose( $fd );
//schemat tabelki do wyswietlenia nowosci
$schemat = 'admin/tpl/schemat.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
//rozdzielenie nowosci
$newsy = explode( '||', $tresc );
//przegladanie poszczegolnych nowosci
foreach( $newsy as $id => $dane )
{
$id++;
$dane = unserialize( $dane ); //odczytaj dane
$tpl = $tpl_c;
$tpl = str_replace( '{$temat}', $dane[0], $tpl );
$tpl = str_replace( '{$dodal}', $dane[1], $tpl );
$tpl = str_replace( '{$email}', $dane[2], $tpl );
if( strlen( $dane[3] ) > 255 )
{ //jesli jest za długi przytnij
$tresc = substr( $dane[3], 0, 255 ) .'...';
$wiecej = '<tr><td colspan="2" align="right"><a href="news.php?id='. $id .'">wiecej</a></td></tr>';
$tpl = str_replace( '{$tresc}', $tresc, $tpl );
$tpl = str_replace( '{$wiecej}', $wiecej, $tpl );
}
else
{ //za mały :-)
$tpl = str_replace( '{$tresc}', $dane[3], $tpl );
$tpl = str_replace( '{$wiecej}', '', $tpl );
}
//pokaż stronę
$tpl = str_replace( '{$data}', date( 'd.m.Y', $dane[4] ), $tpl );
$page = str_replace( '{$tresc}', $tpl, $page );
echo $page;
}
}
else
{ //jest numerek wiadomości
//dane
$plik = 'news/dane.ht';
$fd = fopen( $plik, 'r' );
$tresc = fread( $fd, filesize( $plik ) );
fclose( $fd );
//schemat
$schemat = 'admin/tpl/schemat.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
//rozdzielenie
$newsy = explode( '||', $tresc );
foreach( $newsy as $id => $dane )
{
if( $id+1 == $_GET['id'] )
{ //jesli zgadza sie numerek to pokaz
$dane = unserialize( $dane );
$tpl = $tpl_c;
$tpl = str_replace( '{$temat}', $dane[0], $tpl );
$tpl = str_replace( '{$dodal}', $dane[1], $tpl );
$tpl = str_replace( '{$email}', $dane[2], $tpl );
$tpl = str_replace( '{$tresc}', $dane[3], $tpl );
$tpl = str_replace( '{$wiecej}', '', $tpl );
$tpl = str_replace( '{$data}', date( 'd.m.Y', $dane[4] ), $tpl );
//wyswietl strone
$page = str_replace( '{$tresc}', $tpl, $page );
echo $page;
}
}
}
?>
Teraz kilka słów omówienia. Bardziej spostrzegawczy mogli zauważyć, że numery nowości są zwiększane o jeden. Jest to spowodowane tym, że funkcja empty() wartość 0 traktuje jako pustą, a klucze w tablicy stworzonej przy pomocy explode() są numerowane od zera.
Dlaczego używam tej funkcji? Ponieważ stosowanie funkcji isset() wymusza sprawdzenie czy dane są. Isset sprawdza czy istnieje zmienna np:
<?php
$var = '';
if( isset( $var ) )
{
echo 'jest zmienna';
}
if( !empty( $var ) )
{
echo 'zmienna jest pusta lub nie istnieje';
}
else
{
echo 'zmienna zadeklarowana';
}
?>
Sprawdzenie za pomocą isset wyglądałoby tak:
if( isset( $var ) && $var != '' ) { /* spełniony warunek! */ }
No i jeszcze dlaczego używam cały czas str_replace()? :). Jest to poniekąd utrudnienie, ale tylko na krótką metę. Dzięki temu sposobowi unikam mieszania kodu php z html'em. Pozwala to uniknąć kłopotów z cudzysłowami i apostrofami. Dodatkowo zwiększa przejżystość kodu, zmniejsza liczbę błędów oraz ułatwia edycję. Wszystkie szablony są zapisane w formacie html, tylko czasami spotyka się {$cos}, za co wstawiana jest jakaś wartość.
2. Administracja
Jako, że jest to kurs a nie omówienie to utrudnię nieco życie. Nie będzie opisany sposób na dodawanie nowych wiadomości, będzie to zadanie dla Was.
Dostęp do panelu będzie broniony przy pomocy systemu autoryzacji użytkowników, który opisywałem w poprzedniej odsłonie kursu (też nie ma administracji :)).
Aby móc edytować wiadomość trzeba mieć jakiś sposób na jej rozpoznanie, jakiś numer identyfikacyjny lub coś podobnego. Zadanie te spełnia pętla:
foreach( $tablica as $klucz => $wartosc )
Kod strony głównej administracji wygląda tak:
<?php
ini_set( 'session.use_cookies', 1 );
session_set_cookie_params( 3600 );
session_start( );
//schemat
$fd = fopen( 'tpl/page.tpl', 'r' );
$page = fread( $fd, filesize( 'tpl/page.tpl' ) );
fclose( $fd );
//formularz do logowania
function formularz()
{
$form = "<form method='POST' action='login.php'>";
$form .= "Login<input type='text' name='login'><br>";
$form .= "Haslo<input type='password' name='haslo'>";
$form .= "<input type='hidden' name='from' value='". $_SERVER['PHP_SELF'] ."'>";
$form .= "<input type='submit' value='ok'></form>";
//nie wyswietla, ale zwraca sam kod
return $form;
}
//jesli nie jest adminem pokaż formularz do logowania
if( $_SESSION['status'] != 'a' )
{
$head = '<h1>brak dostepu</h1>';
$head .= 'Musisz sie zalogowac jako admin<br>';
$head .= formularz();
$page = str_replace( '{$tresc}', $head, $page );
echo $page; // pokaż
exit(); // zakończ działanie skryptu
}
else
{ //jest adminem
$head = '<h1>Admin</h1>';
$head .= 'Witaj '. $_SESSION['user'] .'!<br>';
$head .= '<a href="login.php?def=logout">Wyloguj sie</a><p>'; // link do wylogowania sie
//wczytaj dane
$plik = '../news/dane.ht';
$fd = fopen( $plik, 'r' );
$tresc = fread( $fd, filesize( $plik ) );
fclose( $fd );
$schemat = 'tpl/admin.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
//podziel
$newsy = explode( '||', $tresc );
foreach( $newsy as $id => $dane )
{
$dane = unserialize( $dane ); //odczytaj
$tpl = $tpl_c;
if( strlen( $dane[3] ) > 255 )
{ //przytnij
$tresc = substr( $dane[3], 0, 255 ) .'...';
$tpl = str_replace( '{$tresc}', $tresc, $tpl );
}
else
{
$tpl = str_replace( '{$tresc}', $dane[3], $tpl );
}
$tpl = str_replace( '{$temat}', $dane[0], $tpl );
$tpl = str_replace( '{$dodal}', $dane[1], $tpl );
$tpl = str_replace( '{$id}', $id+1, $tpl );
$tpl = str_replace( '{$data}', date( 'd.m.Y', $dane[4] ), $tpl );
$return .= $tpl; //przypisz do zmiennej
}
$page = str_replace( '{$tresc}', $head . $return, $page );
echo $page; //pokaż
}
?>
Poniżej znajduje się również kod odpowiedzialny za edycję wiadomości. Cała różnica polega na stworzeniu formularza i jego obsłudze, stąd zastosowałem warunek if, elseif oraz else.
<?php
ini_set( 'session.use_cookies', 1 );
session_set_cookie_params( 3600 );
session_start( );
$fd = fopen( 'tpl/page.tpl', 'r' );
$page = fread( $fd, filesize( 'tpl/page.tpl' ) );
fclose( $fd );
function formularz()
{
$form = "<form method='POST' action='login.php'>";
$form .= "Login<input type='text' name='login'><br>";
$form .= "Haslo<input type='password' name='haslo'>";
$form .= "<input type='hidden' name='from' value='". $_SERVER['PHP_SELF'] ."'>";
$form .= "<input type='submit' value='ok'></form>";
return $form;
}
if( $_SESSION['status'] != 'a' )
{ // nie jest adminem
$head = '<h1>brak dostepu</h1>';
$head .= 'Musisz sie zalogowac jako admin<br>';
$head .= formularz();
$page = str_replace( '{$tresc}', $head, $page );
echo $page;
exit();
}
else
{ // jest adminem
$head = '<h1>Admin</h1>';
$head .= 'Witaj '. $_SESSION['user'] .'!<br>';
$head .= '<a href="login.php?def=logout">Wyloguj sie</a><p>';
$plik = '../news/dane.ht';
$fd = fopen( $plik, 'r' );
$tresc = fread( $fd, filesize( $plik ) );
fclose( $fd );
$newsy = explode( '||', $tresc );
if( !empty( $_GET['id'] ) )
{ // jest znany muer wiadomosci
$schemat = 'tpl/edit.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
foreach( $newsy as $id => $dane )
{
if( $id+1 == $_GET['id'] )
{ // numery sa takie same wiec pokaz formularz
$dane = unserialize( $dane );
$tpl = $tpl_c;
$tpl = str_replace( '{$temat}', $dane[0], $tpl );
$tpl = str_replace( '{$dodal}', $dane[1], $tpl );
$tpl = str_replace( '{$email}', $dane[2], $tpl );
$tpl = str_replace( '{$tresc}', $dane[3], $tpl );
$tpl = str_replace( '{$id}', $_GET['id'], $tpl );
$tpl = str_replace( '{$wiecej}', '', $tpl );
$tpl = str_replace( '{$data}', date( 'd.m.Y', $dane[4] ), $tpl );
$return .= $tpl;
}
}
$page = str_replace( '{$tresc}', $head . $return, $page );
echo $page;
}
elseif( !empty( $_POST['id'] ) )
{ // jest zmienna z formularza zatem zmien dane
foreach( $newsy as $id => $dane )
{
$id++;
if( $id == $_POST['id'] )
{
$dane = unserialize( $dane );
$edit[0] = $_POST['temat'];
$edit[1] = $_POST['dodal'];
$edit[2] = $_POST['email'];
$edit[3] = $_POST['tresc'];
$edit[4] = $_POST['zmien'] == 1 ? time() : $dane[4];
$save[ $id ] = serialize( $edit );
}
else
{
$save[ $id ] = $dane;
}
}
$schemat = 'tpl/wiadomosc.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
if( $fd = fopen( $plik, 'w' ) )
{ // mozna otworzyc plik
fwrite( $fd, implode( '||', $save ) );
fclose( $fd );
$tpl_c = str_replace( '{$temat}', 'Zmieniono news', $tpl_c );
$tpl_c = str_replace( '{$tresc}', 'News zostal pomyslnie zmieniony.<br>
<a href="admin.php">Powrot do administracji</a>', $tpl_c );
$page = str_replace( '{$tresc}', $head . $tpl_c, $page );
echo $page;
}
else
{ // nie mozna otworzyc pliku
$tpl_c = str_replace( '{$temat}', 'Nie zmieniono wiadomosci', $tpl_c );
$tpl_c = str_replace( '{$tresc}', 'Wystapil blad podczas proby otworzenia pliku.<br>
<a href="admin.php">Powrot do administracji</a>', $tpl_c );
$page = str_replace( '{$tresc}', $head . $tpl_c, $page );
echo $page;
}
}
else
{ // pokaz liste newsow
$schemat = 'tpl/admin.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
foreach( $newsy as $id => $dane )
{
$dane = unserialize( $dane );
$tpl = $tpl_c;
if( strlen( $dane[3] ) > 255 )
{
$tresc = substr( $dane[3], 0, 255 ) .'...';
$tpl = str_replace( '{$tresc}', $tresc, $tpl );
$tpl = str_replace( '{$wiecej}', $wiecej, $tpl );
}
else
{
$tpl = str_replace( '{$tresc}', $dane[3], $tpl );
}
$tpl = str_replace( '{$temat}', $dane[0], $tpl );
$tpl = str_replace( '{$dodal}', $dane[1], $tpl );
$tpl = str_replace( '{$id}', $id+1, $tpl );
$tpl = str_replace( '{$data}', date( 'd.m.Y', $dane[4] ), $tpl );
$return .= $tpl ;
}
$page = str_replace( '{$tresc}', $head . $return, $page );
echo $page;
}
}
?>
Wręcz na identycznej zasadzie działa usuwanie wiadomości.
<?php
ini_set( 'session.use_cookies', 1 );
session_set_cookie_params( 3600 );
session_start( );
$fd = fopen( 'tpl/page.tpl', 'r' );
$page = fread( $fd, filesize( 'tpl/page.tpl' ) );
fclose( $fd );
function formularz()
{
$form = "<form method='POST' action='login.php'>";
$form .= "Login<input type='text' name='login'><br>";
$form .= "Haslo<input type='password' name='haslo'>";
$form .= "<input type='hidden' name='from' value='". $_SERVER['PHP_SELF'] ."'>";
$form .= "<input type='submit' value='ok'></form>";
return $form;
}
if( $_SESSION['status'] != 'a' )
{ // nie jest adminem
$head = '<h1>brak dostepu</h1>';
$head .= 'Musisz sie zalogowac jako admin<br>';
$head .= formularz();
$page = str_replace( '{$tresc}', $head, $page );
echo $page;
exit();
}
else
{ // wybraniec losu :)
$head = '<h1>Admin</h1>';
$head .= 'Witaj '. $_SESSION['user'] .'!<br>';
$head .= '<a href="login.php?def=logout">Wyloguj sie</a><p>';
$plik = '../news/dane.ht';
$fd = fopen( $plik, 'r' );
$tresc = fread( $fd, filesize( $plik ) );
fclose( $fd );
$newsy = explode( '||', $tresc );
if( !empty( $_GET['id'] ) )
{ // jest znany numer wiadomosci
$schemat = 'tpl/del.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
foreach( $newsy as $id => $dane )
{
if( $id+1 == $_GET['id'] )
{ // numery sie zgadzaja, pokaz wiadomosci i formularz do usuniecia
$dane = unserialize( $dane );
$tpl = $tpl_c;
$tpl = str_replace( '{$temat}', $dane[0], $tpl );
$tpl = str_replace( '{$dodal}', $dane[1], $tpl );
$tpl = str_replace( '{$email}', $dane[2], $tpl );
$tpl = str_replace( '{$tresc}', $dane[3], $tpl );
$tpl = str_replace( '{$id}', $_GET['id'], $tpl );
$tpl = str_replace( '{$wiecej}', '', $tpl );
$tpl = str_replace( '{$data}', date( 'd.m.Y', $dane[4] ), $tpl );
$return .= $tpl;
}
}
$page = str_replace( '{$tresc}', $head . $return, $page );
echo $page;
}
elseif( !empty( $_POST['id'] ) )
{ // jest zmienna z formularza tzn. usun wiadomosci
foreach( $newsy as $id => $dane )
{
$id++;
if( $id != $_POST['id'] )
{ // jesli numer sie nie zgadza wiadomosci ma zostac
$save[] = $dane;
}
}
$schemat = 'tpl/wiadomosc.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
if( $fd = fopen( $plik, 'w' ) )
{ // mozna zapisac
fwrite( $fd, implode( '||', $save ) );
fclose( $fd );
$tpl_c = str_replace( '{$temat}', 'Usunieto news', $tpl_c );
$tpl_c = str_replace( '{$tresc}', 'News zostal usuniety.<br>
<a href="admin.php">Powrot do administracji</a>', $tpl_c );
$page = str_replace( '{$tresc}', $head . $tpl_c, $page );
echo $page;
}
else
{ // nie mozna zapisac
$tpl_c = str_replace( '{$temat}', 'Problem!', $tpl_c );
$tpl_c = str_replace( '{$tresc}', 'News nie zostal usuniety. Wystapil blad podczas proby otworzenia pliku.<br>
<a href="admin.php">Powrot do administracji</a>', $tpl_c );
$page = str_replace( '{$tresc}', $head . $tpl_c, $page );
echo $page;
}
}
else
{ // pokaz liste
$schemat = 'tpl/admin.tpl';
$fd = fopen( $schemat, 'r' );
$tpl_c = fread( $fd, filesize( $schemat ) );
fclose( $fd );
foreach( $newsy as $id => $dane )
{
$dane = unserialize( $dane );
$tpl = $tpl_c;
if( strlen( $dane[3] ) > 255 )
{
$tresc = substr( $dane[3], 0, 255 ) .'...';
$tpl = str_replace( '{$tresc}', $tresc, $tpl );
$tpl = str_replace( '{$wiecej}', $wiecej, $tpl );
}
else
{
$tpl = str_replace( '{$tresc}', $dane[3], $tpl );
}
$tpl = str_replace( '{$temat}', $dane[0], $tpl );
$tpl = str_replace( '{$dodal}', $dane[1], $tpl );
$tpl = str_replace( '{$id}', $id+1, $tpl );
$tpl = str_replace( '{$data}', date( 'd.m.Y', $dane[4] ), $tpl );
$return .= $tpl ;
}
$page = str_replace( '{$tresc}', $head . $return, $page );
echo $page;
}
}
?>
Jak dobrze zauważyliście wiadomości są zapisywane w nowej tablicy $save. Trafią tam wszystkie wiadomości oprócz usuwanej. Następnie zamieniam tablicę w ciąg przy pomocy implode(). Funkcja ta jest bardzo przydatna - łączy poszczególne elementy tablicy (pomijając klucze) wstawiając między nie wybrany przez nas ciąg. Jej składnia jest następująca
<?php
$tablica = array( 1, 2, 3, 4, 5 );
echo implode( '||', $tablica ); // wyswietli 1||2||3||4||5
?>
Korzyści na pewno zauważycie, gdy sami zaczniecie jej używać :).
3. Uwagi końcowe
Skrypt, który macie przedstawiony jest szkieletem. Nie sprawdzałem, ale wiem, że całość się posypie, kiedy wpiszecie w treści, temacie, nadawcy lub adresie || to zrobi wam z tego dwie wiadomości, ale żadna nie będzie poprawnie wyświetlana.
Gdybyście mieli pytania uwagi lub znajdziecie błędy to piszcie śmiało, z chęcią odpowiem. Zdziwiło mnie, że nikt nie chce zaistnieć na łamach strefy. Jeśli ktoś zmienił zdanie to proszę o poprawienie, przebudowanie tej aplikacji lub napisanie zupełnie nowej, któraby oferowała
a) dodawanie nowych wiadomości
b) zmianę znaków nowych lini na <br> (służy do tego funkcja nl2br())
c) dla chętnych możliwość komentowania
Ja nie przedstawię rozwiązań, bo jest to zadanie dla Was. To dla siebie się uczycie i wierzcie mi, bez ćwiczeń niewiele zrobicie. Ja daję zadania niezbyt wygórowane, tak by nikogo nie zniechęcić. Jeśli z czymś nie możesz sobie poradzić, p i s z .
Łukasz 'Splatch' Dywicki
splatch@desk.pl
http://splatch.desk.pl |