Skip to content

Commit

Permalink
yii2 mongodb transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
ziaratban committed Jan 23, 2020
1 parent 8b1efe5 commit d90683a
Show file tree
Hide file tree
Showing 6 changed files with 500 additions and 193 deletions.
85 changes: 85 additions & 0 deletions src/ClientSession.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/

namespace yii\mongodb;

use Yii;


/**
* ClientSession represents a client session and Commands, queries, and write operations may then be associated the session.
* @see https://docs.mongodb.com/manual/release-notes/3.6/#client-sessions
* Note : At least 1.4.0 mongodb php driver version is supported.
* Note : At least 3.6 MongoDB version is supported.
* @see https://github.com/mongodb/mongo-php-driver/releases/tag/1.4.0
* @see https://docs.mongodb.com/ecosystem/drivers/php/#mongodb-compatibility
* @author Abolfazl Ziaratban <[email protected]>
*/
class ClientSession extends \yii\base\BaseObject
{

/**
* @var Connection the database connection that this transaction is associated with.
*/
public $db;

/**
* @var MongoDB\Driver\Session class represents a client session and Commands,
* queries, and write operations may then be associated the session.
* @see https://www.php.net/manual/en/class.mongodb-driver-session.php
*/
public $mongoSession;

/**
* @var Transaction current transaction in session. this transaction can only be created once.
*/
private $_transaction = null;

/**
* Start a new session in a connection.
* @param Connection $db
* @param Array $sessionOptions Creates a ClientSession for the given options
* @see https://www.php.net/manual/en/mongodb-driver-manager.startsession.php#refsect1-mongodb-driver-manager.startsession-parameters
* @return ClientSession return new session base on a session options for the given connection
*/
public static function start($db, $sessionOptions = []){
Yii::debug('Starting mongodb session ...', __METHOD__);
$db->trigger(Connection::EVENT_START_SESSION);
$newSession = new self([
'db' => $db,
'mongoSession' => $db->manager->startSession($sessionOptions),
]);
Yii::debug('MongoDB session started.', __METHOD__);
return $newSession;
}

/**
* Get current transaction of session or create a new transaction once
* @return Transaction return current transaction
*/
public function getTransaction(){
if($this->_transaction === null)
return $this->_transaction = new Transaction(['clientSession' => $this]);
return $this->_transaction;
}

/**
* current session has a transaction?
* @return bool return true if transaction exists otherwise return false
*/
public function getHasTransaction(){
return !empty($this->_transaction);
}

/**
* End current session
*/
public function end(){
$this->mongoSession->endSession();
$db->trigger(Connection::EVENT_END_SESSION);
}
}
98 changes: 56 additions & 42 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,25 @@ public function getFullName()

/**
* Drops this collection.
* @param array $execOptions -> goto Command::execute()
* @throws Exception on failure.
* @return bool whether the operation successful.
*/
public function drop()
public function drop($execOptions = [])
{
return $this->database->dropCollection($this->name);
return $this->database->dropCollection($this->name, $execOptions);
}

/**
* Returns the list of defined indexes.
* @return array list of indexes info.
* @param array $options list of options in format: optionName => optionValue.
* @param array $execOptions -> goto Command::execute()
* @since 2.1
*/
public function listIndexes($options = [])
public function listIndexes($options = [], $execOptions = [])
{
return $this->database->createCommand()->listIndexes($this->name, $options);
return $this->database->createCommand()->listIndexes($this->name, $options, $execOptions);
}

/**
Expand Down Expand Up @@ -107,23 +109,25 @@ public function listIndexes($options = [])
*
* See [[https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#options-for-all-index-types]]
* for the full list of options.
* @param array $execOptions -> goto Command::execute()
* @return bool whether operation was successful.
* @since 2.1
*/
public function createIndexes($indexes)
public function createIndexes($indexes, $execOptions = [])
{
return $this->database->createCommand()->createIndexes($this->name, $indexes);
return $this->database->createCommand()->createIndexes($this->name, $indexes, $execOptions);
}

/**
* Drops collection indexes by name.
* @param string $indexes wildcard for name of the indexes to be dropped.
* You can use `*` to drop all indexes.
* @param array $execOptions -> goto Command::execute()
* @return int count of dropped indexes.
*/
public function dropIndexes($indexes)
public function dropIndexes($indexes, $execOptions = [])
{
$result = $this->database->createCommand()->dropIndexes($this->name, $indexes);
$result = $this->database->createCommand()->dropIndexes($this->name, $indexes, $execOptions);
return $result['nIndexesWas'];
}

