Rau*_*ets 4 orm geometry types doctrine doctrine-orm
我正在尝试将几何类型添加到Doctrine.我的Doctrine DBAL版本和ORM版本是2.1.7.
我试着按照这里的说明操作: Doctrine 2 Types - Custom Mapping Types.
我成功创建了新的数据类型,但是我遇到了convertToPHPValueSQL方法的问题.我希望在从数据库获取几何列时始终调用函数ST_AsText('..')(数据库是PostgreSQL 9.1 + PostGIS 2.0.0).
Doctrine DBAL 2.1文档说得像这样:
Doctrine-DBAL的工作是将您的类型转换为SQL声明.您可以修改Doctrine将生成的SQL声明.首先,您必须通过覆盖canRequireSQLConversion方法来启用此功能:
<?php
public function canRequireSQLConversion()
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
然后重写convertToPhpValueSQL和convertToDatabaseValueSQL方法:
<?php
public function convertToPHPValueSQL($sqlExpr, $platform)
{
return 'MyMoneyFunction(\''.$sqlExpr.'\') ';
}
public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
{
return 'MyFunction('.$sqlExpr.')';
}
Run Code Online (Sandbox Code Playgroud)
现在我们必须使用Doctrine Type系统注册此类型并将其挂钩到数据库平台:
<?php
Type::addType('money', 'My\Project\Types\MoneyType');
$conn->getDatabasePlatform()->registerDoctrineTypeMapping('MyMoney', 'money');
Run Code Online (Sandbox Code Playgroud)
我确实喜欢这个(很多代码都是占位符代码,但如果我做了一些愚蠢的事情,欢迎提出所有建议):
<?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.')'; //+
}
}
Run Code Online (Sandbox Code Playgroud)
现在我添加了使用此列的Entity:
<?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;
}
}
?>
Run Code Online (Sandbox Code Playgroud)
但如果我喜欢这样:
$entity = $em->find('\Minupeenrad\Entities\Field', 1);
Run Code Online (Sandbox Code Playgroud)
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 = ?
Run Code Online (Sandbox Code Playgroud)
尽管canRequireSQLConversion()返回true,但Doctrine不使用我的convertToPHPValueSQL方法.此外,我添加了一些调试代码,以查看是否甚至调用了canRequireSQLConversion(),并且未调用它.我究竟做错了什么?
PS:我试图搜索Stack Overflow,但我只提出了Doctrine 2的GIS扩展,它链接到我已阅读过的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";
}
Run Code Online (Sandbox Code Playgroud)
这段代码显然不尊重方法"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;
}
Run Code Online (Sandbox Code Playgroud)
所以答案是更新我的ORM.
归档时间: |
|
查看次数: |
3335 次 |
最近记录: |