Chci geek triko! Chci geek triko!
Extra 10 % bodů navíc a tričko zdarma při zadání kódu "TRIKO10"

Lekce 6 - NERS - Editor článků v PHP

PHP Databáze pro začátečníky NERS - Editor článků v PHP American English version English version

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, NERS - Registrace uživatelů v PHP, jsme dokončili administrační stránku jednoduchého redakčního systému. V dnešním PHP tutoriálu přidáme přihlašování.

Přihlašování

Vytvoříme skript prihlaseni.php. Jeho HTML část bude následující:

<!DOCTYPE html>
<html lang="cs-cz">
<head>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="styl.css" type="text/css" />
        <title>Přihlášení do administrace</title>
</head>

<body>
        <article>
                <div id="centrovac">
                        <header>
                                <h1>Přihlášení do administrace</h1>
                        </header>
                        <section>
                                <?php
                                if (isset($zprava))
                                        echo('<p>' . $zprava . '</p>');
                                ?>

                                <form method="post">
                                        Jméno<br />
                                        <input type="text" name="jmeno" /><br />
                                        Heslo<br />
                                        <input type="password" name="heslo" /><br />
                                        <input type="submit" value="Přihlásit" />
                                </form>

                                <p>Pokud ještě nemáte účet, <a href="registrace.php">zaregistrujte se</a>.</p>
                        </section>
                        <div class="cistic"></div>
                </div>
        </article>
</body>
</html>

Vidíme PHP direktivu pro výpis chybové zprávy (pokud existuje) a formulář se jménem a heslem. Kód je téměř totožný s tím u registračního formuláře a měl by být tedy srozumitelný.

Nad HTML vložíme následující PHP blok:

<?php
session_start();
require('Db.php');
Db::connect('127.0.0.1', 'ners_db', 'root', '');

if (isset($_SESSION['uzivatel_id']))
{
        header('Location: administrace.php');
        exit();
}

