我正在研究一組組件(希望能成爲一個完整的框架),並且目前正致力於提供一個PHP會話的抽象。構建一個更可測試的會話管理器
我試圖讓代碼儘可能地成爲可測試的,但是按照定義,會話類將以$ _SESSION超全局的形式依賴於全局狀態。
我試圖實現這樣的方式$ SESSION和會話 *函數只被調用在一個地方,我就可以在PHPUnit的覆蓋用於測試目的我的會話課,但我不能幫但不知道是否有更好的方法來做到這一點。
如果你可以建議一個更好的方法來做一個可測試的會話類,那麼我會很感激你可能有任何輸入。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
namespace gordian\reefknot\storage\session;
use gordian\reefknot\storage;
/**
* Session management
*
* Each instance of the Session object represents a "namespace" within the PHP
* $_SESSION system. This allows sessions to be easily managed and organized
* within an application
*
*/
class Session implements storage\iface\Crud, iface\Session
{
protected
$name = '',
$storage = NULL;
/**
* Add a new item to the session
*
* @param mixed $data
* @param string $key
* @return Session
* @throws \InvalidArgumentException Thrown if no name is provided
*/
public function createItem ($data, $key)
{
if (!empty ($key))
{
$key = (string) $key;
if (($this -> storage === NULL)
|| (!array_key_exists ($key, $this -> storage)))
{
$this -> storage [$key] = $data;
}
}
else
{
throw new \Exception ('No valid key given');
}
return ($this);
}
/**
* Delete the specified key
*
* @param string $key
* @return Session
*/
public function deleteItem ($key)
{
unset ($this -> storage [$key]);
return ($this);
}
/**
* Retrieve the data stored in the specified key
*
* @param type $key
* @return mixed
*/
public function readItem ($key)
{
return (array_key_exists ($key, $this -> storage)?
$this -> storage ['key']:
NULL);
}
/**
* Update a previously stored data item to a new value
*
* @param mixed $data
* @param string $key
*/
public function updateItem ($data, $key)
{
if ($this -> storage === NULL)
{
throw new \RuntimeException ('Session contains no data');
}
if (array_key_exists ($key, $this -> storage))
{
$this -> storage [$key] = $data;
}
return ($this);
}
/**
* Clear the session of all stored data
*
* @return Session
*/
public function reset()
{
$this -> storage = NULL;
return ($this);
}
/**
* Retrieve all data stored in the session
*
* @return array
*/
public function getAll()
{
return ($this -> storage);
}
/**
* Return whether there is data stored in this session
*
* @return bool
*/
public function hasData()
{
return (!empty ($this -> storage));
}
/**
* Initialize the back-end storage for the session
*
* This method provides access for this class to the underlying PHP session
* mechanism.
*
* @return bool Whether the newly initialized session contains data or not
* @throws \RuntimeException Will be thrown if the session failed to start
*/
protected function initStorage()
{
// Check that storage hasn't already been initialized
if ($this -> storage === NULL)
{
// Attempt to start the session if it hasn't already been started
if ((session_id() === '')
&& ((headers_sent())
|| ((!session_start()))))
{
throw new \RuntimeException ('Unable to start session at this time');
}
// Alias our instance storage to the named $_SESSION variable
$this -> storage =& $_SESSION [$this -> name];
}
return ($this -> hasData());
}
/**
* Class constructor
*
* @param string $sessName
* @throws \InvalidArgumentException Thrown if no session name is provided
*/
public function __construct ($sessName)
{
if (!empty ($sessName))
{
$this -> name = $sessName;
$this -> initStorage();
}
else
{
throw new \InvalidArgumentException ('Session must have a name');
}
}
}
爲了測試,目前的計劃是與剛剛設置了一個內部數組代替的方法,以取代initStorage()。如果你能提出更好的方法,我會很樂意聽到它。