Skip to content

Commit

Permalink
Merge pull request #26 from jasny/2.0-mongo
Browse files Browse the repository at this point in the history
Added Mongo support.
  • Loading branch information
desarrolla2 committed Nov 26, 2015
2 parents 0fb4f14 + 47bb6fd commit 5a9b1b5
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 2 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,54 @@ $cache = new Cache($adapter);

```

### Mongo

Use it to store the cache in a Mongo database. Requires the
[(legacy) mongo extension](http://php.net/mongo) or the
[mongodb/mongodb](https://github.com/mongodb/mongo-php-library) library.

You may pass either a database or collection object to the constructor. If a
database object is passed, the `items` collection within that DB is used.

``` php
<?php

use Desarrolla2\Cache\Cache;
use Desarrolla2\Cache\Adapter\Mongo;

$client = new MongoClient($dsn);
$database = $client->selectDatabase($dbname);

$adapter = new Mongo($database);
$adapter->setOption('ttl', 3600);
$cache = new Cache($adapter);

```

``` php
<?php

use Desarrolla2\Cache\Cache;
use Desarrolla2\Cache\Adapter\Mongo;

$client = new MongoClient($dsn);
$database = $client->selectDatabase($dbName);
$collection = $database->selectCollection($collectionName);

$adapter = new Mongo($collection);
$adapter->setOption('ttl', 3600);
$cache = new Cache($adapter);

```

_Note that expired cache items aren't automatically deleted. To keep your
database clean, you should create a
[ttl index](https://docs.mongodb.org/manual/core/index-ttl/)._


```
db.items.createIndex( { "ttl": 1 }, { expireAfterSeconds: 30 } )
```

### Mysqli

Expand Down
113 changes: 113 additions & 0 deletions src/Adapter/Mongo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

/*
* This file is part of the Cache package.
*
* Copyright (c) Daniel González
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @author Daniel González <daniel@desarrolla2.com>
*/

namespace Desarrolla2\Cache\Adapter;

use Desarrolla2\Cache\Exception\CacheException;

/**
* Mongo
*/
class Mongo extends AbstractAdapter implements AdapterInterface
{
/**
* @var MongoCollection|MongoDB\Collection
*/
protected $collection;

/**
* @param MongoDB|MongoDB\Database|MongoCollection|MongoDB\Collection $backend
*/
public function __construct($backend = null)
{
if (!isset($backend)) {
$client = class_exist('MongoCollection') ? new \MongoClient() : new \MongoDB\Client();
$backend = $client->selectDatabase('cache');
}

if ($backend instanceof \MongoCollection || $backend instanceof \MongoDB\Collection) {
$this->collection = $backend;
} elseif ($backend instanceof \MongoDB || $backend instanceof \MongoDB\Database) {
$this->collection = $backend->selectCollection('items');
} else {
$type = (is_object($database) ? get_class($database) . ' ' : '') . gettype($database);
throw new CacheException("Database should be a database (MongoDB or MongoDB\Database) or " .
" collection (MongoCollection or MongoDB\Collection) object, not a $type");
}
}

/**
* {@inheritdoc}
*/
public function del($key)
{
$tKey = $this->getKey($key);
$this->collection->remove(array('_id' => $tKey));
}

/**
* {@inheritdoc }
*/
public function get($key)
{
$tKey = $this->getKey($key);
$tNow = $this->getTtl();
$data = $this->collection->findOne(array('_id' => $tKey, 'ttl' => array('$gte' => $tNow)));
if (isset($data)) {
return $this->unPack($data['value']);
}

return false;
}

/**
* {@inheritdoc }
*/
public function has($key)
{
$tKey = $this->getKey($key);
$tNow = $this->getTtl();
return $this->collection->count(array('_id' => $tKey, 'ttl' => array('$gte' => $tNow))) > 0;
}

/**
* {@inheritdoc }
*/
public function set($key, $value, $ttl = null)
{
$tKey = $this->getKey($key);
$tValue = $this->pack($value);
if (!$ttl) {
$ttl = $this->ttl;
}
$item = array(
'_id' => $tKey,
'value' => $tValue,
'ttl' => $this->getTtl($ttl),
);
$this->collection->update(array('_id' => $tKey), $item, array('upsert' => true));
}

/**
* Get TTL as Date type BSON object
*
* @param int $ttl
* @return MongoDate|MongoDB\BSON\UTCDatetime
*/
protected function getTtl($ttl = 0)
{
return $this->collection instanceof \MongoCollection ?
new \MongoDate((int) $ttl + time()) :
new \MongoDB\BSON\UTCDatetime(((int) $ttl + time() * 1000));
}
}
61 changes: 61 additions & 0 deletions tests/Adapter/MongoTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/*
* This file is part of the Cache package.
*
* Copyright (c) Daniel González
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @author Daniel González <daniel@desarrolla2.com>
*/

namespace Desarrolla2\Test\Cache\Adapter;

use Desarrolla2\Cache\Cache;
use Desarrolla2\Cache\Adapter\Mongo;

/**
* MongoTest
*/
class MongoTest extends AbstractCacheTest
{
public function setUp()
{
parent::setup();
if (!extension_loaded('mongo')) {
$this->markTestSkipped(
'The mongo extension is not available.'
);
}

$client = new \MongoClient($this->config['mongo']['dsn']);
$database = $client->selectDB($this->config['mongo']['database']);

$this->cache = new Cache(
new Mongo($database)
);
}

/**
* @return array
*/
public function dataProviderForOptions()
{
return [
['ttl', 100],
];
}

/**
* @return array
*/
public function dataProviderForOptionsException()
{
return [
['ttl', 0, '\Desarrolla2\Cache\Exception\CacheException'],
['file', 100, '\Desarrolla2\Cache\Exception\CacheException'],
];
}
}
5 changes: 3 additions & 2 deletions tests/config.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"port": "11211"
},
"mongo": {
"dns": "mongodb://localhost:27017"
"dsn": "mongodb://localhost:27017",
"database": "cache"
},
"mysql": {
"user": "root",
Expand All @@ -16,4 +17,4 @@
"port": "3306",
"database": "cache"
}
}
}

0 comments on commit 5a9b1b5

Please sign in to comment.