phalcon基于di容器管理所有服务,session也做为服务被引入。正常情况下要实现自定义session_id只要在session_start前使用session_id函数设置即可。但是,一般逻辑是先检查session是否存在用户信息,如果存在表示登陆,不存在表示游客。要获取session信息必须先session_start,因此想要真正自定义session_id,要在返回cookie头前对session_id进行修改。
php提供了一个函数session_regenerate_id(),允许使用新生成的会话 ID 更新现有会话 ID,并且不会修改用户信息。基于这个思路,注入di容器的session服务如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 $di ->setShared('session' , function ( ) { $session = new class () extends SessionManager { }; $factory = new SerializerFactory(); $adapterFactory = new AdapterFactory($factory ); $redis = new class ($adapterFactory , array_merge ([ "lifetime " => 86400, "prefix " => 'sess -ph -', ], $this ->getConfig ()->redis ->toArray ()[0])) extends SessionRedis { private $userSid = "" ; public function getUserSid ( ): string { return $this ->userSid; } public function setUserSid (string $userSid ) { $this ->userSid = $userSid ; } public function create_sid ( ) :string { if (empty ($this ->getUserSid())){ return "guest_" . md5("pref_" . di()->get("request" )->getClientAddress(true )); } return $this ->getUserSid(); } }; $session ->setAdapter($redis ); $session ->start(); return $session ; });
redis存储session,提高效率,session服务对外开放setUserSid方法,用户登陆时重新生成session_id即可。可以在生成用户sid过程中对用户之前的sid进行清理,更新sid的同时,避免sid堆满内存。游客用户可以使用ip作为唯一sid,如果没有特殊需求,固定一个sid更好一点
1 2 3 $this ->session->getAdapter()->setUserSid($this ->generateUserSessId(1 ));$this ->session->regenerateId();$this ->session->set("user_info" , $userInfo );