whereOr nad n LIKE pro jeden sloupec

Tečník
Člen | 18
+
0
-

Zdravím,

potřebuji najít záznamy, které vyhovují něčemu takovému:

select * from table where column like '%string1%' or column like '%string2%' or column like '%string3%' or ...

Zkoušel jsem to udělat pomocí whereOr, ale nevím, jak to správně napsat, když se hledá stále nad stejným sloupcem.

Mějme tedy následující:

$words = ["a", "b", "c"];

$selection = $this->database->table('table');

Napadlo mě vycpávat klíč pole mezerami, ale nepřijde mi to moc pěkné.

foreach ($words as $key => $word) {
	$query['column LIKE ?'.str_repeat(" ", $key)] = "%$word%";
}

$sources->whereOr($query);

Nenapadne prosím někoho nějaké lepší řešení, jak se to dá pomocí whereOr udělat?

h4kuna
Backer | 740
+
0
-

Takto jsi to zkoušel?

foreach ($words as $word) {
	$sources->whereOr('column LIKE ?', "%$word%");
}

Editoval h4kuna (16. 10. 2018 8:17)

Tečník
Člen | 18
+
0
-

Tohle bohužel vrátí chybu Argument 1 passed to Nette\Database\Table\Selection::whereOr() must be of the type array, string given.

whereOr chce jako parametr pole viz https://api.nette.org/…lection.html#…

h4kuna
Backer | 740
+
+2
-

Omlouvám se, psal jsem z paměti, podcenil jsem dotaz. Stáhnul jsem si sandbox a celé si to odladil. Metoda whereOr rozparsuje pole a data připraví pro metodu where, takže to můžeme přeskočit a napsat si to sami, protože v tomto případě je problém s klíčem pole.

$words = ["a", "b", "c"];
$sources = $this->context->table('test');

$condition = '';
$parameters = [];
foreach ($words as $word) {
	if ($condition !== '') {
		$condition .= ' OR ';
	}
	$condition .= 'column LIKE ?';
	$parameters[] = "%$word%";
}

$sources->where($condition, $parameters);

Editoval h4kuna (16. 10. 2018 20:14)

Tečník
Člen | 18
+
0
-

Děkuji, takto nějak to použiji.

Díval jsem se ještě na vnitřek whereOr a ono by to mělo umět vzít pole plných dotazů indexované přes čísla.

[0 => "column LIKE '%a%'", 1 => "column LIKE '%b%'"]

Akorát to pak escapuje to, co je mezi procenty pomocí `, takže dotaz nevrátí, to co chci.
Zajímavé je, že např %ABCD% to neescapuje, ale jakmile tam je malé písmeno, tak jo.

Také to z nějakého důvodu přidá na konec IS NULL AND FALSE, čímž poslední podmínka zanikne

WHERE ((`column` LIKE '%`a`%') OR (`column` LIKE '%`b`%') IS NULL AND FALSE)

Nicméně beru, že je vhodnější psát dotazy s parametry, takže takto mi to zatím stačí.

Leda by někdy v budoucnu uměl whereOr brát něco jako

[0 => ['column LIKE ?' => '%a%'], 1 => ['column LIKE ?' => '%b%']]

Máte-li někdo vysvětlení toho escapování nebo přidávání IS NULL AND FALSE, rád se o tom dozvím víc.

Zapp3
Člen | 8
+
0
-

Nevím jak hezké řešení to je ale takto by ti to nemělo tu hodnotu escapovat, alespoň YetORM to nedělá

['column LIKE ?' => '%'.$value.'%']
Tečník
Člen | 18
+
0
-

Ano, takto to neescapuje, ale tím jsem zpět k mému původnímu řešení s vycpáváním klíče pole mezerami v případě, že chci, aby to whereOr správně pobral.

['column LIKE ?' => '%'.$values[0].'%',
 'column LIKE ? ' => '%'.$values[1].'%',
 'column LIKE ?  ' => '%'.$values[2].'%',
...]
kolsi
Člen | 131
+
0
-

Tečník napsal(a):
Máte-li někdo vysvětlení toho escapování nebo přidávání IS NULL AND FALSE, rád se o tom dozvím víc.

Taktéž by mě zajímalo, proč to přidává k poslední podmínce „IS NULL AND FALSE“. V dokumentaci o tom zmínku nevidím.

CZechBoY
Člen | 3608
+
0
-

Ta podmínka vzniká, když jako parametr předává prázdný pole.

kolsi
Člen | 131
+
0
-

Mám pouze:

->whereOr([ 'podminka1', 'podminka2' ])

Očekával bych výsledek:

WHERE podminka1 OR podminka2

Ale vznikne

WHERE podminka1 OR podminka2 IS NULL AND FALSE

Takže musím udělat nelogický výraz

->whereOr([ 'podminka1', 'podminka2', TRUE ])

Pak vznikne trochu blbá podmínka, která ale funguje tak, jak bych si to představoval

WHERE podminka1 OR podminka2 OR TRUE IS NULL AND FALSE
CZechBoY
Člen | 3608
+
0
-

Pošli co tam přesně máš, tohle se hodně špatně debuguje :-)

kolsi
Člen | 131
+
+1
-

Co se špatně debuguje? Není třeba dělat nic speciálního. Mám prostě jenom obyčejný kód:

$this->connection->table('device')->whereOr(['podminka1', 'podminka2'])->fetchAll();

A jeho výsledkem je:

SELECT *
FROM `device`
WHERE ((`podminka1`) OR (`podminka2`) IS NULL AND FALSE)

A mě zajímá, kde se tam vezme to „IS NULL AND FALSE“, když v dokumentaci o tom nevidím žádnou zmínku.

ludek
Člen | 83
+
+1
-

Zdravím, právě jsem narazil na stejný problém.

Nefungovalo mi vybírání pomocí whereOr a zjistil jsem, že z neznámých důvodů to na konec přidává ‚IS NULL AND FALSE‘, tzn. druhá podmínka neprojde.

Jako když where() dostane jako parametr prázdné pole (dokumentace).

$table->where('id', []);       // id IS null AND false

Nemůže to být chyba v sestavování dotazu uvnitř Nette Database?

Příklad:

//DUMP:
$whereOr = array (2)
0 => "ucet LIKE "%123456/2010%""
1 => "ucet LIKE "CZ%2010%123456""

$result = $repository->table('table')->whereOr($whereOr);
Výsledek:
SELECT *
FROM `table`
WHERE ((`ucet` LIKE "%123456/2010%") OR (`ucet` LIKE "CZ%2010%123456") IS NULL AND FALSE)

EDIT: Možná je to způsobeno prázdným polem $values = [], které se v metodě Database/Table/Selection.php whereOr předává při volání $this->where() i když se jedná o plně definované textové podmínky (whereOr(['full condition'])).

Editoval ludek (22. 3. 2019 12:18)