Autor Zpráva
kopi
Profil
Dobrý den,
formulářem odesílám zaškrtnuté checkboxy. Name checkboxu dávám do pole.
<input type='checkbox' name=checkbox[".$model['id']."]>

zpracování formuláře
if(isset($_POST['filtr']) && isset($_POST['checkbox']) && is_array($_POST['checkbox']))
{
foreach ($_POST['checkbox'] as $id_auta) 
{
  $auto = $id_auta;
}
}

A ted potřebuju sestavit dotaz na SELECT WHERE id = $auto. Myslím ale, že přes cyklus foreach to nepůjde?

Děkuji za radu
Alphard
Profil
Spojujete AND nebo OR? Z kontextu bych hádal něco jako
'... where id_auta in ('.implode(', ', $_POST['checkbox']). ')'
(Tohle je bezpečnostní díra, hodnoty v poli by se měly ověřit.)
kopi
Profil
Mělo by se to spojovat s OR. Ověřením polí myslíte takhle?
if (isset($_POST['checkbox']) && $_POST['checkbox'] !== '') {
    $auto ='".mysqli_real_escape_string($link, $_POST['checkbox'])."';
blaaablaaa
Profil
kopi:
Na ty hodnoty nejlepe pouzit array_map (a predtim array_keys pro ziskani id modelu) a pokud to maji byt integery, tak treba intval. Pak viz Alphard.
kopi
Profil
mohli byste mi ještě poradit, jak to dát do cyklu? Cyklem projíždím ty odeslané checkboxy a to sestavení dotazu má být až pod tím cyklem?
juriad
Profil
if (isset($_POST['checkbox']) && $_POST['checkbox'] !== '') {
  $podminky[] = 'id_auta IN (' . implode(', ', array_map(function($id) {
    return intval($id);
  }, $_POST['checkbox'])) . ')';
}

Vyznačenou část si nahraď svým řešením. Když je víc různých podmínek, tak je ukládám podmínky do pole, a pak je spojím dohromady:
$sql = 'SELECT * FROM tabulka';
if (!$empty($podminky)) {
  $sql .= ' WHERE ' . implode(' AND ', $podminky);
}
kopi
Profil
já se omlouvám, asi jsem natvrdlej, ale tohle, co jste mi napsal mám dát do toho cyklu foreach? nebo do toho cyklu patří jen
$podminky[] = 'id_auta IN (' . implode(', ', array_map(function($id) {
    return intval($id);
juriad
Profil
kopi:
Žádný cyklus není potřeba, on je totiž skrytý v tom implode.
Pozn. zkopíroval jsi jen dva řádky ze tří, ta anonymí funkce musí být ukončená:
}, $_POST['checkbox'])) . ')';

Předpokládejme, že máš filtr, který v HTML vypadá:
<form>
  <input type="checkbox" name="id_auta[]" value="0">
  <input type="checkbox" name="id_auta[]" value="1">
  <input type="checkbox" name="id_auta[]" value="2">
  <input type="checkbox" name="id_auta[]" value="3">
  <input type="checkbox" name="id_auta[]" value="4">
  
  <input type="checkbox" name="typ[]" value="osobak">
  <input type="checkbox" name="typ[]" value="dodavka">
  <input type="checkbox" name="typ[]" value="nakladak">
  <input type="checkbox" name="typ[]" value="trikolka">
  
  <input type="number" name="vek" value="osobak">
  ...
</form>

Pak takový formulář můžeš snadno zpracovat v PHP takto:
$sql = "SELECT * FROM auta";
$podminky = [];

if (isset($_POST['id_auta']) && is_array($_POST['id_auta']) && count($_POST['id_auta']) > 0) { # pokud je vyplněné alespoň jedno auto_id
  $podminky[] = 'id_auta IN (' . implode(', ', array_map(function($id) { # spojíme čárkami hodnoty, které jsou ...
    return intval($id); # čísla
  }, $_POST['id_auta'])) . ')';
}

if (isset($_POST['typ']) && is_array($_POST['typ']) && count($_POST['typ']) > 0) { # pokud je vyplněný alespoň jeden typ
  $podminky[] = 'typ IN (' . implode(', ', array_map(function($typ) use ($link) { # spojíme čárkami hodnoty, které jsou ...
    return "'" . mysqli_real_escape_string($link, $typ) . "'"; # escapované řetězce v apostrofech
  }, $_POST['typ'])) . ')';
}

if (isset($_POST['vek'])) { # pokud byl vyplněný věk
  $podminky[] = 'vek > ' . intval($POST['vek']); # ukázka; třeba porovnáme s číslem
}

if (!$empty($podminky)) { # pokud existuje alespoň jedna podmínka
  $sql .= ' WHERE ' . implode(' AND ', $podminky); # spojíme podmínky ANDem
}

... = mysqli_query($sql); # spustíme dotaz


Když to rozeberu, protože jsi se asi ještě nesetkal s předáváním funkce další funkci:
implode(', ', array_map(function($typ) use ($link) { # spojíme čárkami hodnoty, které jsou ...
    return "'" . mysqli_real_escape_string($link, $typ) . "'"; # escapované řetězce v apostrofech
  }, $_POST['typ']))

Zavolá implode (implode vkládá první argument mezi každé dva po sobě jdoucí prvky druhého argumentu; například: implode('@', ['a', 'b', 'c']) vrátí "a@b@c")
- 1. paramer: řetězec obsahující čárku (", ")
- 2. parametr: pole, které je výsledkem funkce array_map (array map vezme pole a provede nějakou funkci s každým prvkem; například: array_map([1.1, 3.6, 2.3], 'round') vrátí pole [1, 4, 2].
- - 1. parametr: funkce; v dávných verzích PHP se mohl předávat jen název funkce, v nových můžeš přímo předat definici funkce. V tomto případě ta funkce je „closure“, říkáš o ní, že používá kromě svých argumentů ještě proměnnou $link. Tato funkce je volána pro každý prvek pole a vrací „novou hodnotu“.
- - 2. pole $_POST['id_auto']

$mysqlStringParam = function($str) use ($link) {
  return "'" . mysqli_real_escape_string($link, $typ) . "'";
}
$mysqlStringParam("a'bc") vrátí: "'a\'bc'"

Pokud se říkáš, že na řádkách 5, 6, 7 jsem mohl místo definování funkce přímo předat název funkce intval jako řetězec, pak máš pravdu. :-)


Můžeš si sám zkusit naprogramovat funkci implode (to je jednoduché, na pár řádků), a funkci array_map (to už je složitější, potřebuješ použít call_user_func).
kopi
Profil
Děkuju za vyčerpávající odpověď :-) zkusím to. A když nevím, kolik těch checkboxu bude, protože se načítají z db, tak to na tom filtru nic nemění? Proto jsem tam porad hledal nějaký cyklus, kterým projedu všechny odeslané checkboxy.
juriad
Profil
kopi:
Ten cyklus je schovaný ve funkci implode. Zkus si jí sám naprogramovat, mělo by to zabrat maximálně pár minut. Pak ti bude jasnější, co se tam děje. Můj příklad (ta první část v [#6]) je rozšířením Alphardova řešení, které je doplněné o escapování.

Jak jsem zmínil na konci svého příspěvku, napsal jsem to zbytečně složitě, v případě čísel to jde zjednodušit na:
if (isset($_POST['checkbox']) && $_POST['checkbox'] !== '') {
  $podminky[] = 'id_auta IN (' . implode(', ', array_map('intval', $_POST['checkbox'])) . ')';
}
kopi
Profil
SUPÉÉÉR! tak se mi to povedlo rozchodit, konečně tak jak má :) děkuju, že si tam uvedl všechny příklady. dlouho mi trvalo zjistit, proč mi to nejde, když jsem tam měl intval() a posílal jsem řetězec :-)

