如何在会话中存储对象(Codeigniter)


How to store objects in Session (Codeigniter)

情况:似乎不可能在CI_Session中存储任何对象,因为读取它们会导致PHP_Incomplete_Object异常,因为会话总是在加载模型之前启动的。这样,即使在自动加载对象类型时,我也永远无法从会话中读取数据。

我也尝试过使用"Native Session",但问题完全一样。

此外,我尝试存储序列化的对象,但当在加载所有模型后很长一段时间才取消序列化时,它仍然会变成一个类型为"__PHP_Incomplete_Class"的对象。

有人知道变通办法吗?请保留"你为什么要在会话中使用对象"的答案。看够了这些。。。

不幸的是,php不允许您从另一个对象序列化对一个对象的引用。这就是为什么当您恢复对象时,它不包含它开始时使用的数据。

我想出的最好的解决方案是在我的模型层中创建一个会话对象,该对象使用cookie进行恢复。数据库中的会话表处理对对象的引用,否则这些对象将被序列化。一旦您的会话模型被加载,您就可以使用它来加载"会话存储"对象,无论是急切地还是懒散地。

此外,如果这些对象包含对其他模型对象的引用,则可以使用相同的原理,基于关系引用遍历模型层的其余部分。这看起来可能令人望而生畏,但如果您觉得自己不太愿意实现它,您可以查看许多ORM。

我发现的另一个选项是,您可以以会话数组值的形式存储对象:

您可以这样存储:

$this->session->set_userdata($yourObject);

访问方式如下:

$this->session->userdata['property name of your object'];

到目前为止,我找到的唯一解决方案是将类与控制器放在一起(而不是作为库分离)。

不是很经典,但由于某些原因,它可以工作,而CI库实例则不能。

所以基本上:

class Main extends CI_Controller {
    public function index() {           
        $game = new Game(); 
        echo $game->id;
        $this->session->set_userdata('game',$game);
    }
    public function restore_game()  {           
        $game = $this->session->userdata('game');
        echo $game->id;
    }
}
class Game {
    public $id;
    public function __construct() {
        $this->id = rand(0,100);
    }
}

或者,您仍然可以将类保存在"libraries"文件夹中,但使用经典的require_once加载它,而不是$this->load->library("Game"),后者是会话无法处理的对象。

require_once(APPPATH . 'libraries/Game.php');
class Main extends CI_Controller {
   ...
}