Weblog v PHP - vkládání, mazání a úprava článků
21. 01. 2003 | Michal Kebrt | PHP | Komentáře: 3
V posledním článku této série si ukážeme, jakým způsobem vyřešit přidávání nových článků a mazání a úpravu článků již napsaných. Dozvíte se, jak ošetřit uživatelské vstupy tak, aby uživatelé nemohli narušit design ani funkčnost stránek, ale přitom mohli vkládat některé elementy a dlouhé odkazy. Na závěr si budete moci kompletní zdrojové kódy weblogu stáhnout.
Funkční ukázku weblogu najdete na webu Czechie.
Vkládání a mazání článků (index.php)
K rozlišení toho, zda se bude článek vkládat či mazat, použijeme proměnnou $action. Obsahuje-li "post", pak článek vložíme. Nejprve však musíme zkontrolovat, zda byly vyplněny oba povinné údaje (nadpis - title a text článku - article_text) a zda datum vydání není menší než aktuální datum, přičemž necháváme rezervu patnácti minut (lze samozřejmě změnit) na napsání článku. Je-li vše v pořádku, upravíme pomocí funkce Text_Modify(), která bude popsána v závěru, oba vstupní údaje. Následně zjistíme datum prvního dne v týdnu, ve kterém článek vyjde a všechny údaje vložíme do tabulky article. Nakonec, pomocí funkcí popsaných již dříve, vygenerujeme úvodní stránku a příslušnou archivní stránku.
// byla odeslana promenna "action" ?
if(IsSet($_REQUEST['action'])) {
switch($_REQUEST['action']) {
// vlozi clanek
case "post":
// byly vyplneny oba povinne udaje ?
if($_POST['title']=="" || $_POST['article_text'] =="") {
$error = 4;
// neni datum vydani mensi nez aktualni datum (rezerva 15 min) ?
} elseif(MkTime($_POST['from_hour'], $_POST['from_minute']+15, 0, $_POST['from_month'], $_POST['from_day'], $_POST['from_year']) < Time()) {
$error = 5;
} else {
// uprava vstupu
$title = Text_Modify($_POST['title']);
$article_text = Text_Modify($_POST['article_text']);
$publish_date = MkTime($_POST['from_hour'], $_POST['from_minute'], 0, $_POST['from_month'], $_POST['from_day'], $_POST['from_year']); // datum vydani
$day_number = Date("w", $publish_date);
if($day_number == 0) $day_number = 7;
$first_day_of_week = MkTime(0,0,0, $_POST['from_month'], $_POST['from_day']-$day_number+1, $_POST['from_year']); // datum prvniho dne v tydnu, ve kterem clanek vychazi
$query = @MySQL_Query("INSERT INTO article VALUES ('', '$title', '$article_text', '$publish_date', '$user_id', '$first_day_of_week')") or Weblog_Error(2);
$message = 1;
// vygeneruje staticke stranky
require "archive.php";
Create_Archive($first_day_of_week);
Create_Index("static");
MySQL_Close();
Header('Location: http://'. $_SERVER['HTTP_HOST'] . '/weblog/admin/index.php?message=' . URLDecode($message) .'&' . SID); // navrat na uvodni stranku
exit;
}
break;
Pokud proměnná $action obsahuje "delete", příslušný článek se smaže. Ještě než článek smažeme, musíme zjistit, zda přihlášený autor ($user_id) má k danému článku ($article_id) práva. Mohlo by se totiž stát, že by někdo do odkazu vložil id jiného článku a smazal by tak cizí článek. V případě, že přihlášený autor je autorem daného článku nebo je přihlášený autor administrátorem (má práva ke všem článkům), článek smažeme a vygenerujeme statické stránky.
// smaze clanek
case "delete":
$article_id = $_GET['article_id'];
$query = @MySQL_Query("SELECT author FROM article WHERE id = $article_id") or Weblog_Error(2); // autor clanku
$result = MySQL_Fetch_Array($query);
// ma prihlaseny autor prava k tomuto clanku ?
if($result["author"] == $user_id || $user_type == "A") {
$query = @MySQL_Query("SELECT archive_date FROM article WHERE id = $article_id") or Weblog_Error(2); // tyden, ve kterem clanek vysel
$result = MySQL_Fetch_Array($query);
$query = @MySQL_Query("DELETE FROM article WHERE id = $article_id") or Weblog_Error(2);
$message = 2;
// vygeneruje staticke stranky
require "archive.php";
Create_Archive($result['archive_date']);
Create_Index("static");
} else {
$message = 4;
}
MySQL_Close();
Header('Location: http://'. $_SERVER['HTTP_HOST'] . '/weblog/admin/index.php?message=' . $message .'&' . SID); // navrat na uvodni stranku
exit;
break;
}
}
Úprava článku (update.php)
K úpravě napsaných článků použijeme soubor update.php. V úvodu načteme všechny potřebné soubory a do proměnné $article_id vložíme id daného článku.
ini_set('session.use_trans_sid', 1); // zajisti prenos session id
require "checklogin.php"; // je autor prihlasen ?
require "../db.php"; // pripoji k databazi
require "../function.php"; // nacte soubor s dulezitymi funkcemi
require "msg.php"; // chybove hlasky a zpravy
$article_id = $_REQUEST['article_id']; // id clanku
Následně z databáze vybereme nadpis a text daného článku a oba údaje vložíme do poměrně jednoduchého formuláře. Ke zpětné úpravě údajů, které byly modifikovány funkcí Text_Modify(), použijeme funkci un_Text_Modify(), o které bude řeč v závěru.
<?php
// vybere prislusny clanek a zobrazi formular
$query = @MySQL_Query("SELECT title, message FROM article WHERE id = $article_id") or Weblog_Error(2);
$result = MySQL_Fetch_Array($query);
$title = un_Text_Modify($result['title']);
$article_text = un_Text_Modify($result['message']);
?>
<h2 class="heading">Weblog - administrace</h2>
<h3 class="heading">Upravit článek</h3>
<?php
// chybova hlaska
if(IsSet($_GET['error'])) $error = $_GET['error'];
if(IsSet($error) && IsSet($msg_error[$error])) echo '<p class="error">' . $msg_error[$error] . '</p>';
?>
<form action="update.php" method="post">
<input type="hidden" name="sent" value="">
<input type="hidden" name="article_id" value="<?php echo $article_id; ?>">
<div class="form">
<div class="formrow">
<div class="formdesc">Nadpis</div><div class="forminput"><input type="text" name="title" size="30" value="<?php echo $title; ?>" maxlength="150"></div>
</div>
<div class="formrow">
<div class="formdesc">Text</div><div class="forminput"><textarea cols="20" rows="5" name="article_text"><?php echo $article_text; ?></textarea></div>
</div>
<div class="formrowsubmit">
<input type="submit" name="send" value="Upravit" class="submit">
</div>
</div>
</form>
Pokud byl formulář odeslán, zkontrolujeme, zda byly vyplněny oba údaje a zároveň je upravíme funkcí Text_Modify(). Podobně jako u mazání článku, musíme zkontrolovat, zda-li má přihlášený autor práva k danému článku. Následně provedeme aktualizaci údajů v databázi a vygenerujeme statické stránky.
// byl odeslan formular ?
if(IsSet($_POST['sent'])) {
// uprava vstupu
$title = Text_Modify($_POST['title']);
$article_text = Text_Modify($_POST['article_text']);
// byly vyplneny oba povinne udaje ?
if($title=="" || $article_text =="") {
$error = 4;
}
// vse je v poradku
if(!IsSet($error)) {
$query = @MySQL_Query("SELECT author FROM article WHERE id = $article_id") or Weblog_Error(2); // autor clanku
$result = MySQL_Fetch_Array($query);
// ma prihlaseny autor prava k tomuto clanku ?
if($result["author"] == $user_id || $user_type == "A") {
$query = @MySQL_Query("UPDATE article SET title = '$title', message = '$article_text' WHERE id = $article_id") or Weblog_Error(2);
$message = 3;
$query = @MySQL_Query("SELECT archive_date FROM article WHERE id = $article_id") or Weblog_Error(2); // tyden, ve kterem clanek vysel
$result = MySQL_Fetch_Array($query);
// vygeneruje staticke stranky
require "archive.php";
Create_Archive($result['archive_date']);
Create_Index("static");
} else {
$message = 5;
}
MySQL_Close();
Header('Location: http://'. $_SERVER['HTTP_HOST'] . '/weblog/admin/index.php?message=' . URLDecode($message) .'&' . SID); // navrat na uvodni stranku
exit;
}
}
Úprava vstupních údajů
Doposud jsem již několikrát zmínil o funkci Text_Modify(), která provádí úpravu vstupních údajů tak, aby neposlušný uživatel nemohl narušit vzhled ani layout stránky, ale přitom mohl používat některé elementy a vkládat odkazy. Funkci tedy můžete použít v diskusních fórech, návštěvních knihách a podobně.
Postupně se odstraní mezery z obou konců řetězce, nebezpečné znaky se převedou na HTML entity, konce řádků na elementy <br />. S povolením některých elementů, především těch párových, je to o něco složitější. Aby uživatel mohl vložit například text "<em>kurziva <strong>tucna kurziva</strong></em> normal <em>kurziva</em>" a dosáhl požadovaného výsledku "kurziva tucna kurziva normal kurziva", musíme použít regulární výraz podle normy Perl, kde sekvence znaků .*? zajistí, že se funkce zastaví hned u prvního výskytu "</em>". Při použití klasických regulárních výrazů a funkce EregI_Replace() bychom tohoto efektu nedosáhli a v kurzívě by byl celý řetězec. Důležité jsou ještě znaky si, které zajistí to, že funkce nebere ohled na nové řádky a malá a velká písmena. Další podrobnosti týkající se tohoto druhu regulárních výrazů najdete v manuálu PHP. S nepárovými elementy je to o poznání jednodušší, takže můžeme použít známou funkci EregI_Replace().
Dalším problémem jsou dlouhá slova, která dokáží "velmi dobře" narušit vzhled celé stránky. PHP nám sice nabízí funkci Wordwrap(), ale chceme-li uživatelům umožnit vkládání odkazů, které jsou velmi často delší než únosná hranice, musíme použít trošku složitější postup. Celý text nejprve rozdělíme na jednotlivá slova, poté jimi postupně procházíme a testujeme, zda odpovídají tvaru odkazu. Pokud ano, pak obsah elementu <a> rozdělíme, ale parametr href ponecháme nerozdělený. Pokud slovo není odkazem, rozdělíme ho a jednotlivá slova spojíme dohromady.
function Text_Modify($text) {
$text = Trim($text); // odstrani mezery z obou koncu retezce
$text = HTMLSpecialChars($text, ENT_QUOTES); // prevede nebezpecne znaky
// nahradi konce radku na tagy <br />
$text = Str_Replace("\r\n"," <br /> ", $text);
$text = Str_Replace("\n"," <br /> ", $text);
// umozni vkladat nektere parove tagy
$tags = Array("b", "u", "i", "small", "big", "strong", "em");
while(Current($tags)) {
$tag = Current($tags);
$text = Preg_Replace('\'<' . $tag . '>(.*?)</' . $tag . '>\''. "si", ' <' . $tag . '>\\1</' . $tag . '> ', $text);
Next($tags);
}
// umozni vkladat nektere neparove tagy
$tags2 = Array("br", "hr");
while(Current($tags2)) {
$text = EregI_replace("<" . Current($tags2) . "( /)?>", "<" . Current($tags2) . " />", $text);
Next($tags2);
}
$words = Split("[[:blank:]]+", Trim($text)); //rozdeleni textu na slova
$connect_text = '';
while(Current($words)) {
$word = Trim(Current($words)); //odstraneni mezer na konci slova
if(EregI("http://[^ ]+\.[^< ]+", $word, $part)) {
$word = Str_Replace($part[0], '<a href="' . $part[0] . '">' . Wordwrap($part[0], 25, " ", 1) . '</a>', $word);
} elseif(EregI('www\.[^ ]+\.[^< ]+', $word, $part)) {
$word = Str_Replace($part[0], '<a href="http://' . $part[0] . '">' . Wordwrap($part[0], 25, " ", 1) . '</a>', $word);
} else {
$word = Wordwrap($word, 25, " ", 1);
}
$connect_text .= $word . " ";
Next($words);
}
return Trim($connect_text);
}
Abychom uživatelům zajistili komfortní úpravu napsaných článků, zpracujeme údaje modifikované funkcí Text_Modify() opačnou funkcí un_Text_Modify. První tři řádky této funkce, které jsou vlastně opakem k funkci HTMLSpecialChars() můžeme klidně vypustit. Entity i původní znaky se totiž ve formuláři zobrazí identicky. V další části pak elementy <br /> nahradíme řádky a elementy <a> pouze vlastními odkazy.
function un_Text_Modify($text) {
$trans_tbl = Get_HTML_Translation_Table(HTML_SPECIALCHARS);
$trans_tbl = Array_Flip($trans_tbl);
$text = StrTr($text, $trans_tbl);
$text = EregI_Replace(" <br /> ","\n", $text);
$text = EregI_Replace('<a href="([^"]+)">[^<]+</a>', "\\1", $text);
return $text;
}
Instalace weblogu
- Stažení - aplikační balík
- Vytvoření databáze – například pomocí příkazu
mysqladmin create weblog - Nastavení databáze – upravte soubor db.php
- Vytvoření databázových tabulek – pomocí příkazu
mysql weblogspusťte klienta, v něm zapište příkaz\. vase_cesta\weblog.sql;(např.\. c:\lokal\weblog\weblog.sql;), můžete však použít i phpMyAdmin - Administrátor – administrátora můžete vytvořit buď přímo v souboru weblog.sql, kde do příslušného SQL příkazu vložíte dané údaje nebo úpravou daného záznamu v tabulce
authortak, že do položkyuser_typevložíte "A"
Případnou kritiku či náměty na vylepšení weblogu pište, prosím, do diskuse pod článkem.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Další aktuální články na interval.cz
- Rychost, rychlost, rychlost - zrychlete své stránky
- Chamurappiho Webylon: čtyři články s kritikou W3C
- Nenápadný cloud: synchronizace dat z prohlížečů
- Pozvánka: Random Hacks of Kindness 2012
- Zajímavost o češtině pro redakční systém WordPress
Tematicky související články
- Weblog v PHP - administrační rozhraní
- Weblog v PHP - registrace a přihlášení autorů
- Weblog v PHP - archivní stránky
- Weblog v PHP - databázové tabulky a úvodní stránka
- Udělejte si svůj weblog v PHP
Dejte vědět i ostatním o článku
Komentáře ke článku
Datum vložení: 18. Srpen 2009, 15:13:13
co s tím je pokažde když chci přidat nějaký článek tak mi to napíše: Nastala chyba při generování statické stránky.
Datum vložení: 05. Březen 2010, 14:18:27
no me to vubec nejede. pokazde prazdna obrazovka. zkousel jsem do index.php na zacatku napsat obycejne Ahoj a ani to se mi nezobrazi. co s tim? to budu muset projit cely kod? hruza... :o$
Datum vložení: 10. Prosinec 2010, 19:24:24
Mám stejný problém jako denis a masterpawn.. Po přidání článku nelze vygenerovat statickou stránku.. :(
