Skip to content

Commit 84ca383

Browse files
committed
yii2 mongodb transaction
1 parent 8b1efe5 commit 84ca383

File tree

6 files changed

+522
-193
lines changed

6 files changed

+522
-193
lines changed

src/ClientSession.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
/**
3+
* @link http://www.yiiframework.com/
4+
* @copyright Copyright (c) 2008 Yii Software LLC
5+
* @license http://www.yiiframework.com/license/
6+
*/
7+
8+
namespace yii\mongodb;
9+
10+
use Yii;
11+
12+
13+
/**
14+
* ClientSession represents a client session and Commands, queries, and write operations may then be associated the session.
15+
* @see https://docs.mongodb.com/manual/release-notes/3.6/#client-sessions
16+
* Note : At least 1.4.0 mongodb php driver version is supported.
17+
* Note : At least 3.6 MongoDB version is supported.
18+
* @see https://github.com/mongodb/mongo-php-driver/releases/tag/1.4.0
19+
* @see https://docs.mongodb.com/ecosystem/drivers/php/#mongodb-compatibility
20+
* @author Abolfazl Ziaratban <[email protected]>
21+
*/
22+
class ClientSession extends \yii\base\BaseObject
23+
{
24+
25+
/**
26+
* @var Connection the database connection that this transaction is associated with.
27+
*/
28+
public $db;
29+
30+
/**
31+
* @var MongoDB\Driver\Session class represents a client session and Commands,
32+
* queries, and write operations may then be associated the session.
33+
* @see https://www.php.net/manual/en/class.mongodb-driver-session.php
34+
*/
35+
public $mongoSession;
36+
37+
/**
38+
* @var Transaction current transaction in session. this transaction can only be created once.
39+
*/
40+
private $_transaction = null;
41+
42+
/**
43+
* Start a new session in a connection.
44+
* @param Connection $db
45+
* @param Array $sessionOptions Creates a ClientSession for the given options
46+
* @see https://www.php.net/manual/en/mongodb-driver-manager.startsession.php#refsect1-mongodb-driver-manager.startsession-parameters
47+
* @return ClientSession return new session base on a session options for the given connection
48+
*/
49+
public static function start($db, $sessionOptions = []){
50+
Connection::prepareExecOptions($sessionOptions);
51+
Yii::trace('Starting mongodb session ...', __METHOD__);
52+
$db->trigger(Connection::EVENT_START_SESSION);
53+
$newSession = new self([
54+
'db' => $db,
55+
'mongoSession' => $db->manager->startSession($sessionOptions),
56+
]);
57+
Yii::trace('MongoDB session started.', __METHOD__);
58+
return $newSession;
59+
}
60+
61+
/**
62+
* Get current transaction of session or create a new transaction once
63+
* @return Transaction return current transaction
64+
*/
65+
public function getTransaction(){
66+
if($this->_transaction === null)
67+
return $this->_transaction = new Transaction(['clientSession' => $this]);
68+
return $this->_transaction;
69+
}
70+
71+
/**
72+
* current session has a transaction?
73+
* @return bool return true if transaction exists otherwise return false
74+
*/
75+
public function getHasTransaction(){
76+
return !empty($this->_transaction);
77+
}
78+
79+
/**
80+
* End current session
81+
*/
82+
public function end(){
83+
$this->mongoSession->endSession();
84+
$db->trigger(Connection::EVENT_END_SESSION);
85+
}
86+
}

src/Collection.php

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,25 @@ public function getFullName()
5656

5757
/**
5858
* Drops this collection.
59+
* @param array $execOptions -> goto Command::execute()
5960
* @throws Exception on failure.
6061
* @return bool whether the operation successful.
6162
*/
62-
public function drop()
63+
public function drop($execOptions = [])
6364
{
64-
return $this->database->dropCollection($this->name);
65+
return $this->database->dropCollection($this->name, $execOptions);
6566
}
6667

6768
/**
6869
* Returns the list of defined indexes.
6970
* @return array list of indexes info.
7071
* @param array $options list of options in format: optionName => optionValue.
72+
* @param array $execOptions -> goto Command::execute()
7173
* @since 2.1
7274
*/
73-
public function listIndexes($options = [])
75+
public function listIndexes($options = [], $execOptions = [])
7476
{
75-
return $this->database->createCommand()->listIndexes($this->name, $options);
77+
return $this->database->createCommand()->listIndexes($this->name, $options, $execOptions);
7678
}
7779

