4 * Zend Framework (http://framework.zend.com/)
6 * @link http://github.com/zendframework/zf2 for the canonical source repository
7 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
8 * @license http://framework.zend.com/license/new-bsd New BSD License
11 namespace Zend\Session\SaveHandler
;
15 use Zend\Session\Exception\InvalidArgumentException
;
18 * MongoDB session save handler
20 class MongoDB
implements SaveHandlerInterface
23 * MongoCollection instance
25 * @var MongoCollection
27 protected $mongoCollection;
34 protected $sessionName;
44 * MongoDB session save handler options
52 * @param Mongo|MongoClient $mongo
53 * @param MongoDBOptions $options
54 * @throws Zend\Session\Exception\InvalidArgumentException
56 public function __construct($mongo, MongoDBOptions
$options)
58 if (!($mongo instanceof \MongoClient ||
$mongo instanceof \Mongo
)) {
59 throw new InvalidArgumentException(
60 'Parameter of type %s is invalid; must be MongoClient or Mongo',
61 (is_object($mongo) ?
get_class($mongo) : gettype($mongo))
65 if (null === ($database = $options->getDatabase())) {
66 throw new InvalidArgumentException('The database option cannot be emtpy');
69 if (null === ($collection = $options->getCollection())) {
70 throw new InvalidArgumentException('The collection option cannot be emtpy');
73 $this->mongoCollection
= $mongo->selectCollection($database, $collection);
74 $this->options
= $options;
80 * @param string $savePath
84 public function open($savePath, $name)
86 // Note: session save path is not used
87 $this->sessionName
= $name;
88 $this->lifetime
= ini_get('session.gc_maxlifetime');
98 public function close()
109 public function read($id)
111 $session = $this->mongoCollection
->findOne(array(
113 $this->options
->getNameField() => $this->sessionName
,
116 if (null !== $session) {
117 if ($session[$this->options
->getModifiedField()] instanceof MongoDate
&&
118 $session[$this->options
->getModifiedField()]->sec +
119 $session[$this->options
->getLifetimeField()] > time()) {
120 return $session[$this->options
->getDataField()];
132 * @param string $data
135 public function write($id, $data)
137 $saveOptions = array_replace(
138 $this->options
->getSaveOptions(),
139 array('upsert' => true, 'multiple' => false)
144 $this->options
->getNameField() => $this->sessionName
,
147 $newObj = array('$set' => array(
148 $this->options
->getDataField() => (string) $data,
149 $this->options
->getLifetimeField() => $this->lifetime
,
150 $this->options
->getModifiedField() => new MongoDate(),
153 /* Note: a MongoCursorException will be thrown if a record with this ID
154 * already exists with a different session name, since the upsert query
155 * cannot insert a new document with the same ID and new session name.
156 * This should only happen if ID's are not unique or if the session name
157 * is altered mid-process.
159 $result = $this->mongoCollection
->update($criteria, $newObj, $saveOptions);
161 return (bool) (isset($result['ok']) ?
$result['ok'] : $result);
170 public function destroy($id)
172 $result = $this->mongoCollection
->remove(array(
174 $this->options
->getNameField() => $this->sessionName
,
175 ), $this->options
->getSaveOptions());
177 return (bool) (isset($result['ok']) ?
$result['ok'] : $result);
183 * Note: MongoDB 2.2+ supports TTL collections, which may be used in place
184 * of this method by indexing the "modified" field with an
185 * "expireAfterSeconds" option. Regardless of whether TTL collections are
186 * used, consider indexing this field to make the remove query more
189 * @see http://docs.mongodb.org/manual/tutorial/expire-data/
190 * @param int $maxlifetime
193 public function gc($maxlifetime)
195 /* Note: unlike DbTableGateway, we do not use the lifetime field in
196 * each document. Doing so would require a $where query to work with the
197 * computed value (modified + lifetime) and be very inefficient.
199 $result = $this->mongoCollection
->remove(array(
200 $this->options
->getModifiedField() => array('$lt' => new MongoDate(time() - $maxlifetime)),
201 ), $this->options
->getSaveOptions());
203 return (bool) (isset($result['ok']) ?
$result['ok'] : $result);