Expand All @@ -144,13 +148,14 @@ public function dropIndexes($indexes)
* ```
*
* @param array $options list of options in format: optionName => optionValue.
* @param array $execOptions -> goto Command::execute()
* @throws Exception on failure.
* @return bool whether the operation successful.
*/
public function createIndex($columns, $options = [])
public function createIndex($columns, $options = [], $execOptions = [])
{
$index = array_merge(['key' => $columns], $options);
return $this->database->createCommand()->createIndexes($this->name, [$index]);
return $this->database->createCommand()->createIndexes($this->name, [$index], $execOptions);
}

/**
Expand All @@ -171,17 +176,18 @@ public function createIndex($columns, $options = [])
* ]
* ```
*
* @param array $execOptions -> goto Command::execute()
* @throws Exception on failure.
* @return bool whether the operation successful.
*/
public function dropIndex($columns)
public function dropIndex($columns, $execOptions = [])
{
$existingIndexes = $this->listIndexes();

$indexKey = $this->database->connection->getQueryBuilder()->buildSortFields($columns);
foreach ($existingIndexes as $index) {
if ($index['key'] == $indexKey) {
$this->database->createCommand()->dropIndexes($this->name, $index['name']);
$this->database->createCommand()->dropIndexes($this->name, $index['name'], $execOptions);
return true;
}
}
Expand All @@ -190,7 +196,7 @@ public function dropIndex($columns)
$indexName = $this->database->connection->getQueryBuilder()->generateIndexName($indexKey);
foreach ($existingIndexes as $index) {
if ($index['name'] === $indexName) {
$this->database->createCommand()->dropIndexes($this->name, $index['name']);
$this->database->createCommand()->dropIndexes($this->name, $index['name'], $execOptions);
return true;
}
}
Expand All @@ -200,12 +206,13 @@ public function dropIndex($columns)

/**
* Drops all indexes for this collection.
* @param array $execOptions -> goto Command::execute()
* @throws Exception on failure.
* @return int count of dropped indexes.
*/
public function dropAllIndexes()
public function dropAllIndexes($execOptions = [])
{
$result = $this->database->createCommand()->dropIndexes($this->name, '*');
$result = $this->database->createCommand()->dropIndexes($this->name, '*', $execOptions);
return isset($result['nIndexesWas']) ? $result['nIndexesWas'] : 0;
}

Expand All @@ -215,28 +222,30 @@ public function dropAllIndexes()
* @param array $condition query condition
* @param array $fields fields to be selected
* @param array $options query options (available since 2.1).
* @param array $execOptions -> goto Command::executeQuery()
* @return \MongoDB\Driver\Cursor cursor for the search results
* @see Query
*/
public function find($condition = [], $fields = [], $options = [])
public function find($condition = [], $fields = [], $options = [], $execOptions = [])
{
if (!empty($fields)) {
$options['projection'] = $fields;
}
return $this->database->createCommand()->find($this->name, $condition, $options);
return $this->database->createCommand()->find($this->name, $condition, $options, $execOptions);
}

/**
* Returns a single document.
* @param array $condition query condition
* @param array $fields fields to be selected
* @param array $options query options (available since 2.1).
* @param array $execOptions -> goto Command::executeQuery()
* @return array|null the single document. Null is returned if the query results in nothing.
*/
public function findOne($condition = [], $fields = [], $options = [])
public function findOne($condition = [], $fields = [], $options = [], $execOptions = [])
{
$options['limit'] = 1;
$cursor = $this->find($condition, $fields, $options);
$cursor = $this->find($condition, $fields, $options, $execOptions);
$rows = $cursor->toArray();
return empty($rows) ? null : current($rows);
}
Expand All @@ -249,33 +258,35 @@ public function findOne($condition = [], $fields = [], $options = [])
* @return array|null the original document, or the modified document when $options['new'] is set.
* @throws Exception on failure.
*/
public function findAndModify($condition, $update, $options = [])
public function findAndModify($condition, $update, $options = [], $execOptions = [])
{
return $this->database->createCommand()->findAndModify($this->name, $condition, $update, $options);
return $this->database->createCommand()->findAndModify($this->name, $condition, $update, $options, $execOptions);
}

/**
* Inserts new data into collection.
* @param array|object $data data to be inserted.
* @param array $options list of options in format: optionName => optionValue.
* @return \MongoDB\BSON\ObjectID new record ID instance.
* @param array $execOptions -> goto Command::executeBatch()
* @throws Exception on failure.
*/
public function insert($data, $options = [])
public function insert($data, $options = [], $execOptions = [])
{
return $this->database->createCommand()->insert($this->name, $data, $options);
return $this->database->createCommand()->insert($this->name, $data, $options, $execOptions);
}

/**
* Inserts several new rows into collection.
* @param array $rows array of arrays or objects to be inserted.
* @param array $options list of options in format: optionName => optionValue.
* @param array $execOptions -> goto Command::executeBatch()
* @return array inserted data, each row will have "_id" key assigned to it.
* @throws Exception on failure.
*/
public function batchInsert($rows, $options = [])
public function batchInsert($rows, $options = [], $execOptions = [])
{
$insertedIds = $this->database->createCommand()->batchInsert($this->name, $rows, $options);
$insertedIds = $this->database->createCommand()->batchInsert($this->name, $rows, $options, $execOptions);
foreach ($rows as $key => $row) {
$rows[$key]['_id'] = $insertedIds[$key];
}
Expand All @@ -289,12 +300,13 @@ public function batchInsert($rows, $options = [])
* @param array $condition description of the objects to update.
* @param array $newData the object with which to update the matching records.
* @param array $options list of options in format: optionName => optionValue.
* @param array $execOptions -> goto Command::executeBatch()
* @return int|bool number of updated documents or whether operation was successful.
* @throws Exception on failure.
*/
public function update($condition, $newData, $options = [])
public function update($condition, $newData, $options = [], $execOptions = [])
{
$writeResult = $this->database->createCommand()->update($this->name, $condition, $newData, $options);
$writeResult = $this->database->createCommand()->update($this->name, $condition, $newData, $options, $execOptions);
return $writeResult->getModifiedCount() + $writeResult->getUpsertedCount();
}

Expand All @@ -303,16 +315,17 @@ public function update($condition, $newData, $options = [])
* @param array|object $data data to be updated/inserted.
* @param array $options list of options in format: optionName => optionValue.
* @return \MongoDB\BSON\ObjectID updated/new record id instance.
* @param array $execOptions -> goto Command::executeBatch()
* @throws Exception on failure.
*/
public function save($data, $options = [])
public function save($data, $options = [], $execOptions = [])
{
if (empty($data['_id'])) {
return $this->insert($data, $options);
return $this->insert($data, $options, $execOptions);
}
$id = $data['_id'];
unset($data['_id']);
$this->update(['_id' => $id], ['$set' => $data], ['upsert' => true]);
$this->update(['_id' => $id], ['$set' => $data], ['upsert' => true], $execOptions);

return is_object($id) ? $id : new ObjectID($id);
}
Expand All @@ -321,13 +334,14 @@ public function save($data, $options = [])
* Removes data from the collection.
* @param array $condition description of records to remove.
* @param array $options list of options in format: optionName => optionValue.
* @param array $execOptions -> goto Command::executeBatch()
* @return int|bool number of updated documents or whether operation was successful.
* @throws Exception on failure.
*/
public function remove($condition = [], $options = [])
public function remove($condition = [], $options = [], $execOptions = [])
{
$options = array_merge(['limit' => 0], $options);
$writeResult = $this->database->createCommand()->delete($this->name, $condition, $options);
$writeResult = $this->database->createCommand()->delete($this->name, $condition, $options, $execOptions);
return $writeResult->getDeletedCount();
}

Expand All @@ -338,9 +352,9 @@ public function remove($condition = [], $options = [])
* @return int records count.
* @since 2.1
*/
public function count($condition = [], $options = [])
public function count($condition = [], $options = [], $execOptions = [])
{
return $this->database->createCommand()->count($this->name, $condition, $options);
return $this->database->createCommand()->count($this->name, $condition, $options, $execOptions);
}

/**
Expand All @@ -351,9 +365,9 @@ public function count($condition = [], $options = [])
* @return array|bool array of distinct values, or "false" on failure.
* @throws Exception on failure.
*/
public function distinct($column, $condition = [], $options = [])
public function distinct($column, $condition = [], $options = [], $execOptions = [])
{
return $this->database->createCommand()->distinct($this->name, $column, $condition, $options);
return $this->database->createCommand()->distinct($this->name, $column, $condition, $options, $execOptions);
}

/**
Expand All @@ -365,9 +379,9 @@ public function distinct($column, $condition = [], $options = [])
* @return array|\MongoDB\Driver\Cursor the result of the aggregation.
* @throws Exception on failure.
*/
public function aggregate($pipelines, $options = [])
public function aggregate($pipelines, $options = [], $execOptions = [])
{
return $this->database->createCommand()->aggregate($this->name, $pipelines, $options);
return $this->database->createCommand()->aggregate($this->name, $pipelines, $options, $execOptions);
}

/**
Expand All @@ -385,9 +399,9 @@ public function aggregate($pipelines, $options = [])
* @return array the result of the aggregation.
* @throws Exception on failure.
*/
public function group($keys, $initial, $reduce, $options = [])
public function group($keys, $initial, $reduce, $options = [], $execOptions = [])
{
return $this->database->createCommand()->group($this->name, $keys, $initial, $reduce, $options);
return $this->database->createCommand()->group($this->name, $keys, $initial, $reduce, $options, $execOptions);
}

/**
Expand Down Expand Up @@ -429,8 +443,8 @@ public function group($keys, $initial, $reduce, $options = [])
* @return string|array the map reduce output collection name or output results.
* @throws Exception on failure.
*/
public function mapReduce($map, $reduce, $out, $condition = [], $options = [])
public function mapReduce($map, $reduce, $out, $condition = [], $options = [], $execOptions = [])
{
return $this->database->createCommand()->mapReduce($this->name, $map, $reduce, $out, $condition, $options);
return $this->database->createCommand()->mapReduce($this->name, $map, $reduce, $out, $condition, $options, $execOptions);
}
}
Loading

0 comments on commit d90683a

Please sign in to comment.