2013-01-04 22 views
3

我想向幾何學添加幾何類型。我的Doctrine DBAL版本和ORM版本是2.1.7。在Doctrine 2.1.7中添加自定義數據類型(幾何)。方法canRequireSQLConversion()不叫

我試圖按照這裏的說明: Doctrine 2 Types - Custom Mapping Types

我成功創建了新的數據類型,但是我遇到了convertToPHPValueSQL方法的問題。我希望函數ST_AsText('..')在從數據庫中獲取幾何列時總是被調用(數據庫是PostgreSQL 9.1 + PostGIS 2.0.0)。

主義DBAL 2.1文件說,像這樣:

學說,DBAL的工作是你的類型轉換爲SQL 聲明。您可以修改Doctrine將生成的SQL聲明。

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

然後你覆蓋的方法convertToPhpValueSQL和 convertToDatabaseValueSQL:

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

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

現在 首先,你必須通過重寫 canRequireSQLConversion方法來啓用此功能我們必須使用Doctrine Type sy註冊這個類型莖和 鉤到數據庫平臺:

<?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); 

主義確實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 = ? 

主義不使用我的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(),這是錯誤的,我的代碼。新增評論。

這似乎是一個更完整的教程。

回答

6

找到了答案。在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」

在最新版本的學說,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。

相關問題