对会话存储类设计的反馈

时间:2009-09-24 20:04:48

标签: php class oop

我有一个会话类,基本上只是设置和检索会话变量, 我之所以成功,是因为我可以轻松地将其更改为使用会话或其他内容 像memcache一样设置项目并让它们可以在多个页面上访问而无需访问数据库

然后我有这个用户类,它使用会话对象来获取会话变量 我想要添加到这个用户类,为了使它更加封装我希望能够设置我在这个类中检索的变量 所以现在我可以用$ user-> userid显示用户ID;我想首先有一个方法或者其他东西从我猜的会话对象中设置它的值 这听起来是个好主意还是可能有很多开销?

如果我想做的是一个好主意,也许你可以建议/展示我应该怎么做的例子?我在想,如果我添加该方法,我可能应该将__construct方法中的代码移动到它自己的方法中

基本上,我在构造方法中使用的类的顶部列出了变量,如果我在类中有多个方法,但是我需要将它们全部设置在顶部吗?

<?PHP
//user.class.php file
class User
{
    public $userid;
    public $name;
    public $pic_url;
    public $gender;
    public $user_role;
    public $location_lat;
    public $location_long;
    public $newuser;

    function __construct()
    {
        global $session;
        if($session->get('auto_id') != ''){
            //set user vars on every page load
            $this->userid = $session->get('auto_id'); //user id number
            $this->name = $session->get('disp_name');
            $this->pic_url = $session->get('pic_url');
            $this->gender = $session->get('gender');
            $this->user_role = $session->get('user_role');
            $this->location_lat = $session->get('lat');
            $this->location_long = $session->get('long');
            $this->newuser = $session->get('newregister');
        }else{
            return false;
        }
    }
}

//with the class above I can easily show some user variables I have saved into a session like this below
$user = new user();
$user->userid;

?>

5 个答案:

答案 0 :(得分:2)

一般来说,你的想法很好 我将采取不同的三件事:

1)在您的实现中似乎没有考虑拥有多个用户。即同一类的几个实例。

2)我会使用factories而不是在构造函数中使用IF。 因此,对于已保存在会话中的用户,您可以调用:

 $savedUser = User::fromSession($userId);

表示新用户

  $user = new User()

3)使用serialize和反序列化功能将该数据保存到会话

然后你的课程可以实现为

public static function fromSession($userId) {
   return unserialize($session->get('users_'.$userId));
}

public function save() {
   return $session->set('users_'.$this->id , serialize($this));
}

答案 1 :(得分:1)

我想这对于“这是一个好主意”的问题是一个模糊的回答。在我的理解中,在会话中定位变量而不是从数据库中刷新它们是复杂查询和反序列化数据之间权衡的问题。会话数据不是逃避数据库调用的免费魔术缓存,它只是您不必处理的数据库调用的方便包装器。您放置在会话中的任何变量都必须是可序列化的。然后管理整个序列化数据集合;服务器使用会话密钥获取数据,将其全部反序列化,并将其交给php脚本。然后当它关闭该请求 - 响应周期的会话时,它将所有序列化并将其放回到数据库中。

因此,在某些情况下,处理所有这些事情的混乱可能比只是打开一个连接并直接向db请求相同的东西(或一部分东西)更糟糕。

我会说在会话中放置一个或两个关键值是一个很好的停止位置,并且过于依赖它有状态是一个不太理想的计划。

答案 2 :(得分:0)

我会将名为“ValuesInSession”的新会话设置为true或false,具体取决于您是否具有用户类中字段的会话值。然后,在sessions \ users类中,您可以检查此会话是真还是假,并相应地设置您的值(IE从现有会话或空字符串\ 0)

编辑:您可以,或者将该代码放在用户或会话类中,编写一个可以与您的用户类一起使用的新类来正确设置值(也许它可以扩展会话类?)

答案 3 :(得分:0)

我不确定我是否理解这个问题,但是,如果你使用的是php 5,你可以使用__set魔法来帮助解决这个问题。

修改您当前的课程:

class User
{
     private $id;
     private $data = array();

     public function __construct()
     {
          global $session;
          $this->id = $session->get('auto_id');
          $this->data = array(
               'disp_name'=>$session->get('disp_name'),
               'pic_url'=>$session->get('pic_url'),
               'gender'=>$session->get('gender'),
               'user_role'=>$session->get('user_role'),
               'lat'=>$session->get('lat'),
               'long'=>$session->get('long'),
               'newregister'=>$session->get('newregister')
          );
     }

     // return the user id
     public function id()
     {
         return $this->id;
     }

     // the __get magic method is called when trying to retrieve a value of a
     // property that has not been defined.
     public function __get($name)
     {
         if(array_key_exists($name, $this->data))
         {
             return $this->data[$name];
         }
         return null;
     }


     // the __set magic method is called when trying to store a value in a property
     // that has not been defined.
     public function __set($name, $value)
     {
         global $session;
         // check if the key exists in the 'data' array.
         // if so, set the value in the array as well as the session
         if(array_key_exists($name, $this->data))
         {
             $this->data[$name] = $value;
             $session->set($name, $value);
         }
     }
}

这样你仍然可以获得和设置相同的值,但也会将值存储在会话类中。

测试一下:

$user = new User;
if($user->id())
{
     echo $user->disp_name;
     $user->disp_name = 'new name';
     echo $session->get('disp_name');
}

答案 4 :(得分:0)

我不建议你这样做因为:

  1. 选择一个“在未来需要的情况下”的架构并不是一个好习惯('我之所以这样做是因为我可以很容易地改变')。查看http://www.startuplessonslearned.com(Eric Ries)或http://highscalability.com文章
  2. 您的代码很难/无法测试(有关详细信息,请参阅Misko Hevery的博客(谷歌传教士)http://misko.hevery.com
  3. 您正在使用“全局”(如果您想跟踪依赖项,绝不是个好主意。)
  4. 最好分离“业务逻辑”(一个User类)和布线/建筑物(例如工厂类)。 (参见http://en.wikipedia.org/wiki/Single_responsibility_principle和“关注点分离”)
  5. 对于非常好的代码示例(以及了解哪些OO法律不应该被打破),我可以建议你Misko的博客(也不要错过他在谷歌上你可以在youtube上找到的技术讲座)。我相信你会爱上他们。

    希望这有帮助。