7880
/**
@@ -107,23 +109,25 @@ public function listIndexes($options = [])
107109
*
108110
* See [[https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#options-for-all-index-types]]
109111
* for the full list of options.
112+
* @param array $execOptions -> goto Command::execute()
110113
* @return bool whether operation was successful.
111114
* @since 2.1
112115
*/
113-
public function createIndexes($indexes)
116+
public function createIndexes($indexes, $execOptions = [])
114117
{
115-
return $this->database->createCommand()->createIndexes($this->name, $indexes);
118+
return $this->database->createCommand()->createIndexes($this->name, $indexes, $execOptions);
116119
}
117120

118121
/**
119122
* Drops collection indexes by name.
120123
* @param string $indexes wildcard for name of the indexes to be dropped.
121124
* You can use `*` to drop all indexes.
125+
* @param array $execOptions -> goto Command::execute()
122126
* @return int count of dropped indexes.
123127
*/
124-
public function dropIndexes($indexes)
128+
public function dropIndexes($indexes, $execOptions = [])
125129
{
126-
$result = $this->database->createCommand()->dropIndexes($this->name, $indexes);
130+
$result = $this->database->createCommand()->dropIndexes($this->name, $indexes, $execOptions);
127131
return $result['nIndexesWas'];
128132
}
129133

