You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent firstOrCreate在Linux服务器失效,本地Windows正常

解决Laravel firstOrCreate在Linux服务器上的SQL语法错误问题

问题分析

你遇到的问题是firstOrCreate在Linux服务器上抛出SQLSTATE[HY000]: General error: 2036异常,核心原因是生成的SQL中字符串类型的字段(ip_address和data)没有被正确添加引号,导致数据库无法识别合法的查询语法。而Windows本地环境正常,大概率是环境间的PHP类型处理差异或MySQL配置差异(比如严格模式)导致的。

从你提供的实际执行SQL可以看到:

select * from search_histories where (ip_address = 27.34.72.242 and data = {"address":"Surry Hills, New South Wales, Australia","radius":"10",...}) limit 1

这里ip_address被当作数值处理(无引号),data的JSON字符串也没有被包裹引号,完全不符合SQL语法规范。

解决方法

1. 强制转换字段值为字符串类型

显式将ip_address和data的值转换为字符串,确保Laravel的查询构造器将它们识别为字符串参数,自动添加引号:

// 强制转换IP为字符串,避免被识别为数值
$ipAddress = (string) request()->ip();
// 生成JSON字符串并确保类型为string,防止类型歧义
$queryData = (string) json_encode(request()->query(), JSON_UNESCAPED_UNICODE);

$search = SearchHistory::firstOrCreate(
    [
        'ip_address' => $ipAddress,
        'data' => $queryData
    ],
    [
        'user_id' => auth()->id() ?? 0,
        'user_agent' => request()->userAgent()
    ]
);

2. 检查数据库字段类型(可选优化)

如果你的data字段设计为MySQL的JSON类型,建议直接传入数组而非json_encode后的字符串,Laravel会自动处理JSON字段的查询逻辑,避免手动编码可能带来的问题:

$search = SearchHistory::firstOrCreate(
    [
        'ip_address' => (string) request()->ip(),
        'data' => request()->query() // 直接传数组,Laravel自动生成合法的JSON查询
    ],
    [
        'user_id' => auth()->id() ?? 0,
        'user_agent' => request()->userAgent()
    ]
);

3. 验证MySQL sql_mode配置(辅助排查)

检查Linux服务器上的MySQLsql_mode设置,确保没有过于严格的模式导致语法错误被放大(虽然这不是根本原因,但可以辅助确认环境差异):

SELECT @@sql_mode;

如果包含STRICT_TRANS_TABLES等严格模式,可临时调整测试,但不建议长期关闭严格模式,最好从代码层面规范类型处理。

为什么Windows环境正常?

Windows下PHP对字符串类型的判断可能更宽松,或者本地MySQL的sql_mode未启用严格语法检查,使得不规范的SQL(无引号字符串)侥幸执行成功。但这种写法本身存在隐患,必须从代码层面规范类型处理。

内容的提问来源于stack exchange,提问作者Sanish Gurung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:34:10