Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!
Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.
Pisze taki maly projekt na zaliczenie dla znajomego, ktory ma byc taka tablica ogloszen.
W sumie juz jest niemal skonczone (mimo ze pisanie w php z uzyciem sql, javascript i html jednoczesnie moze czasami zakrecic czlowiekiem ;-)) ale tak mi sie spodobala ta zabawa z php ze chcialem sam dla siebie sie dowiedziec jak to ma byc poprawnie zrobione.
Mianowicie chodzi o to jak poprawnie wysylac i przetwarzac formularze aby uchronic sie od glupich bledow w stylu wielokrotnego dodawania tych samych danych itp.
Tutaj teoria http://en.wikipedia.org/wiki/Post/Redirect/Get
tutaj reguly do tego wzorca z nastepnego wyniku google:
Never show pages in response to POST - nie pokazuj stron do ktorych dane sa wysylane metoda post
Always load pages using GET - zawsze laduj strony uzywajac metody get
Navigate from POST to GET using REDIRECT - przekieruj z post do get
Tak wiec ma to wygladac tak (na razie bez konkretnego kodu)
1)strona a z formularzem z metoda post i zabezpieczona np tym http://docs.jquery.com/Plugins/Validation
2)strona b, ktora niczego nie wyswietla a jedynie przetwarza (php) i przekierowuje do #3
3)strona c, ktora wyswietla podsumowanie tego co sie wydarzylo (informuje o ewentualnych bledach itp)
Teraz konkrety:
plik formtest.php
<?php require_once('doctype.php'); require_once('session.php'); require_once('head.php'); ?> <body> <div id="siteContain"> <?php require_once('siteheader.php'); ?> <div id="content"> <div id="leftMenu"> leftmenu </div> <div id="mainContent"> <form action="formtest_post.php" method="POST"> <label for="uname">Login</label><input type="text" name="uname" id="uname" /><br /> <label for="uemail">Email</label><input type="text" name="uemail" id="uemail" /><br /> <button type="submit">Wyślij</button> </form> </div> <div class="spacer"></div> </div> <div id="footer"><?php require_once('footer.php'); ?></div> </div> </body> </html>
plik formtest_post.php:
<?php if(isset($_POST['uname']) && isset($_POST['uemail']) && !empty($_POST['uname']) && !empty($_POST['uemail'])) { $mysqlhost = "localhost"; $mysqluser = "root"; $mysqlpass = ""; $mysqldb = "test"; $conn = mysql_connect($mysqlhost, $mysqluser, $mysqlpass); mysql_select_db($mysqldb) or die(); $adduserquery = "INSERT INTO uzytkownicy(name, email) VALUES(\"{$_POST['uname']}\", \"{$_POST['uemail']}\")"; $query_run = mysql_query("START TRANSACTION"); $query_run = mysql_query($adduserquery); $query_run =mysql_query("SELECT id FROM uzytkownicy ORDER BY id DESC LIMIT 1"); if(mysql_num_rows($query_run)) { $row = mysql_fetch_assoc($query_run); $id = $row['id']; mysql_free_result($query_run); } mysql_query("COMMIT"); mysql_close($conn); ($id)?(header("Location: formtest_get.php?id=$id")):(header("Location: formtest_get.php?id=0")); } ?>
plik formtest_get.php:
<?php require_once('doctype.php'); require_once('session.php'); require_once('head.php'); ?> <body> <div id="siteContain"> <?php require_once('siteheader.php'); ?> <div id="content"> <div id="leftMenu"> left </div> <div id="mainContent"> <?php if(isset($_GET['id']) && !empty($_GET['id'])) { echo $_GET['id']; } else { echo 0; } ?> </div> <div class="spacer"></div> </div> <div id="footer"><?php require_once('footer.php'); ?></div> </div> </body> </html>
ps wiem ze przyklad jest glupi ale nie chcialem zaciemniac a jedynie przedstawic idee
ps2 w tych dolaczonych plikach nie ma zadnej magii zwykly kod html cala logika jest zawarta w tym co widac
1) Dobrze to zrozumialem czy tez umknelo mi cos waznego?
2) W pliku formtest_post.php $query_run = mysql_query("START TRANSACTION"); blokuje tabele aby mozna w nastepnych zapytaniach dostac sie do wlasnie dodanego rekordu sa jakies lepsze sposoby aby to zrobic?
3) Jak wygenerowac "losowy lancych" w url, ktory zaprowadzi do takiego rekordu z bazy danych cos jakby zamiennik do tego mojego ?id=$id (miedzy innymi oprogramowanie tego forum generuje cos takiego po wyslaniu posta/u?)
Pozdrawiam
Offline
1) Chyba ok. Nie ma w tym wielkiej filozofii.
2) Żeby co zrobić? Inaczej zablokować tabele czy dostać rekord? Nie ma potrzeby używać transakcji by pobrać rekord, a tabele można zablokować na wiele sposobów zależnie od poziomu izolacji.
3) Wygeneruj przy zapisie, zapisz w bazie i po nim wyszukuj ;] Chyba, że forum używa jakiego odwracalnego algorytmu i nie musi zapisać wygenerowanego stringa.
http://forum.dug.net.pl/viewtopic.php?pid=226181#p226181 - toż to zwykłe id posta z bazy. Nic generowanego.
Offline
1) Zabezpieczenia po stronie klienta OK, ale po stronie serwera są ważniejsze. Poczytaj o mysql_real_escape_string lub mysqli::real_escape_string i "Magic Quotes"
2) Jak już pisał kamikaze, transakcja nie jest potrzebna do tego co starasz się osiągnąć. Jeśli chcesz tylko obrać id ostatnio dodanego wiersza wystarczy użyć mysql_insert_id lub mysqli::$insert_id. Żeby sprawdzić błędy w zapytaniu użyj mysql_error lub mysqli::$error
Offline
Time (s) | Query |
---|---|
0.00011 | SET CHARSET latin2 |
0.00004 | SET NAMES latin2 |
0.00149 | SELECT u.*, g.*, o.logged FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.ident='18.190.207.144' WHERE u.id=1 |
0.00091 | UPDATE punbb_online SET logged=1716173474 WHERE ident='18.190.207.144' |
0.00039 | SELECT * FROM punbb_online WHERE logged<1716173174 |
0.00075 | DELETE FROM punbb_online WHERE ident='85.208.96.212' |
0.00063 | SELECT topic_id FROM punbb_posts WHERE id=226188 |
0.00116 | SELECT id FROM punbb_posts WHERE topic_id=23080 ORDER BY posted |
0.00078 | SELECT t.subject, t.closed, t.num_replies, t.sticky, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, 0 FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=3) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=23080 AND t.moved_to IS NULL |
0.00008 | SELECT search_for, replace_with FROM punbb_censoring |
0.00127 | SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.topic_id=23080 ORDER BY p.id LIMIT 0,25 |
0.00117 | UPDATE punbb_topics SET num_views=num_views+1 WHERE id=23080 |
Total query time: 0.00878 s |