查询在 MySQL 中有效,但不能通过 Lumen/Laravel - 数值超出范围:1416

Posted

技术标签:

【中文标题】查询在 MySQL 中有效,但不能通过 Lumen/Laravel - 数值超出范围:1416【英文标题】:Query works in MySQL but not via Lumen/Laravel - Numeric value out of range: 1416 【发布时间】:2018-05-03 17:02:44 【问题描述】:

我很难过... 很简单,我正在尝试更新 mysql 数据库中的几何记录,但由于某种原因,它失败了。但是,当 Lumen 抛出 QueryException 时,它会显示正在执行的查询;

UPDATE `user_locations` SET `current_location` = ST_GeomFromText('POINT(1 1)') WHERE user_id = 1

上述查询工作当我通过命令行在 MySQL 中执行它时,但由于某种原因,它不能通过 Laravel/Lumen/PDO/Eloquent 工作(不是确定是哪一个导致了问题)。

这是抛出的错误:

SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field (SQL: update `user_locations` set `current_location` = ST_GeomFromText('POINT(1 1)') where `user_id` = 1)

我能想到的都试过了;

降级 MySQL(我看到其他人在使用 Mysql 5.7 时遇到类似问题) 直接从 Eloquent 转储查询和绑定,以查看实际发送到 MySQL 的内容(见下文) 更改数据库的引擎(目前是 InnoDB) 删除current_location 列上的空间索引

还有什么可能导致这种情况?它不能是 MySQL,因为它是通过命令行工作的,所以它肯定是 Laravel/Eloquent/PDO 中的东西?

其他信息

我正在运行 MySQL 5.7(我也尝试过 5.6,但它抛出了完全相同的错误) 我正在使用 Lumen,但我认为这无关紧要,因为 Laravel 和 Lumen 都使用 Eloquent 我正在使用https://github.com/grimzy/laravel-mysql-spatial,这(我相信)是相关代码: 更新 - 我认为这无关紧要,但在这个特定表上还有另一个 point 字段,但由于我没有更新该字段,因此在查询中应该完全忽略它,因此,不相关...

Builder 扩展了 Illuminate\Database\Eloquent\Builder

/**
 * Update a record in the database.
 *
 * @param   array $values
 * @return  int
 */
public function update(array $values) : int

    foreach ($values as $key => &$value) 
        if ($value instanceof GeometryInterface) 
            $value = $this->asWKT($value);
        
    

    return parent::update($values);


/**
 * Set the MySQL for the geometry field.
 *
 * @param   GeometryInterface $geometry
 * @return  string
 */
protected function asWKT(GeometryInterface $geometry) : string

    return $this->getQuery()->raw("ST_GeomFromText('" . $geometry->toWKT() . "')");

此外,我还尝试了以下方法:

Illuminate\Database\Query\Builder

public function update(array $values)

    $sql = $this->grammar->compileUpdate($this, $values);

    dd($sql, $values, $this->cleanBindings(
        $this->grammar->prepareBindingsForUpdate($this->bindings, $values)
    ));

    return $this->connection->update($sql, $this->cleanBindings(
        $this->grammar->prepareBindingsForUpdate($this->bindings, $values)
    ));

这个输出:

string(70) "update `user_locations` set `current_location` = ? where `user_id` = ?"
array(1) 
  ["current_location"]=>
  &string(47) "ST_GeomFromText('POINT(1 1)')"

array(2) 
  [0]=>
  &string(47) "ST_GeomFromText('POINT(1 1)')"
  [1]=>
  int(1)

【问题讨论】:

我希望这可能是解决方案:liquidweb.com/kb/how-to-disable-mysql-strict-mode 非常感谢@ThomasMoors,我会试试看 我认为使用 DB::raw 来解决你的问题,看看这个 laracast 讨论:laracasts.com/discuss/channels/eloquent/… 感谢@teeyo,但这与$this->getQuery()->raw() 完全相同。可以肯定的是,我在 2 秒前尝试过,但不幸的是得到了相同的结果。 @teeyo 我收回(有点),我发现了这个问题,这是我最可悲、最令人恼火和完全荒谬的错误......见这里protected function asWKT(GeometryInterface $geometry) : string。如果您能发现问题,请告诉我(我会尽快发布答案) 【参考方案1】:

看这里:

照亮\数据库\查询

/**
 * Create a raw database expression.
 *
 * @param  mixed  $value
 * @return \Illuminate\Database\Query\Expression
 */
public function raw($value)

    return $this->connection->raw($value);

raw 的返回不是string,而是\Illuminate\Database\Query\Expression。因此,通过将 asWkt 的返回值转换为 string,它会强制 Eloquent 用引号括起来,从而引发我们看到的错误。

【讨论】:

我注意到了,但不太确定这是错误的原因,很高兴你已经解决了 :)

以上是关于查询在 MySQL 中有效,但不能通过 Lumen/Laravel - 数值超出范围:1416的主要内容,如果未能解决你的问题,请参考以下文章

mysql - 您不能在 FROM 子句中指定要更新的目标表(我的查询有效,但不是等效更新)

Laravel / Lumen formRequest 在提交所有有效值时抛出错误

Lumen MySQL 查询未按预期处理 UTF8 值

PHP 中的 MySQL 查询不再有效

mysql“日期之间”查询在 phpmyadmin 中有效,但 PDO 不返回任何内容

Lumen 主页在 AWS 上正常工作,但其他页面不可用