【问题标题】:Doctrine2 native query does not hydrate custom typeDoctrine2 本机查询不水合自定义类型
【发布时间】:2017-06-22 11:53:43
【问题描述】:

在 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_recipientrecords 的列表)

这种类型被链接到一个实体,用于水合:

class AlertRecipient
{
    protected $email;

    protected $status;

    // ... with accessors
}

onBoostrap事件上进行Doctrine类型注册:

// ...
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[]');
// ...

自定义类型学说适配器已经写好如doc 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}]'

从本机查询水合来看,AlertRecipient 实体中的 result['order_emails'] 没有水合:string '{"(john@doe.com, 1), (jane@doe.com, 1)"}'

那么数据没有被正确的水合......

感谢您的想法

编辑

Client实体中声明alertRecipient属性:

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

 // ... with accessors 

【问题讨论】:

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


    【解决方案1】:

    你关注Doctrine 2 documentation for Custom Mapping Types了吗?

    您应该使用convertToPHPValueconvertToDatabaseValue 之类的方法来使水合正常工作。

    你还写道:

    find() 开始,使用AlertRecipient 实体对结果进行了正确的水合...

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

    类型类(所以你的AlertRecipient 类)应该扩展Doctrine\DBAL\Types\Type

    那么你应该在你使用这个类型的实体定义中用正确的类型属性标记列:

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

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

    【讨论】:

    • 你是对的 dbal 类型,“水合”由 postgreSQL 处理。相关实体用于convertToPHPValue 方法。在我的情况下,对于find() 学说方法,convertToPHPValueSQL 被调用 (return 'to_json(' . $sqlExpr . ')';) 但不是使用本机查询...我正在寻找一种方法来水合Client::alertRecipientsResultSetMapping 对,没有硬代码SELECT ..., to_json(alert_recipients) FROM clients ...
    • @ceadreak alertRecipients 的列定义在您的 Client 实体中是什么样的?
    • @Wilt 请检查我的问题中的编辑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多