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

Laravel中使用DB::raw调用ST_GeomFromText更新几何字段报错

Laravel中更新几何字段报错排查与解决

问题背景

原生SQL操作几何数据完全正常:

  • 查询几何数据:SELECT ST_AsGeoJSON(geometry) from mma_embargos;
  • 插入几何数据:INSERT INTO mma_embargos (geometry) VALUES (ST_GeomFromText('POLYGON ((-55.18473 -6.884111, -55.183144 -6.889768,...'));
    几何数据可正确保存为二进制格式。

但在Laravel中使用updateOrCreate方法结合DB::raw传递ST_GeomFromText函数时,执行如下代码报错:

public static function updateOrCreate(
    string  $numTad,
    string  $document,
    int     $numProcess,
    array   $data,
    ?string $geometry
): IbamaMmaEmbargos
{
    return DB::transaction(function () use ($numTad, $document, $numProcess, $data, $geometry) {
        $embargo = MmaEmbargos::updateOrCreate(
            [
                'num_tad' => $numTad,
                'document' => $document,
                'num_processo' => $numProcess,
            ],
            $data,
        );

        if (isset($geometry)){
            $embargo->update(
                [
                    'geometry' => DB::raw("ST_GeomFromText('$geometry')")
                ]
            );
        }
        return $embargo;
    });
}

错误提示:

SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field (SQL: update mma_embargos set geometry = { }, mma_embargos.updated_at = 2023-12-11 12:49:37 where id = 1)

原因分析

  1. 字符串拼接导致SQL语法错误:直接将$geometry字符串嵌入DB::raw中,若几何数据包含单引号、换行等特殊字符,会破坏ST_GeomFromText的参数结构,导致数据库无法解析有效几何文本。
  2. 模型update方法的自动处理冲突:调用模型update方法时,Laravel的ORM层可能对DB::raw的解析逻辑异常,使得SQL函数未被正确执行,最终传递给数据库的是无效占位符{ }。

解决方案

方案1:使用原生SQL语句执行更新(最直接)

绕过模型ORM的自动处理,用参数绑定的方式执行原生更新,避免字符串转义和语法错误:

if (isset($geometry)) {
    DB::statement(
        'UPDATE mma_embargos SET geometry = ST_GeomFromText(?) WHERE id = ?',
        [$geometry, $embargo->id]
    );
    // 刷新模型实例,确保后续操作能获取最新数据
    $embargo->refresh();
}

方案2:整合到updateOrCreate逻辑中

如果几何字段在创建或更新时都需要处理,直接将其加入updateOrCreate的更新数据数组,使用带参数的DB::raw:

$updateData = $data;
if (isset($geometry)) {
    $updateData['geometry'] = DB::raw('ST_GeomFromText(?)', [$geometry]);
}

$embargo = MmaEmbargos::updateOrCreate(
    [
        'num_tad' => $numTad,
        'document' => $document,
        'num_processo' => $numProcess,
    ],
    $updateData
);

方案3:利用Laravel空间数据特性(推荐)

Laravel支持空间数据类型的原生处理,无需手动调用SQL函数:

  1. 在模型中定义空间字段类型:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\AsPolygon; // 根据实际几何类型选择,如AsPoint、AsLineString等

class MmaEmbargos extends Model
{
    protected $casts = [
        'geometry' => AsPolygon::class,
    ];
}
  1. 直接赋值几何字符串并保存,Laravel会自动转换处理:
if (isset($geometry)) {
    $embargo->geometry = $geometry;
    $embargo->save();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:55:18