没有不值得去解决的问题,也没有不值得去学习的技术!

在 Spatie\QueryBuilder ,请求参数中包含 “,” 报错:SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

在 Spatie\QueryBuilder ,请求参数中包含 "," 报错:SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens (SQL: select count(*) as aggregate from `table` where `table`.`shipping_type` = 2 and `shipping_at_gmt` >= 2024-05-21 08:54:14 and `shipping_at_gmt`
1、在 Spatie\QueryBuilder ,请求参数中包含 “,” 报错:SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens (SQL: select count(*) as aggregate from `table` where `table`.`shipping_type` = 2 and `shipping_at_gmt` >= 2024-05-21 08:54:14 and `shipping_at_gmt` <= 2024-08-21 08:54:14 and `table`.`shipping_error_message` in (aaa))。如图1
在 Spatie\QueryBuilder ,请求参数中包含 "," 报错:SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens (SQL: select count(*) as aggregate from `table` where `table`.`shipping_type` = 2 and `shipping_at_gmt` >= 2024-05-21 08:54:14 and `shipping_at_gmt` <= 2024-08-21 08:54:14 and `table`.`shipping_error_message` in (aaa))。
图1
2、当请求参数 从 “aaa,bbbb” 修改为 “aaa” 后,SQL 不再报错。如图2
当请求参数 从 "aaa,bbbb" 修改为 "aaa" 后,SQL 不再报错
图2
3、查看生成的 SQL
<pre class="wp-block-syntaxhighlighter-code">

select
  count(*) as aggregate
from
  `table`
where
  `table`.`shipping_type` = 2
  and `shipping_at_gmt` >= '2024-05-21 09:00:21'
  and `shipping_at_gmt` <= '2024-08-21 09:00:21'
  and `table`.`shipping_error_message` in ('aaa')

</pre>
4、打印出处理后的查询和绑定的参数,检查是否所有参数都匹配 SQL 中的占位符。确认占位符 ? 有 3 个,绑定的参数有 4 个。根源在于 “aaa,bbbb” 因为是逗号间隔的缘故,被拆分为了 2 个绑定参数。如图3
打印出处理后的查询和绑定的参数,检查是否所有参数都匹配 SQL 中的占位符。确认占位符 ? 有 3 个,绑定的参数有 4 个。根源在于 "aaa,bbbb" 因为是逗号间隔的缘故,被拆分为了 2 个绑定参数。
图3


        print_r($builder->toSql());
        print_r($builder->getBindings());
        exit;


<pre class="wp-block-syntaxhighlighter-code">

select `table`.* from `table` where `shipping_at_gmt` >= ? and `shipping_at_gmt` <= ? and `table`.`shipping_error_message` in (?) order by `operated_at_gmt` descArray
(
    [0] => Illuminate\Support\Carbon Object
        (
            [endOfTime:protected] => 
            [startOfTime:protected] => 
            [constructedObjectId:protected] => 000000000000115d0000000000000000
            [localMonthsOverflow:protected] => 
            [localYearsOverflow:protected] => 
            [localStrictModeEnabled:protected] => 
            [localHumanDiffOptions:protected] => 
            [localToStringFormat:protected] => 
            [localSerializer:protected] => 
            [localMacros:protected] => 
            [localGenericMacros:protected] => 
            [localFormatFunction:protected] => 
            [localTranslator:protected] => 
            [dumpProperties:protected] => Array
                (
                    [0] => date
                    [1] => timezone_type
                    [2] => timezone
                )

            [dumpLocale:protected] => 
            [dumpDateProperties:protected] => 
            [date] => 2024-05-29 03:03:53.000000
            [timezone_type] => 3
            [timezone] => UTC
        )

    [1] => Illuminate\Support\Carbon Object
        (
            [endOfTime:protected] => 
            [startOfTime:protected] => 
            [constructedObjectId:protected] => 000000000000115e0000000000000000
            [localMonthsOverflow:protected] => 
            [localYearsOverflow:protected] => 
            [localStrictModeEnabled:protected] => 
            [localHumanDiffOptions:protected] => 
            [localToStringFormat:protected] => 
            [localSerializer:protected] => 
            [localMacros:protected] => 
            [localGenericMacros:protected] => 
            [localFormatFunction:protected] => 
            [localTranslator:protected] => 
            [dumpProperties:protected] => Array
                (
                    [0] => date
                    [1] => timezone_type
                    [2] => timezone
                )

            [dumpLocale:protected] => 
            [dumpDateProperties:protected] => 
            [date] => 2024-08-29 03:03:53.000000
            [timezone_type] => 3
            [timezone] => UTC
        )

    [2] => aaa
    [3] => bbbb
)


</pre>
5、决定在 Spatie\QueryBuilder 中禁用逗号(,)自动转换为数组的行为。参考:Is it possible to disable a delimiter for an allowed filter?  打印出处理后的查询和绑定的参数,检查是否所有参数都匹配 SQL 中的占位符。确认占位符 ? 有 3 个,绑定的参数有 3 个。符合预期。如图4
决定在 Spatie\QueryBuilder 中禁用逗号(,)自动转换为数组的行为。参考:Is it possible to disable a delimiter for an allowed filter? https://github.com/spatie/laravel-query-builder/discussions/756 打印出处理后的查询和绑定的参数,检查是否所有参数都匹配 SQL 中的占位符。确认占位符 ? 有 3 个,绑定的参数有 3 个。符合预期。
图4


$allowedFilters[] = AllowedFilter::exact($field, null, true, false);


<pre class="wp-block-syntaxhighlighter-code">

select `table`.* from `table` where `shipping_at_gmt` >= ? and `shipping_at_gmt` <= ? and `table`.`shipping_error_message` in (?) order by `operated_at_gmt` descArray
(
    [0] => Illuminate\Support\Carbon Object
        (
            [endOfTime:protected] => 
            [startOfTime:protected] => 
            [constructedObjectId:protected] => 000000000000115d0000000000000000
            [localMonthsOverflow:protected] => 
            [localYearsOverflow:protected] => 
            [localStrictModeEnabled:protected] => 
            [localHumanDiffOptions:protected] => 
            [localToStringFormat:protected] => 
            [localSerializer:protected] => 
            [localMacros:protected] => 
            [localGenericMacros:protected] => 
            [localFormatFunction:protected] => 
            [localTranslator:protected] => 
            [dumpProperties:protected] => Array
                (
                    [0] => date
                    [1] => timezone_type
                    [2] => timezone
                )

            [dumpLocale:protected] => 
            [dumpDateProperties:protected] => 
            [date] => 2024-05-29 05:54:56.000000
            [timezone_type] => 3
            [timezone] => UTC
        )

    [1] => Illuminate\Support\Carbon Object
        (
            [endOfTime:protected] => 
            [startOfTime:protected] => 
            [constructedObjectId:protected] => 000000000000115e0000000000000000
            [localMonthsOverflow:protected] => 
            [localYearsOverflow:protected] => 
            [localStrictModeEnabled:protected] => 
            [localHumanDiffOptions:protected] => 
            [localToStringFormat:protected] => 
            [localSerializer:protected] => 
            [localMacros:protected] => 
            [localGenericMacros:protected] => 
            [localFormatFunction:protected] => 
            [localTranslator:protected] => 
            [dumpProperties:protected] => Array
                (
                    [0] => date
                    [1] => timezone_type
                    [2] => timezone
                )

            [dumpLocale:protected] => 
            [dumpDateProperties:protected] => 
            [date] => 2024-08-29 05:54:56.000000
            [timezone_type] => 3
            [timezone] => UTC
        )

    [2] => aaa,bbbb
)


</pre>
6、当请求参数 是 “aaa,bbbb”,SQL 不再报错,符合预期。查看生成的 SQL。如图5
当请求参数 是 "aaa,bbbb",SQL 不再报错,符合预期。查看生成的 SQL
图5
<pre class="wp-block-syntaxhighlighter-code">

select
  count(*) as aggregate
from
  `table`
where
  `shipping_at_gmt` >= '2024-05-29 05:57:18'
  and `shipping_at_gmt` <= '2024-08-29 05:57:18'
  and `table`.`shipping_error_message` in ('aaa,bbbb')

</pre>

PHP / Laravel / Yii2 老项目维护与长期技术支持

如果你的 PHP / Laravel / Yii2 项目已经上线,但遇到原开发离职、Bug 长期无人修复、接口不稳定、性能下降、代码难以接手等问题,可以联系我做一次远程技术排查。

适合以下情况:
✅ 老旧 PHP 系统无人维护
✅ Laravel / Yii2 项目 Bug 修复
✅ 后台管理系统小功能迭代
✅ RESTful API 接口排查
✅ MySQL / Redis / Nginx 性能问题
✅ 长期远程兼职维护

可先从一次小问题开始:
✅ 线上报错排查
✅ 接口异常分析
✅ 慢查询与性能瓶颈定位
✅ 代码结构初步评估
✅ 部署环境与日志检查

如需咨询,请联系我,并注明:PHP 维护咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理