Autor Zpráva
kuba95
Profil
Zdravím,
mám formulář s checkboxy ukázka a potřebuji, aby se mi databáze změnila podle toho, co upravím ve formuláři. Aby pokud nějaký checkbox zaškrtnu, se zapsala jednička do buňky v SQL tabulce (to mi funguje) ale nevím jak udělat, aby se mi napsala nula když checkbox odškrtnu.

Prosím o radu, jak na to.

Kód formuláře a následného zpracování:
<?

$dhost             = "****"; //usually localhost, or ip
$dusername         = "****"; // database user
$dpassword         = "****"; // database pass
$ddatabase         = "****"; // database name

$con = mysql_connect($dhost, $dusername, $dpassword) or die("Cannot Connect");         ////
mysql_select_db($ddatabase, $con);

mysql_query("SET CHARACTER SET utf8");

echo "<h3>Editace aktuálního stav zkoušení</h3>";

if ($_POST) {

foreach($_POST["checkbox"] as $index => $hodnota){
$explodename = explode("§", $hodnota);

$query = "UPDATE exams SET $explodename[1]='1' WHERE user='$explodename[0]'";
mysql_query($query) or die(mysql_error());


}
echo "Hotovo";
}

echo "
<form method=\"post\" action=\"#\">
<table border=\"2\" style=\"table-layout: fixed; border-collapse: collapse;\">
<tr>
<td>Jméno</td>";

$querp = mysql_query("SELECT * FROM predmety ORDER BY id ASC");
while ($rowp = mysql_fetch_array($querp)) {

echo "<td align=\"center\" valign=\"middle\">$rowp[zkratka]</td>";
}

echo "</tr>";

$quere = mysql_query("SELECT * FROM exams ORDER BY user ASC");

while ($rowe = mysql_fetch_array($quere)) {

$queru = mysql_query("SELECT * FROM users WHERE id = $rowe[user]");
$rowu = mysql_fetch_array($queru);

echo "<tr><td>$rowu[name]</td>";

$quer0 = mysql_query("SELECT * FROM predmety ORDER BY id ASC");
while ($row0 = mysql_fetch_array($quer0)) {

$quer2 = mysql_query("SELECT * FROM exams WHERE user = $rowe[user]");
$row2 = mysql_fetch_array($quer2);

echo "<td align=\"center\" valign=\"middle\">";

if ($row2[$row0[id]] == 1) {

echo "<input type=\"checkbox\" name=\"checkbox[]\" value=\"$rowe[user]§$row0[id]\" checked />";
} else {
echo "<input type=\"checkbox\" name=\"checkbox[]\" value=\"$rowe[user]§$row0[id]\" />";
}
echo "</td>";

}
echo "</tr>";
}
echo "</table>
<br />
<input type=\"submit\" value=\"Upravit\" />
</form>";
?>
Camo
Profil
kuba95:
1.Checkboxom daj do value názov stĺpca ku ktorému sa viažu.
2.Pri spracovaní musíš vytiahnuť názvy stĺpcov z tabuľky do poľa.
3.Prejdeš to pole čo vytiahneš z DB(teda nie POST) a porovnáš či existuje taká hodnota v poli POST. Ak existuje tak nastavíš 1 ak nie tak 0.
4.Problém je v tom, že nevieš robiť normálny update. Ty pre každú jednu položku v cykle robíš query. To je blbosť. V cykle máš iba zostaviť reťazec dotazu. A až po cykle urobiť jediný dotaz.
5.Dávaj do kódu značky \n na koniec riadkov(v HTML výstupe), aby sa dal aj čítať. Aby to nebolo všetko na jednom riadku.
kuba95
Profil
Camo:
díky za radu... Ale nechápu, jak mám vyřešit toto:

4.Problém je v tom, že nevieš robiť normálny update. Ty pre každú jednu položku v cykle robíš query. To je blbosť. V cykle máš iba zostaviť reťazec dotazu. A až po cykle urobiť jediný dotaz.

Mohl bys mi dát nějaký příklad?

Díky
Camo
Profil
kuba95:
Skutočnosť je taká, že som si pomýlil insert s updatom. Ale ak by som sa chcel tváriť ako frajer, tak ťa odkážem na mysqli->multi_query().
Tak to urob ako chceš. U multiquery je trochu zložitejšie spracovanie výsledku a chýb.
kuba95
Profil
Ten post jsem upravil takhle, ale pořád mi to nefunguje a nevim, co na tom je špatně... Prosím někoho o radu...

