Select 用于序列化的 Doctrine 实体的属性子集

Select subset of properties from Doctrine entity for serialization

我正在构建一个 web 服务,它通过 websocket 连接传输 json 域模型的表示。这些实体是用 Doctrine 映射的,不幸的是,这限制了我只能在我的实体 classes 中使用受保护或私有属性。为了在 json 中包含私有属性,我一直在我的实体中使用此特征:

/**
 * A trait enabling serialization for Doctrine entities for websocket transports.
 * Unfortunately, this cannot be included in the abstract class for Doctrine entities
 * as the parent class is unable to access private properties enforced by Doctrine.
 */
trait SerializableTrait
{
    /**
     * Implements {@link \JsonSerializable} interface.
     * @return string - json representation
     */
    public function jsonSerialize()
    {
        return get_object_vars($this);
    }
}

但是,客户端接收到的对象应该只包含实体属性的一个子集,以减少 websocket 连接的负载并防止嗅探私人信息。这是否可以在 php 中优雅地实现而不使用反射 API 或从基础 class 为客户端对象进行子classing(我真的不想拆分实体class)。或者是否有一种方法可以在我不知道的 Doctrine 实体中使用 public 属性?我正在寻找

$lightweightEntity = EntityStripper::strip($entity);

提前致谢!

虽然最初并不热衷于使用反射 API,但它似乎是唯一可行的解​​决方案。所以我想出了这个解决方案来解析自定义 @Serializable 注释以确定哪些属性被序列化:

use Doctrine\Common\Annotations\AnnotationReader;
use App\Model\Annotations\Serializable;

/**
 * A trait enabling serialization of Doctrine entities for websocket transports.
 */
trait SerializableTrait
{
    /**
     * Implements {@link \JsonSerializable} interface and serializes all
     * properties annotated with {@link Serializable}.
     * @return string - json representation
     */
    public function jsonSerialize()
    {
        // Circumvent Doctrine's restriction to protected properties
        $reflection = new \ReflectionClass(get_class($this));
        $properties = array_keys($reflection->getdefaultProperties());
        $reader = new AnnotationReader();

        $serialize = array();

        foreach ($properties as $key) {
            // Parse annotations
            $property = new \ReflectionProperty(get_class($this), $key);
            $annotation = $reader->getPropertyAnnotation($property, get_class(new Serializable()));

            // Only serialize properties with annotation
            if ($annotation) {
                $serialize[$key] = $this->$key;
            }
        }

       return json_encode($serialize, JSON_FORCE_OBJECT);
    }
}