Magento session機制的分析與應用

 

Magento session機制的分析與應用


Magento session實現一定是基於php、apache的,呵呵,因爲Magento是基於php寫的,一般運行在apache web服務器上。所以理解php、apache本身的session實現機制對理解Magento session實現有很大的幫助.

php apache session的機制簡要說明

您可以新建一個test.php文件,文件內容如下:
代碼塊1:

  1. <?php
  2. session_start();
  3. $_SESSION['string'] = ‘string value’;
  4. $_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

  1. 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:

  1. 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

  1. <?php
  2. session_start();
  3. echo ($_SESSION['string']);
  4. 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:

  1. <?php
  2. session_name(‘frontend’);
  3. session_start();
  4. $_SESSION['string'] = ‘string value’;
  5. $_SESSION['array'] = array(‘key1′ => ‘key value1′, ‘key2′ => ‘key value2′);

這樣在第一次set-cookie時不再使用PHPSESSID,而是變成了frontend.session_name一定要在session_start之前調用,不然不會起作用.
當然在取$_SESSION中的值是也要在session_start之前調用session_name方法,如下:
代碼塊6:

  1. <?php
  2. session_name(‘frontend’);
  3. session_start();
  4. echo ($_SESSION['string']);
  5. 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

  1. $namespace = $this->getLayout()->getArea();
  2. 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:

  1. public function __construct($data=array())
  2. {
  3. $name = isset($data['name']) ? $data['name'] : null;
  4. $this->init(‘core’, $name);
  5. }

第3行得到的值爲frontend或者adminhtml(根據前後臺不同此值不同),第4行將調用父類的Mage_Core_Model_Session_Abstract中的init方法,這裏有兩個參數,每1個是在$_SESSION中的分組的名稱,第2個是session_name的值,由於這是每一次調用,所經要設置session_name,如果是後繼的使用,則不一定要傳這個值。Mage_Core_Model_Session_Abstract中的init方法:
代碼塊9:

  1. public function init($namespace, $sessionName=null)
  2. {
  3. parent::init($namespace, $sessionName);
  4. $this->addHost(true);
  5. return $this;
  6. }

第3行代碼調用他父類(Mage_Core_Model_Session_Abstract_Varien)的init方法,把分組名和session_name傳入.此init方法定義如下:
代碼塊10:

  1. public function init($namespace, $sessionName=null)
  2. {
  3. if (!isset($_SESSION)) {
  4. $this->start($sessionName);
  5. }
  6. if (!isset($_SESSION[$namespace])) {
  7. $_SESSION[$namespace] = array();
  8. }
  9. $this->_data = &$_SESSION[$namespace];
  10. $this->validate();
  11. $this->revalidateCookie();
  12. return $this;
  13. }

行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中去取。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章