if ($_POST) {

$querp = mysql_query("SELECT * FROM predmety ORDER BY id ASC");
while ($rowp = mysql_fetch_array($querp)) {                    // vypsání názvů sloupců

$queru = mysql_query("SELECT * FROM users ORDER BY id ASC");
while ($rowu = mysql_fetch_array($queru)) {

foreach($_POST["checkbox"] as $index => $hodnota){
$explodename = explode("§", $hodnota);


if ($rowp[id] == $explodename[1] && $rowu[id] == $explodename[0]) {

$query = "UPDATE exams SET $rowp[id]='1' WHERE user='$explodename[0]'";
mysql_query($query) or die(mysql_error());

} else {

$query = "UPDATE exams SET $explodename[1]='0' WHERE user='$explodename[0]'";
mysql_query($query) or die(mysql_error());

}
}
}
}
echo "Hotovo";
}
Tori
Profil
kuba95:
K tomuto:
foreach($_POST["checkbox"] as $index => $hodnota){
$explodename = explode("§", $hodnota);
if ($rowp[id] == $explodename[1] && $rowu[id] == $explodename[0]) { ....
- zbytečně procházíte celé pole. Bylo by lepší vytvářet checkboxy tak, aby identifikátor předmětu+žáka byl jako index:
echo "<input type=\"checkbox\" name=\"checkbox[".$rowe['user'].'§'.$row0['id']."]\" value=\"1\" />";
Tím vám vznikne něco jako $_POST['checkbox']['1§Aj'] => 1 a místo procházení všech checkboxů můžete použít isset:
// místo řádků 7-15 v [#5]
while ($rowu = mysql_fetch_array($queru)) {
    $idZkousky = $rowu['id'] . '§' . $rowp['id']; 
    if (isset($_POST['checkbox'][$idZkousky])) {
        mysql_query("UPDATE exams SET $rowp[id]='1' WHERE user='$rowp[id]'");
    } else {
        mysql_query("UPDATE exams SET $rowp[id]='0' WHERE user='$rowp[id]'");
    }
}

Zkuste prosím používat lepší (= výstižnější) názvy proměnných, bude se v tom (i nám) lépe orientovat. Tj. např. $rowp změnit na $subject, $rowu$user apod. (A případně to sjednotit na jen češtinu nebo jen angličinu.)

A až vám tohle bude fungovat, tak by to chtělo změnit návrh databáze, aby vypadala spíš takto:

-- tabulka users
id | jmeno
1 | admin

-- tabulka subjects
id | kod | 
1 | Aj
2 | Čj
3 | Ch

-- tabulka exams
id_user | id_subject | grade
1 | 3 | 1
1 | 1 | 1
-- z češtiny ještě nemá zkoušku, takže ten záznam tu vůbec není. Anebo tam i může být, ale se známkou 0, jak chcete.
Má to následující výhody:
- při přidávání / odebrání předmětu nemusíte měnit strukturu tabulky exams
- celou strukturu tabulky s checkboxy můžete získat jedním dotazem (teď to nelze, protože se nedá propojit hodnota DB buňky s názvem sloupce)
kuba95
Profil
Děkuji Vám oběma za rady, už mi to funguje :)

Kdyby to někoho zajímalo, tak tady je výsledek:

<?
 
$dhost             = "****"; //usually localhost, or ip
$dusername         = "****"; // database user
$dpassword         = "****"; // database pass
$ddatabase         = "****"; // database name
 
$con = mysql_connect($dhost, $dusername, $dpassword) or die("Cannot Connect");         ////
mysql_select_db($ddatabase, $con);
 
mysql_query("SET CHARACTER SET utf8");
 
echo "<h3>Editace aktuálního stav zkoušení</h3>";

if ($_POST) {

$subjectList0 = mysql_query("SELECT * FROM subjects ORDER BY id ASC");
while ($subjectList = mysql_fetch_array($subjectList0)) {                    

$userList0 = mysql_query("SELECT * FROM users ORDER BY id ASC");
while ($userList = mysql_fetch_array($userList0)) {
    $idExam = $userList['id'] . '§' . $subjectList['id']; 
    if (isset($_POST['checkbox'][$idExam])) {
        $examExist0 = mysql_query("SELECT * FROM exams WHERE user = '$userList[id]' AND subject = '$subjectList[id]'");
        $examExist = mysql_num_rows($examExist0);

    if ($examExist == 0) {
        mysql_query("INSERT INTO exams(user, subject, done) VALUES ('$userList[id]','$subjectList[id]','1')");
        }
    } else {
    mysql_query("DELETE FROM exams WHERE user = '$userList[id]' AND subject = '$subjectList[id]'");
    
    }
}
}
echo "Hotovo";
}

echo "
<form method=\"post\" action=\"?action=editexams\">
<table border=\"2\" style=\"table-layout: fixed; border-collapse: collapse;\">
<tr>
<td>Jméno</td>\n";

$subjectList0 = mysql_query("SELECT * FROM subjects ORDER BY id ASC");
while ($subjectList = mysql_fetch_array($subjectList0)) {

echo "<td align=\"center\" valign=\"middle\">$subjectList[shortcut]</td>\n";
}

echo "</tr>\n";

$user0 = mysql_query("SELECT * FROM users ORDER BY id ASC");
while ($user = mysql_fetch_array($user0)) {

echo "\n<tr><td>$user[name]</td>";

$subject0 = mysql_query("SELECT * FROM subjects ORDER BY id ASC");
while ($subject = mysql_fetch_array($subject0)) {

$done0 = mysql_query("SELECT done FROM exams WHERE user = '$user[id]' AND subject = '$subject[id]' ");
$done = mysql_fetch_array($done0);

echo "\n<td align=\"center\" valign=\"middle\">";

if ($done > 0) {
echo "<input type=\"checkbox\" name=\"checkbox[".$user['id'].'§'.$subject['id']."]\" value=\"1\" checked />";
} else {
echo "<input type=\"checkbox\" name=\"checkbox[".$user['id'].'§'.$subject['id']."]\" value=\"1\" />";
}
echo "</td>";

}
echo "</tr>";
}
echo "
</table>
<br />
<input type=\"submit\" value=\"Upravit\" />
</form>";
?>
Tori
Profil
Pěkně. :)

