【问题标题】:Serialize an object differently depending on the user's privileges根据用户的权限对对象进行不同的序列化
【发布时间】:2014-01-01 22:09:32
【问题描述】:

目前,为了将数据从我的网络应用发送到前端,我的类实现了JsonSerializable 接口。

但是现在,当用户有足够的权限时,我想向前端发送更多信息。这些权限只能通过Entity\User 类的对象知道,例如$user->hasPrivileges(…)

遗憾的是,我无法将 $user 变量提供给 jsonSerialize() 方法。实现这一目标的最干净的方法是什么?

【问题讨论】:

  • 当然,祝大家新年快乐 :) !
  • 所以你不知道哪个用户“登录”了?
  • @MatthiasDunkel 我有:用户由 $user 变量表示。但我无法通过jsonSerialize() 访问它。
  • 你不能在类中有一个变量来实现持有用户的 JsonSerializable 吗?然后你可以像$this->user 一样访问它
  • @MatthiasDunkel 好吧,这就是 dev-null-dweller 和 kuroi neko 的提议 :) 。有关 cmets,请参见下文。

标签: php serialization


【解决方案1】:

我假设您可以在前端类中添加一个属性来过滤掉非特权数据,并在调用 jsonSerialize 之前设置此属性:

class FrontEnd implements JsonSerializable {
    private $serialize_all = false;
    private $pub_data   = Array(/* whatever */);
    private $admin_data = Array (/* whatever */);

    public function admin_output ($p) { $this->serialize_all = $p; }

    public function jsonSerialize() 
    {
        return $this->serialize_all 
            ? array_merge ($this->pub_data, $this->admin_data)
            : $this->pub_data;
    }
}

$frontend->admin_output ($user->is_admin ());
$output = json_encode ($frontend);

如果您有许多不同的对象要序列化,您可以将它们子类化为处理问题的类,如下所示:

abstract class privilegiedSerializable implements jsonSerializable {

    abstract function json_encode ($is_admin); // child picks the export data

    protected function do_encode ($data) // and we take care of the rest
    {
        $this->json_data = $data;
        $out = json_encode ($this);
        $this->json_data = null; // cleanup a bit
        return $out;
    }
    public function jsonSerialize () { return $this->json_data; }
}

class FrontEnd extends privilegiedSerializable {
    private $pub_data   = Array(/* whatever */);
    private $admin_data = Array (/* whatever */);

    public function json_encode ($is_admin)
    {
       return $this->do_encode (
              $is_admin
            ? array_merge ($this->pub_data, $this->admin_data)
            : $this->pub_data);
    }
}

$output = $frontend->json_encode ($user->is_admin())

或者如果用户权限在脚本执行期间是一个常量:

abstract class privilegiedSerializable implements jsonSerializable {

    static private $serialize_all = false;
    static public function admin_output ($p) { self::$serialize_all = $p; }
    abstract function json_encode (); // child picks the export data

    // same as before
}

class FrontEnd extends privilegiedSerializable {
    // ...

    public function json_encode ()
    {
       return $this->do_encode (
              parent::$serialize_all
            ? array_merge ($this->pub_data, $this->admin_data)
            : $this->pub_data);
    }

privilegiedSerializable::admin_output ($user->is_admin());
$output1 = $frontend1->json_encode ();
$output2 = $frontend2->json_encode ();

【讨论】:

  • 这里有相同的评论 ^^ :这意味着向每个对象添加一个新属性(为了记住用户,或者至少是权限)。这是不可避免的吗?
【解决方案2】:

在序列化之前通知这个对象:

if ($user->hasPrivileges()) {
   $object->IwillBeSerializngYouForUser($user); 
}
$serialized = $object->jsonSerialize();

【讨论】:

  • 我就是这么想的。但这意味着为每个对象添加一个新属性(为了记住用户,或者至少是权限)。这是不可避免的吗?
  • 好吧,你可以制作装饰器函数CustomJsonSerialize(),它接受参数并调整其属性以进行序列化,然后如果你不想创建新属性,则在内部调用jsonSerialize
猜你喜欢
  • 2014-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 2013-12-07
相关资源
最近更新 更多