从Doctrine实体中选择属性子集以进行序列化

时间:2015-02-08 02:11:29

标签: serialization properties doctrine

我正在构建一个web服务,它通过websocket连接传输域模型的json表示。实体与Doctrine映射,不幸的是,我只限制在我的实体类中使用protected或private属性。为了在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中优雅地实现,而无需使用Reflection API或从客户端对象的基类继承(我不想真正拆分实体类)。或者有没有办法在Doctrine实体中使用我不知道的公共属性?

我正在寻找一些独特的东西
$lightweightEntity = EntityStripper::strip($entity);

提前致谢!

1 个答案:

答案 0 :(得分:0)

虽然最初并不热衷于使用Reflection 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);
    }
}