您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

PHP命令行下模拟Session机制

2024/4/20 22:17:28发布6次查看
— 自动化测试过程中常规策略 一.背景 session称为会话,是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间,如果需要的话,可能还有一定的操作空间。通常情况下session用于存储需要在整个用户会话过程中
— 自动化测试过程中常规策略
一.背景session称为会话,是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间,如果需要的话,可能还有一定的操作空间。通常情况下session用于存储需要在整个用户会话过程中保持其状态的信息,例如登录信息或用户浏览 web应用程序时需要的其它信息。
php的 $_session 的功能之所以如此强大是因为有webserver的支持,试想一下如果在命令行下读取一个 $_session 变量,会是什么结果?
必然是null,因为php的session_start() 函数在命令行下是无法使用的,假若一段逻辑结果中含有这个session会话变量,该如何去测试它的有效性?
二.session的原理为了探究webserver下的session原理,我们做一个简单的测试:
session.php的文件,内容很简单:
2, loc => 4,);
再观察浏览器的request header中的cookie信息依旧不变,但是却可以发现服务器下 /tmp/sess_87bufd4ogid71e1gr6dtcbphi0文件的大小更变,打开发现类似序列化(非序列化)的字符串,信息内容是之前$_session的值:
我们开启一个新的浏览器,比如ie,再查看/tmp/下的文件:
观察新出现一个以sess为前缀的文件,同时ie的cookie下出现了这个phpsessid的值。
因此我们可以基本理解session的工作原理:当session被启用的时候,一个唯一的标识被储存于本地的cookie中。首先使用 session_start() 函数,php从session仓库中加载已经存储的session变量,如果这个仓库不存在,会被创建。当操作 $_session变量时,通过使用php内置session函数处理session变量。当php脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session仓库中,这个路径可以通过php.ini文件中的session.save_path指定,默认在/tmp/目录。三.session策略设计既然session的默认机制是存放在文件中,因此我们是不是可以为了命令行模式做一个假的session机制,因此不妨设计一个策略模式:
当通过浏览器请求,使用一个真的session操作类来操作 $_session全局变量。当通过cli模式请求php文件时,默认使用一个假的session操作类。让我们做这样简单的操作,无论在cli模式或是http模式都能正常运行:
\cores\session::getinstance()->set('name', lancer);\cores\session::getinstance()->set('age', 28);\cores\session::getinstance()->del(age);\cores\session::getinstance()->has(name)\cores\session::getinstance()->has(groups, array( dev => 2, loc => 4,));
我们可以猜想到:
\cores\session对象的 getinstance() 方法必然是一个自动选择策略的过程,返回的是一个对象:
在cli模式下返回的是 \cores\session_cli 对象;在普通模式下返回的是 \cores\session_http 对象。既然是一种策略模式, \cores\session_cli 与 \cores\session_http 必须拥有同样的方法来操作session,所以需要提供一个接口 \cores\session_interface 。
根据我们的想法,设计出简单的uml图,session具有基本的五个方法:
start(开始), set(赋值), has(存在), get(获取), del(删除)
由于session启动后在整个应用中必然是唯一实例,因此上图 \cores\session_cli 与 \cores\session_http都使用了单例模式,但 \cores\session_cli 必须具有一些特殊的操作,比如写入session记录,创建session_id等伪操作,因此添加部分方法:
四.程序实现根据session策略设计,开始编写对应的类:
接口类session_interface (不可否认写接口是最没难度的):/** * session接口 * @author lancer he * @since 2014-04-23 * @copyright http://www.crackedzone.com */interface session_interface { // 开启 public function start(); // 是否存在某个session public function has($name); // 获取某个session public function get($name=''); // 给某个session赋值 public function set($name, $value); // 删除某个session值 public function del($name);}
session_http类,用于管理http请求过来的session策略:/** * http模式下管理$_session类 * @author lancer he * @since 2014-04-23 * @copyright http://www.crackedzone.com */class session_http { protected static $_instance = null; /** * session是否已经开启 * @var boolean */ protected $_started = false; /** * 单例模式禁止clone */ private function __clone() {} /** * 单例模式禁止外部初始化 */ private function __construct() {} /** * 返回单例模式 */ public static function getinstance() { if ( ! is_null( self::$_instance ) ) { return self::$_instance; } $instance = new self(); $instance->start(); self::$_instance = $instance; return $instance; } /** * 开启session * @return void */ public function start() { session_start(); $this->_started = true; } /** * 通过name查看session是否存在 * @param string $name * @return boolean */ public function has($name) { return isset($_session[$name]); } /** * 通过name从session中获取一个值 * @param string $name 为空时返回整个sessino * @return mixed */ public function get($name='') { if ( ! $name ) return $_session; return isset($_session[$name]) ? $_session[$name] : null; } /** * 给指定的name设置一个session值,返回连缀对象 * @param string $name * @param mixed $value * @return object */ public function set($name, $value) { $_session[$name] = $value; return $this; } /** * 从session中删除一个值,失败返回false,成功返回连缀对象 * @param string $name * @return false|object */ public function del($name) { if ( ! $this->has($name) ) return false; unset($_session[$name]); return $this; }}
session_cli类,用于命令行下模拟session效果:/** * cli模式下会模拟一个session_id,同时在/tmp/下产生一个sesscli文件用来保存session信息 * @author lancer he * @since 2014-04-23 * @copyright http://www.crackedzone.com */class session_cli { protected static $_instance = null; /** * session_id * @var string */ protected $_session_id = null; /** * session file * @var string */ protected $_session_file = null; /** * session数组 * @var array */ protected $_session = array(); /** * session是否已经开启 * @var boolean */ protected $_started = false; /** * 单例模式禁止clone */ private function __clone() {} /** * 单例模式禁止外部初始化 */ private function __construct() {} /** * 返回单例模式 */ public static function getinstance() { if ( ! is_null( self::$_instance ) ) { return self::$_instance; } $instance = new self(); $instance->start(); self::$_instance = $instance; return $instance; } /** * 开启session * @return void */ public function start() { $this->_init(); $this->_started = true; } /** * 初始session * @return void */ protected function _init() { $this->_session_id = md5(uniqid()); $this->_session_file = '/tmp/' . application_cli_session_file_prefix . $this->_session_id; if ( file_exists($this->_session_file) ) { $this->_session = unserialize( file_get_contents($this->_session_file) ); return; } file_put_contents($this->_session_file, null); } /** * 通过name查看session是否存在 * @param string $name * @return boolean */ public function has($name) { return isset($this->_session[$name]); } /** * 通过name从session中获取一个值 * @param string $name 为空时返回整个sessino * @return mixed */ public function get($name='') { if ( ! $name ) return $this->_session; return isset($this->_session[$name]) ? $this->_session[$name] : null; } /** * 给指定的name设置一个session值,返回连缀对象 * @param string $name * @param mixed $value * @return object */ public function set($name, $value) { $this->_session[$name] = $value; return $this; } /** * 从session中删除一个值,失败返回false,成功返回连缀对象 * @param string $name * @return false|object */ public function del($name) { if ( ! $this->has($name) ) return false; unset($this->_session[$name]); return $this; } /** * 将session存放到tmp文件中 * @return void */ public function __destruct() { file_put_contents($this->_session_file, serialize($this->_session) ); }}
环境使用角色类 session:由于具体策略类已经完成,所以我们只需要定义一个常量用于区分是否是cli请求,同样使用单例模式自动装载对应的具体策略。
class session { public static function getinstance() { return application_is_cli ? session_cli::getinstance() : session_http::getinstance(); }}
测试过程:将设计的程序,通过http和cli方式分别测试:cli测试结果:
http测试结果:
虽然保存在 /tmp/ 目录下的内容格式不一致,但已经模拟出一个session仓库的功能,实现了对这个仓库的增删改查功能。
五.小结通过策略模式模拟一个虚拟的session功能,保证session在命令行下能够正常工作,为项目的自动化测试提供了基本支持。
策略模式其用意在于封装了一组新的算法,基于不同的策略下能够互相替换,为此我们能够在自动化测试中模拟出更多的功能,如请求的request功能,渲染的view功能等。
原创文章,转载请注明:原文标题:php命令行下模拟session机制
原文地址:http://www.crackedzone.com/php-cli-using-session-strategy.html
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录