原则返回null代替EntityNotFoundException

时间:2018-08-17 10:25:17

标签: php doctrine-orm entity

我的数据库中的FK损坏,如果我加载一个实体并要求相关的实体,Doctrine将抛出\Doctrine\ORM\EntityNotFoundException

对于有问题的实体,我希望在FK损坏的地方返回NULL而不是抛出异常。这是因为在Twig模板中会发生异常,因此我希望Twig在这种情况下不必处理异常。

以下是示例配置。

<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
    <entity name="Foo\Click" table="clicks">
        <id name="id" type="bigint" column="click_id">
            <generator strategy="IDENTITY"/>
        </id>
        <!-- .. -->
        <many-to-one field="visitor" target-entity="Foo\Visitor" fetch="LAZY">
            <join-columns>
                <join-column name="visitor_id" referenced-column-name="visitor_id"/>
            </join-columns>
        </many-to-one>
    </entity>

    <entity name="Foo\Visitor" table="visitors" read-only="true">
        <id name="visitorId" type="integer" column="visitor_id">
            <generator strategy="IDENTITY"/>
        </id>
        <!-- ... -->
        <one-to-one field="firstClick" target-entity="Foo\Click" fetch="LAZY">
            <join-columns>
                <join-column name="click_id" referenced-column-name="click_id"/>
            </join-columns>
        </one-to-one>
    </entity>
</doctrine-mapping>

以下是预期结果的示例,其中单击作为访客ID,但该ID不存在访客记录。在这种情况下,我宁愿不必将逻辑包装在“尝试/捕获”中,而是让Click::getVisitor()返回null;

<?php
$clickOne = $entityManager()->find(Foo\Click::class, 1);
$v = $clickOne->getVisitor();

if ($v !== null) {
    echo $v->getId(); // may throw Doctrine\ORM\EntityNotFoundException
}

Doctrine是否有针对此的策略?


更新:添加了示例配置和代码,现在我知道为什么使用简单的Doctrine配置无法实现这一点。

2 个答案:

答案 0 :(得分:1)

EntityNotFoundException从Doctrine的代理中抛出。因此,您可以使用EAGER加载方法来摆脱代理并获取NULL而不是异常。

答案 1 :(得分:0)

这是我根据comment制定的iainn采取的策略。

<?php
class Parent
{
    protected $child;

    public function getChild()
    {
        if ($this->child instance of \Doctrine\ORM\Proxy\Proxy) {
            try {
                $this->child->__load();
            } catch (\Doctrine\ORM\EntityNotFoundException $e) {
                $this->child = null
            }
        }

        return $this->child;
    }
}

我确信不建议您的实体直接与代理互动。但是我宁愿选择这种方法,而不是在实体上调用已知方法(这也将具有加载方法的作用),因为对于下一个可能会读它的开发人员来说,此代码的意图更加清楚。

我不确定与这样的代理进行交互是否有任何副作用。