1

我创建了一个对象到 ID 数据转换器。它是自定义 ObjectIdType 的一部分,它允许我输入文档的 ID,而不是使用“文档”表单类型。这对 MongoDB 来说很方便(当有 1 亿个文档可供选择时)。

数据转换器对 ID 进行查询并返回一个对象。如果找不到对象,则返回 null。问题是 - 有时 null 是可接受的值,有时则不是。

即使我添加了 NotNull 验证器,我也会收到以下错误 -

可捕获的致命错误:传递给 Character::setPlayer() 的参数 1 必须是 Document\Player 的实例,给定 null

因此,无论验证失败,它都会调用 setter。我通过在变压器中抛出 TransformationFailedException 来解决这个问题——但这似乎是个坏主意。我真的不应该使用数据转换器来验证。

变压器的代码如下。我想要的是能够将验证器放在正确的位置,并拦截设置器,这样它就不会被调用。一般来说,这似乎有点代码味道,我很想知道其他人是如何解决这个问题的。

class ObjectToIdTransformer implements DataTransformerInterface
{
    private $objectLocator;
    private $objectName;
    private $optional;

    /**
     * @param ObjectLocator $objectLocator
     * @param $objectName
     */
    public function __construct(ObjectLocator $objectLocator, $objectName, $optional = false)
    {
        $this->objectLocator = $objectLocator;
        $this->objectName    = $objectName;
        $this->optional      = $optional;
    }

    /**
     * {@inheritdoc}
     */
    public function transform($value)
    {
        if (null === $value) {
            return null;
        }

        if (!$value instanceof BaseObject) {
            throw new TransformationFailedException("transform() expects an instance of BaseObject.");
        }

        return $value->getId();
    }

    /**
     * {@inheritdoc}
     */
    public function reverseTransform($value)
    {
        if (null === $value) {
            return null;
        }

        $repo = $this->objectLocator->getRepository($this->objectName);
        $object = $repo->find($value);

        if (!$this->optional && !$object) {
            throw new TransformationFailedException("This is probably a bad place to validate data.");
        }

        return $object;
    }
}
4

1 回答 1

3

实际上,这是一个非常不直观的 PHP 怪癖——尤其是对于那些来自其他(逻辑、直观、理智)语言(如 Java)的人。如果您希望能够将null参数传递给类型提示参数,则必须将其默认值设置为null

public function setPlayer(Player $player = null)
{
    // ...
}

是的,在这里谈论一些一致性......

于 2013-09-16T17:04:06.893 回答