Diskuze: Komentáře pouze pro přihlášené
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.


Jan Lupčík:29.1.2017 8:27
Pouze vždy ověříš, zda je uživatel přihlášený, např. podle
$_SESSION
.
if (isset($_SESSION['user']) && $_SESSION['user'])
{
// ...
}
Tu podmínku můžeš použít jak při odesílání formuláře, tak při
jeho zobrazování.
Petr Langer:29.1.2017 13:28
Co jsem tak letmo proletěl onu knihu návštěv, tak by nejspíš stačilo udělat drobnou úpravu v při návrhu databáze. Konkrétně propojit tabulku články a komentáře. Nevím jak jsi v tomhle směru zdatný, tak se případně dál zeptej na to, co by ti nebylo jasný.
Petr Langer:29.1.2017 16:49
Jde o to, že budeš mít řekněme tabulku články a tabulku komentáře.
Jak teď ale poznáš, který komentář patří k jakému článku? Když to
vezmu stručně tak v tabulce komentáře budeš mít sloupeček id_clanku_FK
(cizí klíč), kterým budeš odkazovat na článek, ke kterému komentář
patří. Jestli si databázi navrhuješ přes phpMyAdmin, tak tam myslím ten
cizí klíč nastavit jde, ale nejsem si jistý. Lepší by bylo ho tam potom
přidat SQL příkazem na konci, ale to teď nebudeme řešit. Když už budeš
mít databázi hotovou, tak při zobrazení nějakého článku budeš znát
jeho ID z GET parametru, pak už jen stačí upravit dotaz do databáze tak, aby
načetl i komentáře, které mají id_clanku_FK stejné jako id_clanku, to se
dělá přes SQL pomocí JOIN.
Jinak můžeš postupovat podle návodu, jen při ukládání komentáře do DB
musíš uložit navíc to ID článku do id_clanku_FK (nebo jak si to
pojmenuješ) a při načítání to samé.
Ok, v tabulce mám sloupec pojmenovaný jako id_clanku_FK (mohl by jsi mi
prosím napsat ten sql dotaz, který je propojí?
Mám tabulky clanky se sloupcem clanky_id a chci mít cizí klíč v tabulce
nkniha ve sloupci id_clanku_FK
A zapisovaní dat do databáze takto:
<?php
session_start();
require('Db.php');
$spojeni = Db::connect('127.0.0.1', 'sokolmilicincz1', 'root', ''); //pripojeni k db
if (isset($_GET['clanek'])) //zobrazeni clanku
$url = $_GET['clanek'];
else
$url = 'uvod';
$clanek = Db::queryOne('
SELECT *
FROM clanky
WHERE url=?
', $url);
if (!$clanek) //pokud se nenalezne clanek, tak 404
{
if ($url != 'chyba')
{
header('Location: index.php?clanek=chyba');
exit();
}
else
die('Nebyl nalezen chybovy clanek');
}
if (isset($_GET['odhlasit']))
{
session_destroy();
header('Location: index.php');
exit();
}
function zabezpec($retezec)
{
return Db::quote($retezec);
}
?>
<!DOCTYPE html>
<html lang="cs-cz">
<head>
<meta charset="utf-8" />
<meta name="description" content="<?= htmlspecialchars($clanek['popisek']) ?>" />
<meta name="keywords" content="<?= htmlspecialchars($clanek['klicova_slova']) ?>" />
<link rel="stylesheet" href="styl.css" type="text/css"/>
<link rel=stylesheet href="style_blue.css" id=css>
<link rel=stylesheet href="print.css" media="print">
<title><?= htmlspecialchars($clanek['titulek']) ?></title>
<script src="js/rozklikavaci_menu.js"></script>
<script src="js/switcher.js"></script>
<script src="js/checkform.js"></script>
</head>
<body>
<header>
<div id="logo"><img src="obrazky/sokolMale.png" alt="logo"></div>
<nav>
<ul>
<li class="aktivni"><a href="index.php">Domů</a></li>
<li><a href="sport.php">Sport</a></li>
<li><a href="kultura.php">Kultura</a></li>
<li><a href="fotogalerie.php">Fotogalerie</a></li>
<li><a href="dokumenty.php">Dokumenty</a></li>
<li><a href="historie.php">Historie</a></li>
<?php
if (!isset($_SESSION['id'])) {
echo '<a href="prihlaseni.php" class="login">Přihlášení</a>';
} else {
echo '<a href="index.php?odhlasit" class="login">Odhlásit</a>';
echo '<a href="#" class="login">'.htmlspecialchars($_SESSION['uzivatel_jmeno']).'</a>';
}
?>
</ul>
</nav>
</header>
<div id="centrovac">
<article>
<header>
<h1><?= htmlspecialchars($clanek['titulek']) ?></h1>
</header>
<section>
<?= $clanek['obsah'] ?>
</section>
<div class="cistic"></div>
</article>
</div>
<?php
if (!isset($_SESSION['id'])) {
echo 'Pro komentování článků se prosím <a href="prihlaseni.php">přihlašte</a>';
}
else
{
** if (isset($_POST['autor']) AND isset($_POST['obsah'])) {
$data_insert['autor'] = zabezpec($_POST['autor']);
$data_insert['datumvlozeni'] = DATE("Y-m-d");
$data_insert['obsah'] = zabezpec($_POST["obsah"]);
Db::insert("nkniha", $data_insert);**
}
}
?>
<div id="komentare">
<form action="" method="post" name="formular">
Vaše jméno:<br>
<input type="text" name="autor" maxlength="30" size="30" required pattern="[0-9A-Za-z]{3,}" title="Minimální délka jména musí být tři znaky." accesskey="j"><br>
Váš vzkaz:<br>
<textarea name="obsah" rows="7" cols="50" wrap="soft" required pattern="[0-9A-Za-z]{2,}" title="Vzkaz musí být delší více jak tři znaky"></textarea><br>
<input type="submit" value="Ulož do knihy">
</form>
</div>
<footer>
<a href="prihlaseni.php">Administrace</a>
</footer>
</body>
</html>
Nevím teď úplně teď, jakým způsobem bych měl získat to ID článků, jak jsi o tom mluvil... :/
Petr Langer:30.1.2017 12:55
ID článku bys měl mít v $clanek['clanky_id']. Pro získání komentářů by ti pak měl stačit dlaší dotaz:
$komentare = Db::queryAll('
SELECT *
FROM komentare
WHERE id_clanku_FK=?
', $clanek['clanky_id']);
Zkouším to tedy nejdříve jednoduše - vypsat všechny komentáře, které se v tabulce nkniha vyskytují takto:
$spojeni = Db::connect('127.0.0.1', 'sokolmilicincz1', 'root', ''); //pripojeni k db
$vysledek= mysqli_query($spojeni, "SELECT * FROM nkniha ORDER BY id DESC");
while ($radek=mysqli_fetch_array($vysledek)):
echo '<p><b>'.$radek['autor'].'</b> ';
echo '('.$radek['datumvlozeni'].')<br>';
echo $radek['obsah'].'</p>';
endwhile;
A vyhodí mi to chyby
mysqli_query() expects parameter 1 to be mysqli, null given in
mysqli_fetch_array() expects parameter 1 to be mysqli_result, null
Chápu asi správně, že ta druhá chyba souvisí s tou první a ta první říká, že proměnné nejsou definovány - což pravda není, si myslím. Proměnnou $spojeni definuji již na začátku
Vubec netestujes, jestli se pripojila db, jestli probehla spravne ta query a
pak zachazis s vysledkem jako kdyby vse bylo vzdy ok... spojeni uz mas na
zacatku souboru, tak mozna to mas 2x, pak v te query na cteni formularu mas
ORDER BY id, ale pises, ze PK se jmenuje clanky_id.
Pak k tomu formulari name=formular - chybi tam id clanku pro komentar - coz asi
pujde pouzit primo z promenne $clanek[id] :
$data_insert['id_clanku_FK'] = $clanek['clanky_id'];
Petr Langer:30.1.2017 16:58
Nevím proč najednou používáš mysqli a ne PDO wrapper, který jsi používal předtím. Zkus
$komentare = Db::queryAll('SELECT * FROM KOMENTARE');
foreach $komentare as $komentar {
echo $komentar['nazevSloupceKVypsani'];}
Jenom si tam doplň název toho sloupce tak jak ho máš pojmenovaný v databázi a pak by se ti měli vypsat všechny komentáře za sebou.
Je to tak
Už se to vypisuje pod sebou i dokonce podle těch cizích klíčů - akorát bych měl ještě dvě otázky
- Pokud stisknu F5, odešle se znovu ten formulář a udělá se duplicitní příspěvek - dá se tomu nějak zabránit?
- Nějak jsem nepřišel na to, jak by to mělo fungovat, aby mohli komentovat pouze přihlášení uživatelé. Ten kód teď vypadá takto
<?php
if (!isset($_SESSION['id'])) {
echo 'Pro komentování článků se prosím <a href="prihlaseni.php">přihlašte</a>';
}
else
{
if (isset($_POST['autor']) AND isset($_POST['obsah'])) {
$data_insert['autor'] = zabezpec($_POST['autor']);
$data_insert['datumvlozeni'] = DATE("Y-m-d");
$data_insert['obsah'] = zabezpec($_POST["obsah"]);
$data_insert['id_clanku_FK'] = $clanek['clanky_id'];
Db::insert("nkniha", $data_insert);
}
}
$komentare = Db::queryAll('SELECT * FROM nkniha WHERE id_clanku_FK=? ORDER BY id DESC', $clanek['clanky_id']);
foreach ($komentare as $komentar) {
echo '<p><b>'. $komentar['autor']. '</b> ';
echo '<p><b>'. $komentar['datumvlozeni']. '</b> ';
echo '<p><b>'. $komentar['obsah']. '</b> ';
}
'<form action="index.php" method="post" name="formular">
Vaše jméno:<br>
<input type="text" name="autor" maxlength="30" size="30" required pattern="[0-9A-Za-z]{3,}" title="Minimální délka jména musí být tři znaky." accesskey="j"><br>
Váš vzkaz:<br>
<textarea name="obsah" rows="7" cols="50" wrap="soft" required title="Vzkaz musí být delší více jak tři znaky"></textarea><br>
<input type="submit" value="Ulož do knihy">
</form>'
?>
</div>
Myslel jsem si, že ten if udělá to, že pokud není uživatel
přihlášen, vypíše mu to pouze text "Pro komentování se prosím
přihlašte " a pokud je přihlášen (čili ta podmínka není splněna), tak
se mu zobrazí ten celý formulář. Teď to funguje tak, že se mu žádný
formulář nezobrazí
Petr Langer:30.1.2017 19:07
Ad 1) Ten formulář můžeš zpracovat v jinym scriptu (to změníš v
atributu action ve formuláři) a pak to zase přesměrovat zpátky.
Ad 2) Před tim formulářem ti nejspíš chybí echo a navíc je až za ifem
takže se pak zobrazí vždycky. Musíš ho přesunout do toho else.
- Jak to přesně myslím v jiném skriptu? změním v atributu action třeba na stranka zpracovani.php a tam přepíšu to zpracování formuláře?
- Jasně, mi to funguje
Nicméně kdybych chtěl, aby se mi automaticky ukládalo do databáze jméno uživatele, který je zrovna přihlášen (tj. kdybych byl přihlášen jako "user", nemohl bych se u komentáře vyplnil žádné jméno - rovnou by mi to uložilo do db jako autora "user")?
Petr Langer:30.1.2017 20:19
- Přesně tak.
- Přidej si do formuláře skrytej input a rovnou do něj vlož jméno přihlášenýho uživatele ze session. V tom scriptu kterym to budeš zpracovávat už to jen uložíš do databáze. Fungovat by to mělo ale z pohledu databáze to nebude úplně dobře, ale to by bylo na delší diskuzi a nakonec by stejně bylo nejlepší začít úplně od začátku a hlavně si nejdřív nastudovat, jak se navrhuje databáze
mkores.mk:30.1.2017 21:05
Ok, takže to mám zatím takhle
else
{
if (isset($_POST['autor']) AND isset($_POST['obsah'])) {
$data_insert['autor'] = $uzivatel['uzivatel_jmeno'];
$data_insert['datumvlozeni'] = DATE("Y-m-d");
$data_insert['obsah'] = zabezpec($_POST["obsah"]);
$data_insert['id_clanku_FK'] = $clanek['clanky_id'];
Db::insert("nkniha", $data_insert);
}
echo '<form action="index.php" method="post" name="formular">
Vaše jméno: ';
echo htmlspecialchars($_SESSION['uzivatel_jmeno']).'<br>
<input type=hidden name=';
$uzivatel = htmlspecialchars($_SESSION['uzivatel_jmeno']).'
><br>';
echo 'Váš vzkaz:<br>
<textarea name="obsah" rows="7" cols="50" wrap="soft" required></textarea><br>
<input type="submit" value="Ulož do knihy">
</form>';
}
$komentare = Db::queryAll('SELECT * FROM nkniha WHERE id_clanku_FK=? ORDER BY id DESC', $clanek['clanky_id']);
foreach ($komentare as $komentar) {
echo '<p><b>Autor: </b>'. $komentar['autor'];
echo 'Datum: '. $komentar['datumvlozeni'];
echo '<p><b>Text: </b>'. $komentar['obsah'];
}
?>
Nicméně úplně si nejsem teď jist, jak mám ze session předat databázi
toho uživatele - mám to takto $data_insert['autor'] =
$uzivatel['uzivatel_jmeno'];
a to mi nefunguje
Petr Langer:30.1.2017 21:12
<input type="hiden" name="jmeno" value=".$_SESSION['uzivatel_jmeno'].">
Snad nějak takhle, píšu z mobilu a nejsem si úplně jistej
Jo, to jo, já jsem myslel spíše co bude v tom zpracovani.php
Tohle tam bude?
session_start();
require('Db.php');
$spojeni = Db::connect('127.0.0.1', 'sokolmilicincz1', 'root', ''); //pripojeni k db
if (isset($_POST['autor']) AND isset($_POST['obsah'])) {
$data_insert['autor'] = Db::quote($_POST['autor']);
$data_insert['datumvlozeni'] = DATE("Y-m-d");
$data_insert['obsah'] = Db::quote($_POST["obsah"]);
$data_insert['id_clanku_FK'] = $clanek['clanky_id'];
Db::insert("nkniha", $data_insert);
Ten předchozí příspěvek ignoruj
Mám tedy na indexu takto napsán formulář
<?php
if (!isset($_SESSION['id'])) {
echo 'Pro komentování článků se prosím <a href="prihlaseni.php">přihlašte</a>';
}
echo '<form action="zpracovani.php" method="post" name="formular">
Vaše jméno: ';
echo htmlspecialchars($_SESSION['uzivatel_jmeno']).'<br>
<input type=hidden name="autor" value='.
htmlspecialchars($_SESSION['uzivatel_jmeno']).'
><br>';
echo 'Váš vzkaz:<br>
<textarea name="obsah" rows="7" cols="50" wrap="soft" required></textarea><br>
<input type="submit" value="Odeslat">
<input type="hidden" name="clanky_id" value='. $_SESSION[$clanek] .'
</form>';
$komentare = Db::queryAll('SELECT autor, datumvlozeni, obsah FROM nkniha WHERE id_clanku_FK=? ORDER BY id DESC', $clanek['clanky_id']);
foreach ($komentare as $komentar) {
echo '<p><b>Autor: </b>'. $komentar['autor'];
echo ' Datum: '. $komentar['datumvlozeni'];
echo '<p><b>Text: </b>'. $komentar['obsah'];
}
?>
A na zpracovani.php to vypadá takto:
<?php
session_start();
require('Db.php');
$spojeni = Db::connect('127.0.0.1', 'sokolmilicincz1', 'root', ''); //pripojeni k db
if (isset($_POST['autor']) AND isset($_POST['obsah'])) {
$data_insert['autor'] = Db::quote($_POST['autor']);
$data_insert['datumvlozeni'] = DATE("Y-m-d");
$data_insert['obsah'] = Db::quote($_POST["obsah"]);
$data_insert['id_clanku_FK'] = DB::quote($_POST["clanky_id"]);
Db::insert("nkniha", $data_insert);
header("index.php");
exit;
}
?>
V pořádku mi to zapisuje do databáze text i autora, ale nezapisuje si to id_clanku_FK (mám tam pravděpodobně chybu v tom předání mezi index.php a zpracovani.php)
Petr Langer:31.1.2017 14:15
Protože ho neposíláš tim formulářem. Udělej to stejně jako s tím jménem tzn. přes skrytej input. $clanek['clanky_id'] by měla bejt proměnná ve který je uložený.
Takže to mám takto:
else
{
echo '<form action="zpracovani.php" method="post" name="formular">
Vaše jméno: ';
echo htmlspecialchars($_SESSION['uzivatel_jmeno']).'<br>
<input type=hidden name="autor" value='.
htmlspecialchars($_SESSION['uzivatel_jmeno']).'
><br>';
echo 'Váš vzkaz:<br>
<textarea name="obsah" rows="7" cols="50" wrap="soft" required></textarea><br>
<input type="submit" value="Odeslat">
<input type=hidden name="clanky_id" value='.
htmlspecialchars($_SESSION['clanky_id;']).'
><br>';' </form>';
Ale stále mi to píše - přitom si myslím, že je to stejné jako to
jméno
Notice: Undefined index: clanky_id; in C:\xampp\htdocs\web\index.php on line
114
Petr Langer:31.1.2017 15:51
Ty tam máš $_SESSION['clanky_id'] (navíc tam máš středník, který tam být nemá), ale to ID článku načítáš někde na začátku společně se všema údajema toho konkrétního článku z databáze do pole $clanek. Tohle pole je asociativní, takže pomocí klíče, který se píše do těch hranatých závorek můžeš přistupovat k jednotlivým atributům toho článku. Ty chceš jeho ID a to je pod klíčem 'clanky_id' (aspoň podle těch kódů co jsi poslal dřív jsem tak usoudil), takže místo
$_SESSION['clanky_id;']
napiš
$clanek['clanky_id']
Jasně, už to chápu.
Ale v tom zpracovani.php to bude už s
DB::quote($_POST["clanky_id"])
Protože jsem to obdržel od formuláře.
Stále mi to nicméně nefunguje, do databáze se zapisuje id_clanky jako 0 - přitom pokud si tam vyhodím někde echo $clanek['clanky_id'], tak mi to píše id: 8 (což je správně)...
session_start()
$_SESSION["jmeno"] = "jmeno uzivatele po prihlaseni";
if (!empty($_SESSION["jmeno"])) {
//kod
}
Petr Langer:31.1.2017 18:58
Zkontroluj názvy proměnných. Konkrétně jestli v DB nemáš id_clanky a v kódu clanky_id
Nene, opravdu tam mám clanky_id. Když třeba nahradím $clanek['titulek'] pravě tím $clanek['clanky_id'], vypíše mi to správně ID toho článku. Nemohl by být problém v tom zpracování? Aktuálně ho mám takto:
<?php
session_start();
require('Db.php');
$spojeni = Db::connect('127.0.0.1', 'sokolmilicincz1', 'root', ''); //pripojeni k db
if (isset($_POST['autor']) AND isset($_POST['obsah'])) {
$data_insert['autor'] = Db::quote($_POST['autor']);
$data_insert['datumvlozeni'] = DATE("Y-m-d");
$data_insert['obsah'] = Db::quote($_POST['obsah']);
$data_insert['id_clanku_FK'] = DB::quote($_POST['clanky_id']);
Db::insert("nkniha", $data_insert);
header('Location: index.php');
exit;
}
?>
A takto je ten formulář
echo '<form action="zpracovani.php" method="post" name="formular">
Vaše jméno: ';
echo htmlspecialchars($_SESSION['uzivatel_jmeno']).'<br>
<input type=hidden name="autor" value='.
htmlspecialchars($_SESSION['uzivatel_jmeno']).'
><br>';
echo 'Váš vzkaz:<br>
<textarea name="obsah" rows="7" cols="50" wrap="soft" required></textarea><br>
<input type="submit" value="Odeslat">
<input type=hidden name="clanky_id" value='.
htmlspecialchars($clanek['clanky_id']). '
><br>';
'</form>';
Zkus do té podmínky dát tenhle kód
Db::query('
INSERT INTO nkniha (autor, datumvlozeni, obsah, id_clanku_FK)
VALUES (?, ?, ?, ?,)
',$_POST['autor'], DATE("Y-m-d"), $_POST['obsah'], $_POST['clanky_id']);
pak už mě napadá jen že je něco špatně v databázi. Jestli ti to nepůjde tak sem napiš jaký sloupečky máš v tabulce nkniha a jakýho jsou datovýho typu.
Petr Langer:31.1.2017 19:47
V tom zpracování máš if, tak co je vevnitř smaž kromě toho headeru a vlož tam to co jsem psal
Takže by to mělo být takto?
<?php
session_start();
require('Db.php');
$spojeni = Db::connect('127.0.0.1', 'sokolmilicincz1', 'root', ''); //pripojeni k db
if (isset($_POST['autor']) AND isset($_POST['obsah'])) {
Db::query('
INSERT INTO nkniha (autor, datumvlozeni, obsah, id_clanku_FK)
VALUES (?, ?, ?, ?,)
',$_POST['autor'], DATE("Y-m-d"), $_POST['obsah'], $_POST['clanky_id']);
header('Location: index.php');
exit;
}
?>
Vyhodí mi to error
Warning: PDO::prepare(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 2 in C:\xampp\htdocs\web\Db.php on line 42
Fatal error: Uncaught Error: Call to a member function execute() on boolean in C:\xampp\htdocs\zwa - project\Db.php:43 Stack trace: #0 C:\xampp\htdocs\zwa - project\Db.php(53): Db::executeStatement(Array) #1 C:\xampp\htdocs\web\zpracovani.php(10): Db::query('\r\n ...', 'admin', '2017-01-31', 'Ahoj', '8') #2 {main} thrown in C:\xampp\htdocs\webt\Db.php on line 43
Petr Langer:31.1.2017 19:56
Napiš jak vypadá ta tabulka v databázi do který to ukládáš.
Petr Langer:31.1.2017 20:06
Teď koukám, že na tom řádku s otazníkama je na konci jedna čárka navíc. Zkus jí odmazat jestli to nebylo tím.
+20 Zkušeností
+2,50 Kč

Petr Langer:31.1.2017 20:16
Nevím, to co jsi používal ty je pro mě neznámý způsob práce s databází. Taky jsem začínal na zdejším NERS, kde se používá PDO a to používám pořád.
Ve zpracovani.php mas na konci funkci header, tak tam musis dat misto index jmeno souboru s clankem a doplnit ho o identifikaci aktualniho clanku
Zobrazeno 42 zpráv z 42.