Symfony实体的PHP 7类型声明

Vyc*_*rya 1 php symfony

在PHP 7中,如果提供的参数具有非预期类型,则可以使用类型声明引发异常。可以将其仅用于允许symfony实体吗?

/**
 * @param User|MyOtherEntity $entity
 */
public function serialize(TYPEHINTFORENTITY $entity)
{
    $json = json_decode($this->serializer->serialize(
        $entity,
        'json'
    ), true);

    return $json;
}

public function deserialize($json, string $class): TYPEHINTFORENTITY
{
    $entity = $this->serializer->deserialize(
        json_encode($json),
        'MyBundle\Entity\' . $class,
        'json',
        DeserializationContext::create()->setGroups(
            array('group')
        )
    );

    return $entity;
}
Run Code Online (Sandbox Code Playgroud)

如果我使用相同的功能来序列化不同的实体,则无法使用

public function serialize(User $entity)
Run Code Online (Sandbox Code Playgroud)

因为那将不允许MyOtherEntity的实体进行序列化。

Don*_*sto 5

从PHP的角度来看,实体不是“特殊”对象。您可以通过两种方式解决此问题

  1. 定义一个公共接口(可能没有任何方法),键入它的提示,然后让所有实体都实现该接口
  2. 使用PHP 7.2object引入的 typehint类型

使用第一个解决方案,如果有人尝试传递不是该接口的实现的东西,那么您是安全的。当然,您需要记住,每次在代码库中创建一个新实体时,它都应实现该接口。

对于第二种解决方案,您不如第一点那样安全,但是您仍要确保传递的所有内容都不是标量或原始类型

在第一个解决方案的帮助下,您最终会写出类似

interface Entity { }
class FooEntity implements Entity { }
class BarEntity implements Entity { }
...
public function serialize(Entity $entity) { }
Run Code Online (Sandbox Code Playgroud)

有了第二个解决方案

public function serialize(object $entity) { }
Run Code Online (Sandbox Code Playgroud)

如果需要允许这种类型的实体,则建议采用第一种解决方案,而第二种则更宽松:对于我来说,这两种方法都很好,但是您需要关注代码的规则是什么

编辑

我看到了其他建议扩展而不是实现接口的答案:如果不是绝对必要,请不要从超类扩展,因为PHP类只能从一个类扩展而它们可以实现多个接口。如果需要第一个解决方案,接口是必经之路,否则,如果您需要模型强加一些实际的扩展,就会遇到麻烦