Vícenásobný where v akci presenteru
- wicked
- Člen | 290
Zdravím přátelé,
na webu využívám vyhledávání (jeden formulář s 5 poličky) který odesílám takto
$values = $form->getValues();
$q = $values;
$this->redirect("hledat", array(
'firma' => $q->firma,
'jmeno' => $q->jmeno,
'ic' => $q->ic,
'prijmeni' => $q->prijmeni,
'dic'=> $q->dic,
'mesto' => $q->mesto
));
Následně v akci je zpracovávám
public function actionHledat($firma, $jmeno) {
$firma = $this->zakaznici->findAll()->where("firma LIKE ?", $firma OR "jmeno LIKE ?", $jmeno);
if (!$firma->count()) {
$this->flashMessage ("Zákazník dle parametrů nenalezen!", "alert alert-danger");
$this->redirect("default");
}
$firma = $firma->fetch();
$this->template->q = $firma;
}
Pokud uvedu v 1. radku akce jenom firmu, vše se zobrazi, ale jakmile to
necham takto, dostavám
Argument count does not match placeholder count
Co dělám špatně?
Mám ještě pred oslanim kontrolovat, zda je pole vyplněno?
Děkuji
EDIT:
ted mám toto
$firma = $this->zakaznici->findAll()->where("firma = ? OR jmeno = ?", $firma, $jmeno);
Ale neprojde kdyz nemam vyplnene jmeno, respektive
Column operator does not accept NULL argument
Editoval wicked (17. 8. 2014 14:14)
- David Matějka
- Moderator | 6445
za foo = ?
nemuzes do parametru dosadit NULL
, musi
to byt foo IS NULL
. Ale stejne nepredpokladam, ze bys chtel
filtrovat ... OR firma IS NULL
, takze bych spis kontroloval, ktere
policka jsou nastaveny a dle toho sestavil podminku do where
- wicked
- Člen | 290
matej21 napsal(a):
za
foo = ?
nemuzes do parametru dosaditNULL
, musi to bytfoo IS NULL
. Ale stejne nepredpokladam, ze bys chtel filtrovat... OR firma IS NULL
, takze bych spis kontroloval, ktere policka jsou nastaveny a dle toho sestavil podminku do where
Takže to bych musel už upravit funkci na odeslaní
public function hledatFormSucceeded($form) {
// Nacteme data z formulare
$values = $form->getValues();
$q = $values;
$this->redirect("hledat", array(
'firma' => $q->firma,
'jmeno' => $q->jmeno,
'ic' => $q->ic,
'prijmeni' => $q->prijmeni,
'dic'=> $q->dic,
'mesto' => $q->mesto
));
}
O to, že jestli je pole vyplneno, predej jej, ale jak potom v actionHledat zjistim, ktere pole jsou predana?
- David Matějka
- Moderator | 6445
ne, v tom action kontroluj, co je nastaveno a co ne…
Editoval matej21 (17. 8. 2014 14:38)
- David Matějka
- Moderator | 6445
bohuzel NDB na to asi nema zadnej helper, budes to muset udelat rucne, treba:
$cond = array();
if($firma !== NULL) {
$cond["firma = ?"] = $firma;
}
...
$...->where(implode(" OR ", array_keys($cond)), $cond);
- wicked
- Člen | 290
matej21 napsal(a):
bohuzel NDB na to asi nema zadnej helper, budes to muset udelat rucne, treba:
`
php
$cond = array();
if($firma !== NULL) {
$cond[„firma = ?“] = $firma;
}
…
$…->where(implode(" OR ", array_keys($cond)), $cond);
Tak jsem to zkusil udělat jak jsi psal, ale …
public function actionHledat($firma, $jmeno) {
$cond = array();
if ($firma !== NULL) {
$cond["firma = ?"] = $firma;
} elseif($jmeno !== NULL) {
$cond["jmeno = ?"] = $jmeno;
}
$firma = $this->zakaznici->findAll()->where(implode(" OR ", array_keys($cond)), $cond);
if (!$firma->count()) {
$this->flashMessage ("Zákazník dle parametrů nenalezen!", "alert alert-danger");
$this->redirect("default");
}
$firma = $firma->fetch();
$this->template->q = $firma;
}
> ```
A skončím na
**Column operator does not accept array argument**
Což chápu, že práce s poly nejde ...
- David Matějka
- Moderator | 6445
ach, tam je v sql builderu debilni (vlastne tam byt musi… no
i kdyz…) podminka :\
takze budes muset udelat:
//$cond bude stejny
$firma = $this->zakaznici->findAll();
array_unshift($cond, implode(" OR ", array_keys($cond)));
call_user_func_array(array($firma, 'where'), $cond);
a btw, dej si to z presenteru do toho repozitare se zakaznikama.. metodu treba findByFilter a posli tam pole s filtrem…
Editoval matej21 (17. 8. 2014 16:01)
- wicked
- Člen | 290
matej21 napsal(a):
ach, tam je v sql builderu
debilni(vlastne tam byt musi…) podminka :\
takze budes muset udelat://$cond bude stejny $firma = $this->zakaznici->findAll() array_unshift(implode(" OR ", array_keys($cond)), $cond); call_user_func_array(array($firma, 'where'), $cond);
a btw, dej si to z presenteru do toho repozitare se zakaznikama.. metodu treba findByFilter a posli tam pole s filtrem…
Tak tohle jde mimo mě … vůbec to nechápu …
btw, ani to nejde, respektivě:
syntax error, unexpected ‚array_unshift‘ (T_STRING)
A kdyz udělam misto středníků → tak
Call to undefined method
Nette\Database\Table\Selection::array_unshift().
- David Matějka
- Moderator | 6445
chybel mi tam za findAll() strednik… doplnil jsem to
Editoval matej21 (17. 8. 2014 15:34)
- wicked
- Člen | 290
matej21 napsal(a):
chybel mi tam za findAll() strednik… doplnil jsem to
Promin, ze jsem otravny, ale jelikoz tomu nerozumim, tak si nemuzu pomoc…
Doplnil jsem stredniky ale …
Only variables should be passed by reference
Ted to je takto
public function actionHledat($firma, $jmeno) {
$cond = array();
if ($firma !== NULL) {
$cond["firma = ?"] = $firma;
} elseif ($jmeno !== NULL) {
$cond["jmeno = ?"] = $jmeno;
}
$firma = $this->zakaznici->findAll();
array_unshift(implode(" OR ", array_keys($cond)), $cond);
call_user_func_array(array($firma, 'where'), $cond);
if (!$firma->count()) {
$this->flashMessage("Zákazník dle parametrů nenalezen!", "alert alert-danger");
$this->redirect("default");
}
$firma = $firma->fetch();
$this->template->q = $firma;
}
Nezlob se a dekuji
- David Matějka
- Moderator | 6445
sorry, prohodil jsem poradi argumentu do array_unshift :) uz jsem to tam opravil…
- David Matějka
- Moderator | 6445
1. vytvoris to pole $cond
, to bude pote obsahovat treba:
$cond = array(
"firma = ?" => 'foo',
"jmeno = ?" => 'bar',
);
2. pomoci implode se spojeji klice do podminky
firma = ? OR jmeno = ?
3. tohle se pomoci array_unshift da jako prvni prvek pole
4. a call_user_func_array zavola onu fci where na onom objektu s parametry v
$cond
, takze je to jako volani
->where('firma = ? OR jmeno = ?', 'foo', 'bar');
Editoval matej21 (17. 8. 2014 16:18)
- wicked
- Člen | 290
matej21 napsal(a):
1. vytvoris to pole
$cond
, to bude pote obsahovat treba:$cond = array( "firma = ?" => 'foo', "jmeno = ?" => 'bar', );
2. pomoci implode se spojeji klice do podminky
firma = ? OR jmeno = ?
3. tohle se pomoci array_unshift da jako prvni prvek pole
4. a call_user_func_array zavola onu fci where na onom objektu s parametry v$cond
, takze je to jako volani->where('firma = ? OR jmeno = ?', 'foo', 'bar');
Asi … to začínám chápat :-)
Zjistim jeste vic infa ohledne tech funkcí.
Každopádně děkuji ;)
- wicked
- Člen | 290
Mám další dotaz …
DOufám, že mi s ním pomůžete.
Jak jsem tu pomohl @matej21 s tím výtahem z DB …
Musel jsem DB předělat tak, že mám
zakaznici
id
firma
id
dic
a
zakaznici_kontakt
id
zakaznici_id
atd …
Samozdrejmne spojene FK zakaznici_id → zakaznici.id
Jen mě není jasné, jak bych měl ten script upravit aby to fungovalo stále jako vyhledávání.
Ve výpisu mě je to jasné, spojil jsem to ve foreach related…
ale jak to udělat tu?
Děkuji
EDIT:
Ještě druhá věc, když chci data z DB spojit abych pak mohl naplnit formulář pro editaci, dle dokumentace jsem to udělal takto
$zakaznici = $this->zakaznici->findAll()->where("id", $id);
$zakaznici->where('zakaznici_kontakty.zakaznici_id ?', $id);
Ale to mě píše že nebylo nic nalezeno
No reference found for $zakaznici->zakaznici_kontakty
Měl jsem za to, že to je jako join
EDIT2
postup
mam toto
$zakaznici = $this->zakaznici->findAll()->where("id", $id);
$zakaznici->where(':zakaznici_kontakty.zakaznici_id ?', $id)
->group('zakaznici.id')
->having('COUNT(:zakaznici.id)', $id);
Vytvori to dotaz
SELECT `zakaznici`.*
FROM `zakaznici`
LEFT JOIN `zakaznici_kontakty` AS `zakaznici` ON `zakaznici`.`id` = `zakaznici`.`zakaznici_id`
WHERE (`id` = '172') AND (`zakaznici_kontakty`.`zakaznici_id` = '172')
GROUP BY `zakaznici`.`id`
HAVING COUNT(`zakaznici`.`id`) 172
Ale dostanu chybuSQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: ‚zakaznici‘
Editoval wicked (24. 8. 2014 16:35)
- ludek
- Člen | 83
Tohle je skutečně funkční způsob jak operativně upravovat
WHERE
dotaz s podmínkami OR
a třeba i
LIKE
. Když chci podmínky AND
, můžu si dotaz
libovolně skládat. Prostě připisuju WHERE
a ono se mi
to spojí.
$hledat = 'slovo';
$hledej = $this->database->table('spisy');
$hledej->where('nazev LIKE ?', '%'.$hledat.'%';
$hledej->where('popis LIKE ?', '%'.$hledat.'%';
$hledej->where('misto LIKE ?', '%'.$hledat.'%';
$this->template->vysledek = $hledej;
mi udělá:
SELECT * FROM `spisy` WHERE `nazev` LIKE '%slovo%' AND `popis` LIKE '%slovo%' AND `misto` LIKE '%slovo%';
Jenomže když chci hledat s OR
jsem v háji. Musel bych napsat
snad jedině:
$hledej = $this->database->table('spisy')
->where('nazev LIKE ? OR popis LIKE ? OR misto LIKE', '%'.$hledat.'%', '%'.$hledat.'%', '%'.$hledat.'%');
A co když těch polí k prohledání je mnohem víc? A co když předem nevím, která chci prohledat?
Jde to teda udělat takto:
$hledat = 'slovo';
// Pole s podmínkami si sestavím podle potřeby, třeba ho v nějakém cyklu podle situace vygeneruju.
// na ukázku:
$podminky = array(
"nazev LIKE ?" => '%'.$hledat.'%',
"popis LIKE ?" => '%'.$hledat.'%',
"misto LIKE ?" => '%'.$hledat.'%',
"neco_dalsiho LIKE ?" => '%nejake_jine_slovo%'
);
Teď je třeba pole upravit tak, aby bylo vhodné pro PHP příkaz
call_user_func_array()
.
Ten zavolá na připraveném objektu $hledej
funkci
where
a předá jí za sebou parametry v poli
$podminky
.
Jako první musí být popis podmínky se zástupnými otazníčky, za tím
dosazované parametry.
První popisný parametr sestavím pomocí implode
, kdy pospojuju
názvy klíčů (array_keys
).
A dopředu ho přešoupnu příkazem array_unshift
.
// sestavím první parametr:
$prvni = implode(" OR ", array_keys($podminky));
// zapíšu jako první prvek toho stejného pole
array_unshift($podminky, $prvni);
// jestli nevěříte, dumpněte si to
// dump($podminky);
// a předhodím hotové pole ke zpracování funkcí `where`:
$hledej = $this->database->table('spisy');
call_user_func_array(array($hledej, 'where'), $podminky);
$this->template->vysledek = $hledej;
A ono to fakt udělá:
SELECT *
FROM `spisy` WHERE (`nazev` LIKE '%slovo%' OR `popis` LIKE '%slovo%' OR `misto` LIKE '%slovo%' OR `neco_dalsiho` LIKE '%nejake_jine_slovo%');
Davidu Matějkovi velký dík.