Doctrine2本机查询不会保留自定义类型

时间:2017-02-05 13:23:03

标签: php postgresql symfony doctrine-orm zend-framework2

在ZF2-PostgreSQL应用程序中,我想使用Doctrine2本机查询来构建分页器列表。

因此,如果选择任何自定义Doctrine / Pgsql类型,它会很有用。但对于一个查询,我会使用自定义类型的数据。

我在PostgreSQL中声明了一个名为AlertRecipient的Doctrine 2自定义类型,如下所示:

CREATE TYPE alert_recipient AS (
    email text,
    status int
);

此类型用于某些表格。 clients表中的示例:

ID (int) | name (varchar) | alerts (alert_recipients[])
1        | John Doe       | {"(john@doe.com, 1), (jane@doe.com, 1)"} 
2        | Foo Bar        | {"(foo@bar.com, 1)"} 

alert_recipient[]扩展alert_recipient以存储许多alert_recipient条记录的列表

此类型与实体相关联,用于保湿:

class AlertRecipient
{
    protected $email;

    protected $status;

    // ... with accessors
}

Doctrine类型注册是在onBoostrap事件:

上进行的
// ...
if (!Type::hasType('alert_recipient'))
{
    Type::addType('alert_recipient', AlertRecipient::class);
}
$platform->registerDoctrineTypeMapping('alert_recipient', 'alert_recipient');

if (!Type::hasType('alert_recipient[]'))
{
    Type::addType('alert_recipient[]', AlertRecipients::class);
}
$platform->registerDoctrineTypeMapping('_alert_recipient', 'alert_recipient[]');
// ...

自定义类型学说适配器已编写,例如文档http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/custom-mapping-types.html

查询如下:

$rsm = new ResultSetMappingBuilder($em);

$rsm->addRootEntityFromClassMetadata(Client::class, 'c');
// ... some other data from join entity (e.g)

$query = 'SELECT c.* FROM clients c JOIN ...';
$em->createNativeQuery($query, $rsm);

$results = $query->getResult(NativeQuery::HYDRATE_ARRAY);

问题是我从find() Doctrine本机方法或我的原生查询结果的水合作用中没有相同的行为。

在自定义类型适配器中调试:

public function convertToPHPValue($value, AbstractPlatform $platform)
{
    var_dump($value); exit;
    // ...
}

修改

public function convertToPHPValueSQL($sqlExpr, $platform)
{
    return 'to_json(' . $sqlExpr . ')';
}

find()开始,使用AlertRecipient实体正确补充结果:string '[{"email":"john@doe.com","status":1}, {"email":"jane@doe.com","status":1}]'

从本地查询水合,结果['order_emails']在AlertRecipient实体中没有水合:string '{"(john@doe.com, 1), (jane@doe.com, 1)"}'

然后数据没有正确补充......

感谢您的想法

修改

alertRecipient实体中Client财产的声明:

/* @ORM\Column(type="alert_recipient[]", nullable=true, name="alert_recipients")
 * @Gedmo\Versioned
 */
 protected $alertRecipients = [];

 // ... with accessors 

1 个答案:

答案 0 :(得分:0)

您是否关注broadcasting

您应该使用convertToPHPValueconvertToDatabaseValue这样的方法来保持水分正常工作。

您还写道:

  

find()开始,使用AlertRecipient实体...

正确补充了结果

据我了解,AlertRecipient是一个dbal Type类,而不是Entity类。

键入类(因此您的AlertRecipient类)应该扩展Doctrine\DBAL\Types\Type

然后,您应该在实体定义中使用此类型标记具有正确类型属性的列:

/** @Column(type="alert_recipient") */
$alertRecipient;

由于您没有共享所有详细信息(例如您使用自定义类型的实体定义),我不确定您哪里出错,但如果您按照文档说明这一切都应该按预期工作,那么我的猜猜你会跳过其中一个步骤。