Prepared Statements. Bind value for IN clause, eg.:
$array_of_ids = array(1,2,3,4);
$array_of_ids = ArrayHelper::toInteger($array_of_ids);
$array_of_ids = $db->q($array_of_ids);
$ids = implode(',', $array_of_ids);
...
->where($db->qn('id') .' IN (:ids)')
...
->bind(':ids', $ids, ParameterType::STRING)
Return data for all IDs.
Returns data only for first ID.
Apache, MySQL, Joomla! 4
Probably $ids string in quoted somewhere on binding / execution.
Labels |
Removed:
?
|
Labels |
Added:
No Code Attached Yet
|
@pioada Just 2 questions: Why do you quote the IDs and use the string type? Are they stored as string in database? Otherwise if your code shall work with both database drivers MySQLi and MySQL (PDO), or even with PostgreSQL, you should use the integer type. And why do you use ArrayHelper::toInteger? Isn't it already an array of integers?
Besides that, as @joomdonation correctly pointed out you can use whereIn
with the array directly.
Another way would be to do it like here: https://github.com/joomla/joomla-cms/blob/4.0-dev/libraries/src/MVC/Model/AdminModel.php#L1478
->where($db->quoteName('id') . ' IN (' . implode(',', $query->bindArray(array_values($array_of_ids))) . ')'
(The array_values
is only needed if the array elements are not indexed by 0,1, 2, ..., e.g. if an element has been removed from the array so it besomes an associated list.)
So or so I think you see your mistake: You should use either bindArray
or whereIn
(which also binds as array).
P.S.: The short named aliases q
and qn
should not be used anymore in J4, They still work, but they are deprecated. You should use quote
and quoteName
.
P.P.S.: Let us know if our comments helped you to solve your issue so we can close it here, or close it yourself. Thanks in advance.
@richard67 Data comes from form, should be integers but it can be anything. You're right, quoting is unnecessary.
whereIn and where + bindArray works fine. In AdminModel.php#L1478 look few lines up or down. There is code like:
$where[] = $db->quoteName('key') . ' = :oldKey';
$query->bind(':oldKey', $oldKey);
This is what I try to use / do.
Meybe my first example is too simple and therefore confusing.
Extended example:
...
->where($db->qn('id') .' IN (:ids)'),
->where($db->qn('some_col') .' = :some_value')
...
foreach ($somethings as $something) {
->bind(':ids', $ids, ParameterType::STRING), <- string because I don't see a better type
->bind(':some_col', $some_value, ParameterType::INTEGER)
->execute();
}
:some_col + $some_value always works fine.
But when I try to do the same with IN clause it return only row for first ID. So if first ID is 1 then it will return row with id=1 but when first id is eg 4 then it return row for id=4. Should return all rows like it do for whereIn or where + bindArray.
I got same result when quote $ids in "standard" IN, eg:
$ids = implode(',', $ids);
->where($db->qn('id') .' IN ('. $ids .')')
I tlooks like ids given in ->bind(':ids', $ids, ParameterType::STRING) are quoted somewhere on bind or execute. But i dont know where exactly and i dont see way to prevent quoting.
BTW: Thanks for info about q / qn depreciation.
@pioada You still don't get that you can't use bind for an array, like you are trying to do with your ->bind(':ids', $ids, ParameterType::STRING)
. You have to use whereIn or where + bindArray. What I don't get is why you bind it again and again in your foreach loop which doesn't change the IDs array.
Anyway I do not see a bug here, so please check again and consider to close that issue and if necessary ask for further support in the support forum.
Thanks in advance.
My code is just example. This one is interesting: https://github.com/joomla/joomla-cms/blob/4.0-dev/libraries/src/MVC/Model/AdminModel.php#L1512
@pioada But you notice that in the example you linked above the $id is a single value from an array as being used in the foreach loop, so it is one string value, while in all your previous examples and in the description of this issue, you tried to bind an array as string.
Summary. It can be whereIn, where + bindArray.
This code will work as well:
$keys = array(':id1',':id2',':id3',':id4');
$values = array(1,4,3,4);
...
->where($db->quoteName('field_id') .' IN ('. implode(',', $keys) .')')
...
->bind($keys, $values, ParameterType::INTEGER)
Got everything i needed. Thanks. Closing.
Status | New | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2021-10-22 07:27:20 |
Closed_By | ⇒ | richard67 |
Your code could be replaced with the below one line of code: