A brief description of the issue goes here.
Environment
| Package |
Version |
| bolt/core |
6.1.8 |
| symfony/framework-bundle |
6.4.46 |
| doctrine/orm |
3.7.1 |
| doctrine/dbal |
4.4.4 |
| PHP |
8.2.13 |
| Database |
MariaDB 10.4 |
Upgraded from Bolt 5.1.24. Same behaviour on a freshly cleared cache.
Description
A setcontent query that filters a content field with multiple values
(|| or &&) fails with:
Too many parameters: the query defines 3 parameters and you bound 4
The same syntax on a system field (e.g. status) works fine, so the
problem seems specific to how field filters are turned into DQL.
The number of declared parameters stays constant no matter how many values
are passed, while the number of bound parameters grows with each value. That
suggests the multi-value filter binds one parameter per value, but the DQL it
produces only ever contains a single placeholder for that field.
Steps to reproduce
ContentType with a plain select field:
blog:
fields:
jezik:
type: select
required: true
multiselect: false
values:
hr: 'Croatian'
en: 'English'
hren: 'Both'
Then run any of these:
{% setcontent records = 'blog' where { jezik: 'hr || hren' } latest limit 1 %}
Results
┌─────────────────────────────────┬───────────────────────────────────────┐
│ Query │ Result │
├─────────────────────────────────┼───────────────────────────────────────┤
│ { jezik: 'hr || hren' } │ fails — defines 3 parameters, bound 4 │
├─────────────────────────────────┼───────────────────────────────────────┤
│ { jezik: 'hr || hren || en' } │ fails — defines 3 parameters, bound 5 │
├─────────────────────────────────┼───────────────────────────────────────┤
│ { jezik: 'hr && hren' } │ fails — defines 3 parameters, bound 4 │
├─────────────────────────────────┼───────────────────────────────────────┤
│ { jezik: 'hr' } │ works │
├─────────────────────────────────┼───────────────────────────────────────┤
│ { status: 'published || held' } │ works (system field) │
├─────────────────────────────────┼───────────────────────────────────────┤
│ no filter │ works │
└─────────────────────────────────┴───────────────────────────────────────┘
Expected: all of the above return records.
Actual: every multi-value filter on a content field throws.
Notes
- Reproduced through Bolt\Storage\Query::getContent() directly, so it is not
template-specific.
- Ruled out a project-level decorator of Bolt\Storage\Directive\OrderDirective
— the failure is identical with the decorator removed, and with no ordering
in the query at all.
- Bolt\Storage\QueryParameterParser::multipleValueHandler() builds one
placeholder per value and calls $filter->setParameters() with all of them,
so the mismatch most likely appears further down, where the field filter is
joined onto the query. I have not traced it past that point.
Workarounds used
- Two separate setcontent queries merged in Twig.
- Where the field has a small closed set of values, negation of the complement
('!en' instead of 'hr || hren') — single parameter, works.
A brief description of the issue goes here.
Environment
Upgraded from Bolt 5.1.24. Same behaviour on a freshly cleared cache.
Description
A
setcontentquery that filters a content field with multiple values(
||or&&) fails with:Too many parameters: the query defines 3 parameters and you bound 4
The same syntax on a system field (e.g.
status) works fine, so theproblem seems specific to how field filters are turned into DQL.
The number of declared parameters stays constant no matter how many values
are passed, while the number of bound parameters grows with each value. That
suggests the multi-value filter binds one parameter per value, but the DQL it
produces only ever contains a single placeholder for that field.
Steps to reproduce
ContentType with a plain select field:
Then run any of these:
{% setcontent records = 'blog' where { jezik: 'hr || hren' } latest limit 1 %}Results
Expected: all of the above return records.
Actual: every multi-value filter on a content field throws.
Notes
template-specific.
— the failure is identical with the decorator removed, and with no ordering
in the query at all.
placeholder per value and calls $filter->setParameters() with all of them,
so the mismatch most likely appears further down, where the field filter is
joined onto the query. I have not traced it past that point.
Workarounds used
('!en' instead of 'hr || hren') — single parameter, works.