orm - 在 Doctrine 2.1.7 中添加自定义数据类型(几何)。未调用方法 canRequireSQLConversion()

标签 orm types doctrine doctrine-orm geometry

我正在尝试将几何类型添加到 Doctrine。我的 Doctrine DBAL 版本和 ORM 版本是 2.1.7。

我尝试按照此处的说明进行操作:
Doctrine 2 Types - Custom Mapping Types .

我成功创建了新的数据类型,但是 convertToPHPValueSQL 方法有问题。我希望在从数据库(数据库是 PostgreSQL 9.1 + PostGIS 2.0.0)获取几何列时始终调用函数 ST_AsText(' .. ')。

Doctrine DBAL 2.1 文档是这样说的:

The job of Doctrine-DBAL is to transform your type into SQL declaration. You can modify the SQL declaration Doctrine will produce. At first, you must to enable this feature by overriding the canRequireSQLConversion method:



<?php
public function canRequireSQLConversion()
{
    return true;
}  

Then you override the methods convertToPhpValueSQL and convertToDatabaseValueSQL :



<?php
public function convertToPHPValueSQL($sqlExpr, $platform)
{
    return 'MyMoneyFunction(\''.$sqlExpr.'\') ';
}

public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
{
    return 'MyFunction('.$sqlExpr.')';
}

Now we have to register this type with the Doctrine Type system and hook it into the database platform:



<?php
Type::addType('money', 'My\Project\Types\MoneyType');
$conn->getDatabasePlatform()->registerDoctrineTypeMapping('MyMoney', 'money');

我确实喜欢这个(很多代码是占位符代码,但如果我做了一些愚蠢的事情,欢迎所有建议):

<?php

namespace Minupeenrad\Types;

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;

/**
 * Class for database column "geometry".
 *
 * @author Rauni Lillemets
 */
class GeometryType extends Type {
    const GEOMETRY = 'geometry';
    const SRID = 3301;

    public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform) {
        return 'geometry';
    }

    //Should create WKT object from WKT string. (or leave as WKT string)
    public function convertToPHPValue($value, AbstractPlatform $platform) {
        return $value; //+ 
    }

    //Should create WKT string from WKT object. (or leave as WKT string)
    public function convertToDatabaseValue($value, AbstractPlatform $platform) {
        return $value; //+
    }

    public function getName() {
        return self::GEOMETRY;
    }

    public function canRequireSQLConversion() {
        return true;
    }

    //Should give WKT
    public function convertToPHPValueSQL($sqlExpr, $platform) {
        return 'ST_AsText(\''.$sqlExpr.'\') '; //+
    }

    //Should create WKB
    public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) {
        return 'ST_GeomFromText(\''.$sqlExpr.'\', '.self::SRID.')'; //+
    }
}

现在我添加了使用此列的实体:

<?php
namespace Minupeenrad\Entities;

/**
 * Field
 *
 * @author Rauni Lillemets
 * @Entity
 * @Table(name="myfields.fields")
 */
class Field extends GeometryObject {
    /**
     * @Id
     * @Column(type="integer")
     * @GeneratedValue
     */
    private $id;

    /** 
     * @ManyToOne(targetEntity="User") 
     */
    private $user;

    /**
     * @Column(type = "string", length = "40")
     */
    private $fieldNumber;

    public function getId() {
        return $this->id;
    }

    public function getUser() {
        return $this->user;
    }

    public function setUser($user) {
        $this->user = $user;
    }

    public function getFieldNumber() {
        return $this->fieldNumber;
    }

    public function setFieldNumber($fieldNumber) {
        $this->fieldNumber = $fieldNumber;
    }
}
?>

但如果我这样做:

$entity = $em->find('\Minupeenrad\Entities\Field', 1);

Doctrine 对数据库执行 SQL 请求,如下所示:

SELECT t0.id AS id1, t0.fieldNumber AS fieldnumber2, t0.geometry AS geometry3, t0.user_id AS user_id4
FROM myfields.fields t0
WHERE t0.id = ?

Doctrine 没有使用我的 convertToPHPValueSQL 方法,尽管 canRequireSQLConversion() 返回 true。此外,我添加了一些调试代码以查看是否甚至调用了 canRequireSQLConversion() ,并且没有调用它。我究竟做错了什么?

PS:我试图搜索堆栈溢出,但我只想出了GIS extension for Doctrine 2 ,它链接到我已经阅读过的 Doctrine 2.1.x 手册。

编辑:我会在这里阅读:http://docs.doctrine-project.org/en/latest/cookbook/advanced-field-value-conversion-using-custom-mapping-types.html

EDIT2:修复了函数 getSqlDeclaration(),这在我的代码中是错误的。添加了评论。

这似乎是一个更完整的教程。

最佳答案

找到了答案。

在 Doctrine 2.1.7 中,如果我使用 $em->find(),最终会调用 BasicEntityPersister()_getSelectColumnSQL()。它有以下代码:(取自 https://github.com/doctrine/doctrine2/blob/2.1.x/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php )

/**
 * Gets the SQL snippet of a qualified column name for the given field name.
 *
 * @param string $field The field name.
 * @param ClassMetadata $class The class that declares this field. The table this class is
 * mapped to must own the column for the given field.
 * @param string $alias
 */
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
{
    $columnName = $class->columnNames[$field];
    $sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias) . '.' . $class->getQuotedColumnName($field, $this->_platform);
    $columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
    $this->_rsm->addFieldResult($alias, $columnAlias, $field);

    return "$sql AS $columnAlias";
}

这段代码显然不尊重方法“canRequireSQLConversion”

在最新的 Doctrine 版本 2.3.1 中(参见 https://github.com/doctrine/doctrine2/blob/2.3/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php ):
/**
 * Gets the SQL snippet of a qualified column name for the given field name.
 *
 * @param string $field The field name.
 * @param ClassMetadata $class The class that declares this field. The table this class is
 * mapped to must own the column for the given field.
 * @param string $alias
 */
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
{
    $sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias)
         . '.' . $this->quoteStrategy->getColumnName($field, $class, $this->_platform);
    $columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]);

    $this->_rsm->addFieldResult($alias, $columnAlias, $field);

    if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
        $type = Type::getType($class->getTypeOfField($field));
        $sql = $type->convertToPHPValueSQL($sql, $this->_platform);
    }

    return $sql . ' AS ' . $columnAlias;
}

所以答案是更新我的ORM。

关于orm - 在 Doctrine 2.1.7 中添加自定义数据类型(几何)。未调用方法 canRequireSQLConversion(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14154502/

相关文章:

node.js - 序列化嵌套数据结构

java - ORM建模: Database first vs classes first

c# - 如何找到两种类型中最小的可分配类型(重复)?

scala - 我可以像使用C++模板特化一样专门化Scala中的函数类型参数吗?

c - 不兼容的指针类型错误 [C]

symfony - 克隆 Doctrine ArrayCollection 不带引用

php - 如何从 symfony 2.4 中的选择字段插入数据

scala - ScalikeJdbc 多重插入

.net - 什么是适合我们需求的轻量级 ORM?

sql - Doctrine 列 id 在 PostgreSQL 上不存在