if ($_POST)
{
        $uzivatel = Db::queryOne('
                SELECT uzivatele_id, admin, heslo
                FROM uzivatele
                WHERE jmeno=?
        ', $_POST['jmeno']);
        if (!$uzivatel || !password_verify($_POST['heslo'], $uzivatel['heslo']))
                $zprava = 'Neplatné uživatelské jméno nebo heslo';
        else
        {
                $_SESSION['uzivatel_id'] = $uzivatel['uzivatele_id'];
                $_SESSION['uzivatel_jmeno'] = $_POST['jmeno'];
                $_SESSION['uzivatel_admin'] = $uzivatel['admin'];
                header('Location: administrace.php');
                exit();
        }
}
?>

První řádky nám zpřístupní session a připojí se k databázi. Pokud je uživatel přihlášený, tak mu přihlašovací stránku zobrazovat nebudeme a přesměrujeme ho rovnou na administraci a skript zastavíme.

Pokud byl odeslán formulář, vybereme z databáze informace o uživateli podle zadaného jména a zkontrolujeme, zda se zadané heslo shoduje s otiskem hesla. Toho docílíme funkcí password_verify(), které zadáme jako parametry heslo a jeho otisk. Funkce nám následně vrátí true/false, podle toho, zda heslo souhlasí, či nikoliv. Pokud uživatele nenajdeme nebo bylo zadáno chybné heslo, uložíme chybovou hlášku. V případě úspěchu uložíme načtené informace o uživateli do session a tím ho přihlásíme. Dále ho přesměrujeme na administraci.

Můžete se zkusit přihlásit. Pokud jste ještě přihlášení z registrace, tak se odhlaste a přihlaste znovu.

Přihlašování uživatelů v PHP

Přidělení role administrátora

V našem systému máme u každého uživatele sloupec admin. Ten bude nabývat hodnoty 0 nebo 1 podle toho, zda je uživatel administrátor. Tuto hodnotu může nastavit nově registrovanému uživateli pouze administrátor webu pomocí phpMyAdmin. Přesuneme se tedy do phpMyAdmin a přepneme hodnotu admin u našeho účtu na 1 (na políčko stačí jen poklikat a hodnotu přepsat).

Administrátorská práva v phpMyAdmin

Nyní se odhlaste a přihlaste.

Editor článků

Přejděme k editoru článků. Vytvořme soubor editor.php a vložme do něj HTML blok:

<!DOCTYPE html>
<html lang="cs-cz">
<head>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="styl.css" type="text/css" />
        <title>Editor článků</title>
</head>

<body>
        <article>
                <div id="centrovac">
                        <header>
                                <h1>Editor článků</h1>
                        </header>
                        <section>
                                <?php
                                if (isset($zprava))
                                        echo('<p>' . $zprava . '</p>');
                                ?>

                                <form method="post">
                                        <input type="hidden" name="clanky_id" value="<?= htmlspecialchars($clanek['clanky_id']) ?>" /><br />
                                        Titulek<br />
                                        <input type="text" name="titulek" value="<?= htmlspecialchars($clanek['titulek']) ?>" /><br />
                                        URL<br />
                                        <input type="text" name="url" value="<?= htmlspecialchars($clanek['url']) ?>" /><br />
                                        Popisek<br />
                                        <input type="text" name="popisek" value="<?= htmlspecialchars($clanek['popisek']) ?>" /><br />
                                        Klíčová slova<br />
                                        <input type="text" name="klicova_slova" value="<?= htmlspecialchars($clanek['klicova_slova']) ?>" /><br />
                                        <textarea name="obsah"><?= htmlspecialchars($clanek['obsah']) ?></textarea>
                                        <input type="submit" value="Odeslat" />
                                </form>
                        </section>
                        <div class="cistic"></div>
                </div>
        </article>
        <script type="text/javascript" src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
        <script type="text/javascript">
                tinymce.init({
                        selector: "textarea[name=obsah]",
                        plugins: [
                                "advlist autolink lists link image charmap print preview anchor",
                                "searchreplace visualblocks code fullscreen",
                                "insertdatetime media table contextmenu paste"
                        ],
                        toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
                        entities: "160,nbsp",
                        entity_encoding: "named",
                        entity_encoding: "raw"
                });
        </script>
</body>
</html>

Kód obsahuje opět jen jednoduchý HTML formulář a výpis chybové zprávy. Data se do formulářových polí vypisují z pole $clanek. Formulář má ještě jednu zvláštnost a tou je skryté pole s ID daného článku. Podle tohoto pole poznáme, zda vkládáme nový článek (bude prázdné) nebo zda editujeme existující (bude v něm ID tohoto článku).

Zajímavý je JavaScript na konci souboru, ve které načteme WYSIWYG editor TinyMCE. To je editor vzhledově podobný např. MS Wordu, který nám generuje HTML kód podle toho, co v něm naklikáme.

První skript je odkaz na online úložiště, ze kterého si prohlížeč TinyMCE stáhne. Druhý skript obsahuje nastavení editoru, zvolíme, že editor chceme vytvořit z textarea s názvem obsah. Další řádky nastavují pluginy a vypínají převod české diakritiky na entity, což je jinak poměrně nepříjemná záležitost.

Nad HTML kód dodejme obslužný PHP blok:

<?php
session_start();
if (empty($_SESSION['uzivatel_admin']))
        die('Nedostatecna opravneni');

require('Db.php');
Db::connect('127.0.0.1', 'ners_db', 'root', '');

$clanek = array(
        'clanky_id' => '',
        'titulek' => '',
        'obsah' => '',
        'url' => '',
        'popisek' => '',
        'klicova_slova' => '',
);
if ($_POST)
{
        if (!$_POST['clanky_id'])
        {
                Db::query('
                        INSERT INTO clanky (titulek, obsah, url, popisek, klicova_slova)
                        VALUES (?, ?, ?, ?, ?)
                ', $_POST['titulek'], $_POST['obsah'], $_POST['url'], $_POST['popisek'], $_POST['klicova_slova']);
        }
        else
        {
                Db::query('
                        UPDATE clanky
                        SET titulek=?, obsah=?, url=?, popisek=?, klicova_slova=?
                        WHERE clanky_id=?
                ', $_POST['titulek'], $_POST['obsah'], $_POST['url'], $_POST['popisek'], $_POST['klicova_slova'], $_POST['clanky_id']);
        }
        header('Location: index.php?clanek=' . $_POST['url']);
        exit();
}
else if (isset($_GET['url']))
{
        $nactenyClanek = Db::queryOne('
                SELECT *
                FROM clanky
                WHERE url=?
        ', $_GET['url']);
        if ($nactenyClanek)
                $clanek = $nactenyClanek;
        else
                $zprava = 'Článek nebyl nalezen';
}

?>

Pokud uživatel není administrátor, zastavíme celý skript s chybovou hláškou. Pro kontrolu přihlášení administrátora nám nestačí isset(), ale musíme použít empty(). V session totiž může existovat klíč 'uzivatel_admin', ale může mít hodnotu 0.

Dále se připojíme k databázi a do proměnné $clanek si připravíme pole s prázdnými hodnotami. To aby se do formuláře nic nevypsalo a zároveň nám PHP neohlásilo chybu s neexistující proměnnou.

Pokud byl odeslán formulář, podíváme se do skrytého pole. Pokud je prázdné, vložíme nový článek do databáze. Pokud je v skrytém poli nějaká hodnota, updatujeme článek s tímto ID. SQL příkaz UPDATE jsme si ještě nepředstavovali, ale je velmi jednoduchý. Pomocí SET jednoduše nastavíme pole která potřebujeme. Co je důležité je nezapomenout na klauzuli WHERE, kde určíme které řádky se mají takto updatovat. Bez ní by se updatovaly všechny články na tyto hodnoty!

Po přidání nebo editaci článku na něj přesměrujeme.

Pokud nebyl odeslaný formulář, podíváme se, zda nemáme v GET url článku. To by znamenalo, že chceme nějaký editovat a proto se do pole $clanek pokusíme nahrát data z článku s tímto URL. Data se potom předvyplní do polí formuláře. Při neúspěchu vypíšeme chybovou hlášku.

Nyní si editor spusťte a vložte si článek s URL "uvod". To bude hlavní stránka našeho webu:

Editor článků TinyMCE v PHP

Článek uložte do databáze. Pokračovat budeme zas v příští lekci, NERS - Výpis článků v PHP.


 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
17 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Miniatura
Všechny články v sekci
Databáze v PHP pro začátečníky
Miniatura
Následující článek
NERS - Výpis článků v PHP
Aktivity (5)

 

 

Komentáře
Zobrazit starší komentáře (77)

Avatar
Peter Schoeller:4.3.2017 15:32

Ospravedlnujem sa, ale hned ako som odoslal otazku, som nasiel riesenie :)

$existuje_mail = Db::querySingle('
                        SELECT COUNT(*)
                        FROM members
                        WHERE (?) IN (email, email_2)
                        LIMIT 1
                ', $_POST['email']); // nastavenie duplicity emailu
 
Odpovědět 4.3.2017 15:32
Avatar
Michal Pácal [Mysak0CZ]:4.3.2017 21:19

2 otazníky => 2 hodnoty ;-)

$existuje_mail = Db::querySingle('
                        SELECT COUNT(*)
                        FROM members
                        WHERE email=? OR email_2=?
                        LIMIT 1
                ', $_POST['email'], $_POST['emai]); // nastavenie duplicity emailu
 
Odpovědět  +1 4.3.2017 21:19
Avatar
Martin Bušek:30. ledna 21:20

Ahoj používám DB.php wraper a resim problem.
Napsal jsem si funkci ktera mi ma vracet pocet radku "zaznamu" v DB

Pokud primo v SQL zadam dotaz

SELECT COUNT(`uzivatele_id`) FROM `db_uzivatele`

Vrati se mi 4.

Pokud napisu funkci

function spocitej_techniku(){
$technika_pocet = Db::queryAll('SELECT COUNT(uzivatele_id)
                                FROM db_uzivatele
                                ');
return $technika_pocet;
}

Vrati se mi mi slovo Array, Neco asi delam spatne ale nemam tuseni co :(

 
Odpovědět 30. ledna 21:20
Avatar
Hando
Člen
Avatar
Odpovídá na Martin Bušek
Hando:30. ledna 22:09

Ahoj.
No, pokud by ses podíval do zdrojového kódu toho db wrapperu, tak bys našel toto:

/**
 * Spustí dotaz a vrátí všechny jeho řádky jako pole asociativních polí. Dále se předá libovolný počet dalších parametrů.
 * @param string $query Dotaz
 * **@return mixed Pole řádků nebo false při neúspěchu**
 */
public static function queryAll($query) {
        $statement = self::executeStatement(func_get_args());
        return $statement->fetchAll(PDO::FETCH_ASSOC);
}

Zkus Db::querySingle :)

 
Odpovědět  +1 30. ledna 22:09
Avatar
Martin Bušek:30. ledna 22:52

Diky funguje, jsem zacatechnik, obsahu Db.php absolutne nerozumim, tak sem to zatim neotviral :D

Muze nekdo znalejsi vysvetlit rozdil mezi

DB::query, DB::querySingle, Db::queryOne, Db::queryAll

At v tom mám jasno, předpokládam ze vic jich není.
zajímámě k cemu každý dotaz slouži jak zpracova data a k cemu se primarne vyuziva, jiste to pouze i dalsim uzivatelum:)

Dekuji

 
Odpovědět 30. ledna 22:52
Avatar
Hando
Člen
Avatar
Odpovídá na Martin Bušek
Hando:31. ledna 0:01

Tak ono je to jednoduché, pokud si projdeš zdejší tutoriály, tak je tam tvorba takového wrapperu popsána a kód je i docela pěkně zdokumentován, takže z toho rozdíly mezi jednotlivými funkcemi (resp. metodami) vyčteš.
Nechce se mi tu popisovat nějak obsáhle, čím se co liší, ale ve zkratce:

  • query - obecné dotazy, update, insert atd., vrací počet ovlivněných řádků.
  • queryOne - vrátí ti pole jednoho řádku.
  • querySingle - vrátí ti jednu vybranou hodnotu jednoho řádku (např. select id from... vrátní právě hodnotu toho id)
  • queryAll - vrátí ti pole všech řádků (resp. pole polí) nebo false.

Více najdeš zde:
7. díl - Databázový wrapper
Rozšíření je v pokračování seriálu (metody 'zmen', 'vloz'...), další rozvoj a převedení do ang. mutace je v seriálu o objektovém programování e-shopu.

Editováno 31. ledna 0:03
 
Odpovědět  +2 31. ledna 0:01
Avatar
Hando
Člen
Avatar
Odpovídá na Martin Bušek
Hando:31. ledna 0:12
  • pokračování, co jsem dopisoval v editaci - nebylo by možné prodloužit limit na editaci? Těch pár minut je zbytečně málo.

V seriálu o e-shopu v OOP (MVC) je toho pak o něco víc (metody 'vložVše', 'uprav', transakce...) a pokud to myslíš s programováním vážně, tak to je docela dobrá volba, jelikož v češtině takový seriál podle všeho neexistuje a naučí tě spoustu věcí.

Ale pokud budeš plánovat další rozvoj práce s db, tak je potřeba se naučit číst dokumentaci a zkoumat cizí kód, protože teprve tehdy si zvládneš správě vybrat, jaká knihovna je pro tebe ta pravá. Složitější dotazy na databázi tyhle věci odhalí. Můžeš se zkusit podívat třeba na českou DIBI ( DIBI ) nebo na jakýkoliv balík, které používají frameworky - na githubu je toho spoustu.

 
Odpovědět  +1 31. ledna 0:12
Avatar
Bohuslav Holček:17. července 12:05

musim uznat ze na netu je spousty mozna 90% info o php je zastarale informace z minuleho stoleti. tady na itnetwork je fakt kvalitne zpracovane a studuji podle toho. je to smutne jak je internet zaplevelenej tim starym mnohdy uz neplatnim kodem o mysql prikazech nemluvne. ucim se tak sem rad jak za serial tak i za PDO wrapper a klobouk dolu. a je usmevne kolik lidi komentuje ze jim neco nefunguje a vzdy to skonci tim ze chybu mneli nekde oni... jeste jednou diky za serial....

 
Odpovědět 17. července 12:05
Avatar
Marty
Člen
Avatar
Marty:7. října 2:06

NetBeans mě upozorňuje na tuhle chybu:

Do not Access Superglobal $_POST Array Directly

Už dlouho se používá $_POST, tak proč by se to najednou mělo psát funkcí filter_input(IN­PUT_POST...)?
Co konkrétně by se eventuálně mohlo stát, při použití přímého přístupu?

 
Odpovědět 7. října 2:06
Avatar
Zdeněk Srb
Člen
Avatar
Odpovídá na Marty
Zdeněk Srb:7. října 9:50

Tak říkáš aplikaci jaké proměnné z toho formuláře očekáváš a zbytek tě nazajímá, jde o další vrstvu ochrany proti koncovému uživateli.

 
Odpovědět  +1 7. října 9:50
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 87. Zobrazit vše