Doctrine 问题:无法从您发送到 GEOMETRY 字段的数据中获取几何对象

Doctrine issue: Cannot get geometry object from data you send to the GEOMETRY field

我按照 this guidepoint 类型添加到 Doctrine。

这是我在实体中定义坐标字段的方式:

/**
 * @ORM\Column(type="point", nullable=true)
 */
private $coordinates;

这就是我试图保存实体的方式:

$obj = new GeoPoint();
$obj->setAddress('Test');
$obj->setCoordinates(new Point(40.7603807, -73.9766831));
$manager->persist($obj);
$manager->flush();

我的配置:

doctrine:
    dbal:
        types:
            point: Viny\PointType
        driver: 'pdo_mysql'
        server_version: '5.7'
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci
        url: '%env(resolve:DATABASE_URL)%'
        mapping_types:
            point: point
    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        naming_strategy: doctrine.orm.naming_strategy.underscore
        quote_strategy: backend_lib.orm.quote_strategy
        auto_mapping: true
        mappings:
            App:
                is_bundle: false
                type: annotation
                dir: '%kernel.project_dir%/src/Entity'
                prefix: 'App\Entity'
                alias: App

结果数据库列定义:

`coordinates` point DEFAULT NULL,

结果我得到:

An exception occurred while executing 'INSERT INTO geo_point (address, coordinates) VALUES (?, ?)' with params ["Test", "POINT(-73.976683 40.760381)"]:

SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field

最终查询:

INSERT INTO geo_point (address, coordinates) VALUES ('Test', 'POINT(-73.976683 40.760381)');

您发布的 doctrine configuration 有误。应该是:

#doctrine.yaml
doctrine:
    dbal:
        types: ### Use types instead of mapping_types
            point: App\...\GeoPointType

你可以看出映射有问题,因为你生成了 sql:

INSERT INTO geo_point (address, coordinates) VALUES ('Test', 'POINT(-73.976683 40.760381)');

mysql本身不懂POINT。它需要包装在 PointFromText 中。这种包装是通过以下方式完成的:

    // class GeoPointType
    public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
    {
        return sprintf('PointFromText(%s)', $sqlExpr);
    }

而且它显然没有被调用。

Here is a working example.