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

Laravel 8+Voyager+Swagger中geometry字段API返回异常如何解决

问题背景
  • 技术栈:Laravel 8 + Voyager + Swagger
  • 参照Voyager坐标自定义文档开发,offices表points字段采用geometry类型存储坐标,建表代码:
Schema::create('offices', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('address')->nullable();
    $table->geometry('points')->nullable();
    $table->timestamps();
});
  • 故障现象:API返回points字段时抛出序列化错误,尝试使用mb_convert_encoding(\DB::raw($this->attributes['points']), 'UTF-8')处理后,字段返回乱码:
"points": "\u0000\u0000\u0000\u0000\u0001\u0001\u0000\u0000\u0000??\u0010??bR??Ng???D@",
故障原因

MySQL的geometry类型存储的是WKB(Well-Known Binary)格式的二进制空间数据,不是普通字符串类型,直接读取会返回二进制内容,既无法直接被JSON序列化,强行转字符编码也只会输出乱码。

解决方法

方案1:查询时通过空间函数直接输出可读格式

查询时调用MySQL内置空间函数,将二进制geometry转为可序列化的文本/JSON格式,无需额外模型处理:

  • 若需要前端地图组件直接识别的标准GeoJSON格式,使用ST_AsGeoJSON函数:
$officeList = Office::select(
    'id',
    'name',
    'address',
    \DB::raw('ST_AsGeoJSON(points) as points'),
    'created_at',
    'updated_at'
)->get();

返回的points为标准GeoJSON字符串,可直接被Leaflet、Mapbox、高德/百度地图等前端组件解析使用。

  • 若需要WKT(Well-Known Text)文本格式(如POINT(116.397 39.908)),将ST_AsGeoJSON替换为ST_AsText即可。

方案2:模型层配置访问器+修改器,自动处理读写转换

如果不想每次查询都手写DB::raw,可在Office模型中添加访问器和修改器,自动完成字段格式转换:

// app/Models/Office.php

/**
 * 读取points字段时自动从二进制WKB转为GeoJSON数组
 */
public function getPointsAttribute($value)
{
    if (is_null($value)) {
        return null;
    }
    $geoJson = \DB::selectOne(
        'SELECT ST_AsGeoJSON(ST_GeomFromWKB(?)) as point',
        [$value]
    )->point;
    return json_decode($geoJson, true);
}

/**
 * 写入points字段时自动将坐标转为geometry格式存储
 * 传入格式示例:['lng' => 116.397, 'lat' => 39.908]
 */
public function setPointsAttribute($value)
{
    if (is_array($value) && isset($value['lng'], $value['lat'])) {
        $this->attributes['points'] = \DB::raw(
            sprintf("ST_GeomFromText('POINT(%f %f)')", $value['lng'], $value['lat'])
        );
    }
}

配置后所有查询、写入操作都会自动处理格式,Swagger接口文档中直接将points定义为GeoJSON对象类型即可,不会再出现序列化报错。

注意:mb_convert_encoding是字符编码转换函数,无法处理二进制空间数据,该方案完全无效,不要使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:09:18