@@ -144,13 +148,14 @@ public function dropIndexes($indexes)
144148
* ```
145149
*
146150
* @param array $options list of options in format: optionName => optionValue.
151+
* @param array $execOptions -> goto Command::execute()
147152
* @throws Exception on failure.
148153
* @return bool whether the operation successful.
149154
*/
150-
public function createIndex($columns, $options = [])
155+
public function createIndex($columns, $options = [], $execOptions = [])
151156
{
152157
$index = array_merge(['key' => $columns], $options);
153-
return $this->database->createCommand()->createIndexes($this->name, [$index]);
158+
return $this->database->createCommand()->createIndexes($this->name, [$index], $execOptions);
154159
}
155160

156161
/**
@@ -171,17 +176,18 @@ public function createIndex($columns, $options = [])
171176
* ]
172177
* ```
173178
*
179+
* @param array $execOptions -> goto Command::execute()
174180
* @throws Exception on failure.
175181
* @return bool whether the operation successful.
176182
*/
177-
public function dropIndex($columns)
183+
public function dropIndex($columns, $execOptions = [])
178184
{
179185
$existingIndexes = $this->listIndexes();
180186

181187
$indexKey = $this->database->connection->getQueryBuilder()->buildSortFields($columns);
182188
foreach ($existingIndexes as $index) {
183189
if ($index['key'] == $indexKey) {
184-
$this->database->createCommand()->dropIndexes($this->name, $index['name']);
190+
$this->database->createCommand()->dropIndexes($this->name, $index['name'], $execOptions);
185191
return true;
186192
}
187193
}
@@ -190,7 +196,7 @@ public function dropIndex($columns)
190196
$indexName = $this->database->connection->getQueryBuilder()->generateIndexName($indexKey);
191197
foreach ($existingIndexes as $index) {
192198
if ($index['name'] === $indexName) {
193-
$this->database->createCommand()->dropIndexes($this->name, $index['name']);
199+
$this->database->createCommand()->dropIndexes($this->name, $index['name'], $execOptions);
194200
return true;
195201
}
196202
}
@@ -200,12 +206,13 @@ public function dropIndex($columns)
200206

201207
/**
202208
* Drops all indexes for this collection.
209+
* @param array $execOptions -> goto Command::execute()
203210
* @throws Exception on failure.
204211
* @return int count of dropped indexes.
205212
*/
206-
public function dropAllIndexes()
213+
public function dropAllIndexes($execOptions = [])
207214
{
208-
$result = $this->database->createCommand()->dropIndexes($this->name, '*');
215+
$result = $this->database->createCommand()->dropIndexes($this->name, '*', $execOptions);
209216
return isset($result['nIndexesWas']) ? $result['nIndexesWas'] : 0;
210217
}
211218

@@ -215,28 +222,30 @@ public function dropAllIndexes()
215222
* @param array $condition query condition
216223
* @param array $fields fields to be selected
217224
* @param array $options query options (available since 2.1).
225+
* @param array $execOptions -> goto Command::executeQuery()
218226
* @return \MongoDB\Driver\Cursor cursor for the search results
219227
* @see Query
220228
*/
221-
public function find($condition = [], $fields = [], $options = [])
229+
public function find($condition = [], $fields = [], $options = [], $execOptions = [])
222230
{
223231
if (!empty($fields)) {
224232
$options['projection'] = $fields;
225233
}
226-
return $this->database->createCommand()->find($this->name, $condition, $options);
234+
return $this->database->createCommand()->find($this->name, $condition, $options, $execOptions);
227235
}
228236

229237
/**
230238
* Returns a single document.
231239
* @param array $condition query condition
232240
* @param array $fields fields to be selected
233241
* @param array $options query options (available since 2.1).
242+
* @param array $execOptions -> goto Command::executeQuery()
234243
* @return array|null the single document. Null is returned if the query results in nothing.
235244
*/
236-
public function findOne($condition = [], $fields = [], $options = [])
245+
public function findOne($condition = [], $fields = [], $options = [], $execOptions = [])
237246
{
238247
$options['limit'] = 1;
239-
$cursor = $this->find($condition, $fields, $options);
248+
$cursor = $this->find($condition, $fields, $options, $execOptions);
240249
$rows = $cursor->toArray();
241250
return empty($rows) ? null : current($rows);
242251
}
@@ -249,33 +258,35 @@ public function findOne($condition = [], $fields = [], $options = [])
249258
* @return array|null the original document, or the modified document when $options['new'] is set.
250259
* @throws Exception on failure.
251260
*/
252-
public function findAndModify($condition, $update, $options = [])
261+
public function findAndModify($condition, $update, $options = [], $execOptions = [])
253262
{
254-
return $this->database->createCommand()->findAndModify($this->name, $condition, $update, $options);
263+
return $this->database->createCommand()->findAndModify($this->name, $condition, $update, $options, $execOptions);
255264
}
256265

257266
/**
258267
* Inserts new data into collection.
259268
* @param array|object $data data to be inserted.
260269
* @param array $options list of options in format: optionName => optionValue.
261270
* @return \MongoDB\BSON\ObjectID new record ID instance.
271+
* @param array $execOptions -> goto Command::executeBatch()
262272
* @throws Exception on failure.
263273
*/
264-
public function insert($data, $options = [])
274+
public function insert($data, $options = [], $execOptions = [])
265275
{
266-
return $this->database->createCommand()->insert($this->name, $data, $options);
276+
return $this->database->createCommand()->insert($this->name, $data, $options, $execOptions);
267277
}
268278

269279
/**
270280
* Inserts several new rows into collection.
271281
* @param array $rows array of arrays or objects to be inserted.
272282
* @param array $options list of options in format: optionName => optionValue.
283+
* @param array $execOptions -> goto Command::executeBatch()
273284
* @return array inserted data, each row will have "_id" key assigned to it.
274285
* @throws Exception on failure.
275286
*/
276-
public function batchInsert($rows, $options = [])
287+
public function batchInsert($rows, $options = [], $execOptions = [])
277288
{
278-
$insertedIds = $this->database->createCommand()->batchInsert($this->name, $rows, $options);
289+
$insertedIds = $this->database->createCommand()->batchInsert($this->name, $rows, $options, $execOptions);
279290
foreach ($rows as $key => $row) {
280291
$rows[$key]['_id'] = $insertedIds[$key];
281292
}
@@ -289,12 +300,13 @@ public function batchInsert($rows, $options = [])
289300
* @param array $condition description of the objects to update.
290301
* @param array $newData the object with which to update the matching records.
291302
* @param array $options list of options in format: optionName => optionValue.
303+
* @param array $execOptions -> goto Command::executeBatch()
292304
* @return int|bool number of updated documents or whether operation was successful.
293305
* @throws Exception on failure.
294306
*/
295-
public function update($condition, $newData, $options = [])
307+
public function update($condition, $newData, $options = [], $execOptions = [])
296308
{
297-
$writeResult = $this->database->createCommand()->update($this->name, $condition, $newData, $options);
309+
$writeResult = $this->database->createCommand()->update($this->name, $condition, $newData, $options, $execOptions);
298310
return $writeResult->getModifiedCount() + $writeResult->getUpsertedCount();
299311
}
300312

@@ -303,16 +315,17 @@ public function update($condition, $newData, $options = [])
303315
* @param array|object $data data to be updated/inserted.
304316
* @param array $options list of options in format: optionName => optionValue.
305317
* @return \MongoDB\BSON\ObjectID updated/new record id instance.
318+
* @param array $execOptions -> goto Command::executeBatch()
306319
* @throws Exception on failure.
307320
*/
308-
public function save($data, $options = [])
321+
public function save($data, $options = [], $execOptions = [])
309322
{
310323
if (empty($data['_id'])) {
311-
return $this->insert($data, $options);
324+
return $this->insert($data, $options, $execOptions);
312325
}
313326
$id = $data['_id'];
314327
unset($data['_id']);
315-
$this->update(['_id' => $id], ['$set' => $data], ['upsert' => true]);
328+
$this->update(['_id' => $id], ['$set' => $data], ['upsert' => true], $execOptions);
316329

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

@@ -338,9 +352,9 @@ public function remove($condition = [], $options = [])
338352
* @return int records count.
339353
* @since 2.1
340354
*/
341-
public function count($condition = [], $options = [])
355+
public function count($condition = [], $options = [], $execOptions = [])
342356
{
343-
return $this->database->createCommand()->count($this->name, $condition, $options);
357+
return $this->database->createCommand()->count($this->name, $condition, $options, $execOptions);
344358
}
345359

346360
/**
@@ -351,9 +365,9 @@ public function count($condition = [], $options = [])
351365
* @return array|bool array of distinct values, or "false" on failure.
352366
* @throws Exception on failure.
353367
*/
354-
public function distinct($column, $condition = [], $options = [])
368+
public function distinct($column, $condition = [], $options = [], $execOptions = [])
355369
{
356-
return $this->database->createCommand()->distinct($this->name, $column, $condition, $options);
370+
return $this->database->createCommand()->distinct($this->name, $column, $condition, $options, $execOptions);
357371
}
358372

359373
/**
@@ -365,9 +379,9 @@ public function distinct($column, $condition = [], $options = [])
365379
* @return array|\MongoDB\Driver\Cursor the result of the aggregation.
366380
* @throws Exception on failure.
367381
*/
368-
public function aggregate($pipelines, $options = [])
382+
public function aggregate($pipelines, $options = [], $execOptions = [])
369383
{
370-
return $this->database->createCommand()->aggregate($this->name, $pipelines, $options);
384+
return $this->database->createCommand()->aggregate($this->name, $pipelines, $options, $execOptions);
371385
}
372386

373387
/**
@@ -385,9 +399,9 @@ public function aggregate($pipelines, $options = [])
385399
* @return array the result of the aggregation.
386400
* @throws Exception on failure.
387401
*/
388-
public function group($keys, $initial, $reduce, $options = [])
402+
public function group($keys, $initial, $reduce, $options = [], $execOptions = [])
389403
{
390-
return $this->database->createCommand()->group($this->name, $keys, $initial, $reduce, $options);
404+
return $this->database->createCommand()->group($this->name, $keys, $initial, $reduce, $options, $execOptions);
391405
}
392406

393407
/**
@@ -429,8 +443,8 @@ public function group($keys, $initial, $reduce, $options = [])
429443
* @return string|array the map reduce output collection name or output results.
430444
* @throws Exception on failure.
431445
*/
432-
public function mapReduce($map, $reduce, $out, $condition = [], $options = [])
446+
public function mapReduce($map, $reduce, $out, $condition = [], $options = [], $execOptions = [])
433447
{
434-
return $this->database->createCommand()->mapReduce($this->name, $map, $reduce, $out, $condition, $options);
448+
return $this->database->createCommand()->mapReduce($this->name, $map, $reduce, $out, $condition, $options, $execOptions);
435449
}
436450
}

0 commit comments

Comments
 (0)