Magento session机制的分析与应用
Magento session实现一定是基于php、apache的,呵呵,因为Magento是基于php写的,一般运行在apache web服务器上。所以理解php、apache本身的session实现机制对理解Magento session实现有很大的帮助.
php apache session的机制简要说明
您可以新建一个test.php文件,文件内容如下:
代码块1:
- <?php
- session_start();
- $_SESSION['string'] = ‘string value’;
- $_SESSION['array'] = array(‘key1′ => ‘key value1′, ‘key2′ => ‘key value2′);
打开浏览器,输入http://yourdomain/test.php,如果您是第一次访问这个domain(如果不是,建议你先清除掉cookie),
此时您可以打开FF,您可以在代码调试器中看到:
Response Headers 说明web服务器把回给浏览器的东东,其中蓝色底部份设置了一个cookie给浏览器,存储在客户端,供后继使用.
我们重点要分析一下蓝色底部份设置,这里给浏览器设置了下cookie 其中cookie的id为:PHPSESSID,值为随机生成的一串数据(可以看出)。在服务端我们要向客户端写cookie,一般要通过编码的方式,如在php中使用:setcookie这个方法。但是从代码块1中我们并没有使用setcookie方法向客户端写cookie,那它这个cookie是怎样写过去的呢,原因只有一个,由session_start();写过去的。那cookie的key PHPSESSID这个值又是来自那里呢?
我们看一下php.ini文件中的如下几行代码:
代码块2
-
session.name = PHPSESSID; Initialize session on request startup.
session.auto_start = 0; Lifetime in seconds of cookie or, if 0, until browser is restarted.
session.cookie_lifetime = 0; The path for which the cookie is valid.
session.cookie_path = /; The domain for which the cookie is valid.
session.cookie_domain =; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript.
session.cookie_httponly =
从以上配置信息可以看到session.name就是用来设置这个cookie的id的.一般会在服务器上生成一个sess_*(随机生成的串)的文本文件(我没修改过session.cookie_path,使用的是window操作系统,生成在windows/temp目录下).
内容如下:
代码块3:
- string|s:12:”string value”;array|a:2:{s:4:”key1″;s:10:”key value1″;s:4:”key2″;s:10:”key value2″;}
这是一个josn对象,是代码块1,行3,4的结果.
到目前为止,服务器端把用户的session 数据以cookie名为PHPSESSID的值作为文件名保存在服务端了,同时把这个cookie发送到了客户端,保存到了客户端的硬盘上,其实在服务端和客户端建立了一个联系.
我们再新建一个页面get_session.php:
代码块4
- <?php
- session_start();
- echo ($_SESSION['string']);
- print_r($_SESSION['array']) ;
此时,您可以打开FF,您可以在代码调试器中看到:
此时Response Headers中没有了set-cookie了,而在Request Headers中有一个Cookie蓝色底部份,这里的数据是客户端发送到服务端的cookie数据。服务器中的session_start()会拿到PHPSESSID这个cookie,从而得到这个cookie的值,再到文件系统中去读取那个文件,把文件的内容还原到_SESSION变量中,从而用来识别这个用户.只要用户不清除cookie和cookie没有到期,那么用户访问这个domain中的任一页面,都会带着这个cookie提交到服务端,从而服务端可以识别是这个用户.
修改PHPSESSID为您自定义的值
默认情况下我们使用PHPSESSID这个词作为前后台(客户端和服务器端)的沟通桥梁,但是一般在我们的应用中,我们不想使用这个词,那么我们可以通过php自带的方法session_name()这个方法修改。
代码块5:
- <?php
- session_name(‘frontend’);
- session_start();
- $_SESSION['string'] = ‘string value’;
- $_SESSION['array'] = array(‘key1′ => ‘key value1′, ‘key2′ => ‘key value2′);
这样在第一次set-cookie时不再使用PHPSESSID,而是变成了frontend.session_name一定要在session_start之前调用,不然不会起作用.
当然在取$_SESSION中的值是也要在session_start之前调用session_name方法,如下:
代码块6:
- <?php
- session_name(‘frontend’);
- session_start();
- echo ($_SESSION['string']);
- print_r($_SESSION['array']) ;
Magento session的机制
(1):Magento中的前台和后台的session是分开的,也就是说前台和后台使用不同的key值进行客户端和服务器会话沟通,前端使用frontend后台使用adminhtml,这样前台和后台同时在一台机上使用时,不会发生seesion混乱的情况.
(2):session数据,一般都是保存在$_SESSION这个全局变量中,但是在Magento中,$_SESSION数据被分成很多组,每一个组由一个session类进行封装。看如下Magento中session类图:
一看到Varien_Object类,我们就会想到有一个_data类变量保存这个类的数据,同时提供写数据方法(set/setData)和读数据的方法(get/getData).
上图中带色部份,为最底层业务实现的session类,用来分离$_SESSION中的数据,进行分别的管理。如Mage_Core_Model_Session中的分组名为:core,Mage_Customer_Model_Session的分组名为customer,Mage_Checkout_Model_Session中的分组名为checkout.那么现在$_SESSION中的实际数据看上去如下$_SESSION=array(‘core’=>array(…), ‘customer’=>array(…), ‘checkout’=>array(…),…)其中Mage_Core_Model_Session,Mage_Customer_Model_Session,Mage_Checkout_Model_Session中的_data分别拥有core,customer,checkout中数组的引用,所以对这三个类中的_data操作,实际上是对全局变量$_SESSION中的三个数组的操作。如果我们要自定义自己的$_SESSION中的数据分组,可以定义一个类似上面的类,并在此类中定义其$_SESSION中的分组就可以了。
(3):Magento中session的初始化:
在Mage_Core_Controller_Varien_Action类中(用户控制器中的项层类)的preDispatch方法中有如下代码:
代码块7
- $namespace = $this->getLayout()->getArea();
- Mage::getSingleton(‘core/session’, array(‘name’ => $namespace))->start();
其中第一行中得到的area值是在前端用户控制器类(Mage_Core_Controller_Front_Action)和后台用户控制器类(Mage_Adminhtml_Controller_Action)中preDispatch方法中设置的frontend和adminhtml,这个值其实是我们上面分析的session_name的值。
行2初始化了一个core/session类,其实是Mage_Core_Model_Session类的实例,此类的初始化方法如下:
代码块8:
- public function __construct($data=array())
- {
- $name = isset($data['name']) ? $data['name'] : null;
- $this->init(‘core’, $name);
- }
第3行得到的值为frontend或者adminhtml(根据前后台不同此值不同),第4行将调用父类的Mage_Core_Model_Session_Abstract中的init方法,这里有两个参数,每1个是在$_SESSION中的分组的名称,第2个是session_name的值,由于这是每一次调用,所经要设置session_name,如果是后继的使用,则不一定要传这个值。Mage_Core_Model_Session_Abstract中的init方法:
代码块9:
- public function init($namespace, $sessionName=null)
- {
- parent::init($namespace, $sessionName);
- $this->addHost(true);
- return $this;
- }
第3行代码调用他父类(Mage_Core_Model_Session_Abstract_Varien)的init方法,把分组名和session_name传入.此init方法定义如下:
代码块10:
- public function init($namespace, $sessionName=null)
- {
- if (!isset($_SESSION)) {
- $this->start($sessionName);
- }
- if (!isset($_SESSION[$namespace])) {
- $_SESSION[$namespace] = array();
- }
- $this->_data = &$_SESSION[$namespace];
- $this->validate();
- $this->revalidateCookie();
- return $this;
- }
行3,在没有调用session_start();之前,$_SESSION是没有被定义的,所以初始化时,行3是一定会被执行的,只要初始化后,行4是不被执行了。所以start方法在初始化时是会执行的,代码块7行2中的start()方法其实是不必要调的.行5-8如果分组中在$_SESSION没有,此先建立这个分组。行9把$_SESSION中分组的引用给session类中的_data.
start()方法您可以跟进去看一下,这个方法主要是说明:我们的session数据在服务端已一种什么方式存储。Magento1.3支持:文件、数据库、memcache。同时设置session_name,和cookie的一些参数据。
(4):Magento session中数据的使用,由于Magento中的$_SESSION中的数据被分成很多组(根据业务)封装到了各自的业务对象中,所以我们如果要取session中的数据,不要直接到$_SESSION中去取,而应该到这些封装类的中去取,如你要得到当前登录用户的一些信息或者看当前用户是否登录了,你可以到Mage_Customer_Model_Session中去取。