Mám jen ještě jeden technický dotaz, potřebuju za ten sql dotaz $sql .= ' WHERE ' . implode(' OR ', $podminky); dát podmínku limit kvůli stránkování. Ale pořád tam mám nějakou syntaktickou chybu. ztrácím se mezi všemi těmi uvozovkami a apostrofy. Potřebuju tam nacpat ještě ... and stav=aktivni ORDER BY id Desc limit ' .$start.','.$PZS.
juriad
Profil
Vypiš si proměnnou $sql a snad uvidíš, kde je chyba.
Mimochodem, opravdu chceš podmínky ORovat? Pokud ano, tak bys někde mělo použít závorky protože A OR B AND C se vyhodnotí jako A OR (B AND C), a tedy by to kritérium na stav byla aplikované jen pro poslední podmínku. Pozor také na to, že když žádná podmínka neexistuje, tak nemůžeš přidávat AND.
kopi
Profil
udělal jsem tedy spojení pomocí AND. proměnnou $sql mi to vypisuje správně tak, jak si ji napsal ty. Jakmile někam přidám další podmínky jako je limit, tak to hodí syntax error. když tam dám ... and stav=aktivni, hodí mi to unnexpected '='. Fakt netuším, jak to tam mám zakomponovat
juriad
Profil
Ukaž kus kódu, ve kterém je ta chyba (pár řádek nad a pod, ať máme kontext).
kopi
Profil
už se mi to podařilo udělat správně. měl jsem místo uvozovky postrof. Ukázala se další komplikace. Když odešlu formulář, tak všechno funguje správně, vytvoří se stránkování také správně, ale pak když kliknu na druhou stránku, tak už tam vlastně není znovu odeslaný ten formulář a flitr se zruší. Přemýšlel jsem, že bych ten filtr mohl nějakým způsobem uložit do $_SESSION['filtr']? Nebo je to blbost? Jak jinak udržet hodnoty filtru v průběhu stránkování?
juriad
Profil
kopi:
Do SESSION je to nevhodné, protože uživatel může chtít mít otevřené dvě různé stránky s filtry, a ty by se navzájem ovlivňovaly (existuje jen jedna SESSION).
V tvém případě bych formulář změnil na method="GET" a udržoval si celý filtr v URL. Každý odkaz ve stránkování by obsahoval všechny zadané parametry. Toto je také výhodné k tomu, že si může uživatel uložit stránku s filtrem do oblíbených, může jí někomu poslat, funguje spolehlivě refresh stránky.
kopi
Profil
ok, děkuju. Mám se hoooodně co učit. Ještě jednou díky

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

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

0