如何修复Symfony3.4+PostGIS环境下“Unknown database type geometry”错误
看起来你已经完成了基础配置,但还是遇到了Doctrine无法识别geometry类型的问题,这大概率是配置没有被EC-CUBE/Symfony正确加载,或者缓存、元数据残留导致的。下面一步步来排查和解决:
1. 先明确:Symfony本身不默认支持geometry类型
Doctrine ORM原生没有内置PostGIS的geometry/geography类型支持,必须依赖jsor/doctrine-postgis扩展来提供类型映射和平台扩展,所以核心问题是这个扩展的配置没有被正确生效。
2. 检查Doctrine DBAL类型配置是否正确
打开app/config/eccube/packages/doctrine.yaml,确认你的类型配置在doctrine.dbal.types节点下,格式必须准确:
doctrine: dbal: # 必须配置正确的PostgreSQL版本,对应你的mdillon/postgis容器版本 server_version: '10' types: geography: Jsor\Doctrine\PostGIS\Types\GeographyType geometry: Jsor\Doctrine\PostGIS\Types\GeometryType raster: Jsor\Doctrine\PostGIS\Types\RasterType
server_version非常关键:如果Doctrine自动检测版本错误,会使用原生的PostgreSQL100Platform,而jsor/doctrine-postgis需要替换为支持PostGIS的平台类。
3. 确认PostGIS事件订阅者已正确注册
在app/config/eccube/services.yaml里,确保事件订阅服务被正确标记为Doctrine事件订阅者:
services: jsor.doctrine_postgis.schema_event_subscriber: class: Jsor\Doctrine\PostGIS\Event\PostGISSchemaEventSubscriber tags: - { name: doctrine.event_subscriber }
执行以下命令检查服务是否注册成功:
bin/console debug:container | grep postgis
如果能看到jsor.doctrine_postgis.schema_event_subscriber这个服务,说明注册没问题;如果看不到,检查配置文件的缩进或语法错误。
4. 验证实体类的注解是否正确
打开你的Customize\Entity\GeoLocation类,确认geometry字段的注解使用了正确的类型,并且指定必要参数(如几何类型、SRID):
<?php namespace Customize\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass="Customize\Repository\GeoLocationRepository") * @ORM\Table(name="dtb_geolocation") */ class GeoLocation { // ... 其他字段 /** * @ORM\Column(type="geometry", options={"geometry_type"="POINT", "srid"=4326}) */ private $location; // ... getter/setter方法 }
不要遗漏options里的geometry_type和srid,这会帮助Doctrine正确生成表结构并识别类型。
5. 彻底清除缓存(包括EC-CUBE的自定义缓存)
你已经执行了缓存清理,但EC-CUBE可能有额外的缓存机制,建议:
- 如果访问的是生产环境,执行生产环境缓存清理:
bin/console cache:clear --env=prod --no-warmup - 手动删除
var/cache目录下的所有文件:rm -rf var/cache/* - 重新生成代理类:
bin/console eccube:generate:proxies
6. 检查Doctrine的Platform类是否被替换
jsor/doctrine-postgis会替换默认的PostgreSQL Platform类为支持PostGIS的版本,我们可以通过简单脚本验证:
在项目根目录创建check_platform.php:
<?php require __DIR__.'/vendor/autoload.php'; $kernel = new AppKernel('dev', true); $kernel->boot(); $connection = $kernel->getContainer()->get('doctrine.orm.default_entity_manager')->getConnection(); $platform = $connection->getDatabasePlatform(); echo get_class($platform) . PHP_EOL;
执行脚本:
php check_platform.php
如果输出是Jsor\Doctrine\PostGIS\Platforms\PostgreSQLPlatform或对应版本子类,说明平台替换成功;如果还是Doctrine\DBAL\Platforms\PostgreSQL100Platform,回到步骤3检查服务配置。
7. EC-CUBE特定的配置排查
EC-CUBE 4.0在Symfony基础上做了自定义配置,可能覆盖Doctrine默认配置:
- 检查
app/config/eccube/doctrine.yaml(如果存在),确认里面的配置没有覆盖你在packages/doctrine.yaml里的types配置; - 确认自定义实体被Doctrine正确识别:执行
bin/console doctrine:mapping:info,查看Customize\Entity\GeoLocation是否在列表中。
按照上面的步骤逐一排查,应该能定位并解决问题。
内容的提问来源于stack exchange,提问作者shko