Ještě dvě drobnosti:
1) Na tabulce exams by měl být primární klíč přes oba sloupce (user + subject). Je potřeba jednak pro zrychlení dotazů, a taky abyste neměl duplicitní řádky. (Píšu jen pro jistotu, asi už jste ho tam dal.) S tímhle klíčem můžete pak vynechat select na ř.24 a v případě zaškrtnutého checkboxu prostě použít:

if (isset($_POST['checkbox'][$idExam])) {
        mysql_query("INSERT IGNORE INTO exams(user, subject, done) VALUES ('$userList[id]','$subjectList[id]','1')");
    } else {
        mysql_query("DELETE FROM exams WHERE user = '$userList[id]' AND subject = '$subjectList[id]'");
    }
Pokud záznam s toutéž kombinací ID žáka+předmětu už existuje, nevloží se.
Ještě to můžete vylepšit podle toho, co radil Camo - tj. použít jen jeden hromadný insert:
// před cyklem načnete dotaz
$sql = 'insert ignore into exams (user, subject, done) values ';
$values = '';
while (...) {
    $values .= "('$userList[id]','$subjectList[id]','1') , "; // čárka na konci odděluje hodnoty pro jednotlivé řádky
}
// za cyklem vyhodíte přebytečnou poslední čárku a složíte dotaz
if (!empty($values)) {
    mysql_query($sql . rtrim($values, ', '));
}

2) Zkuste si spustit tenhle dotaz, jestli by nešel použít místo těch tří vnořených. Píšu z hlavy, tak nevím, jestli to bude fungovat jak chci. ID uživatelů a předmětů jsou aliasované, aby se nepřepisovaly navzájem.

select s.*, u.*, s.id as subject_id, u.id as user_id, ifnull(e.done, 0) as done
from users u
cross join subjects s
left join exams e on u.id = e.user and s.id = e.subject
order by u.id, s.id
Při výpise byste pak využil stejný princip jako tady: Nejčastější potíže s PHP (FAQ) » Nadpis skupiny nejen při výpisu z databáze (na zalomení do řádků tabulky).

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: