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);
}
}
我正在构建一个 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);
}
}