Skip to content

Commit ea6dc4a

Browse files
committed
Merge branch 'transaction'
2 parents 94d99c3 + 80f5ae1 commit ea6dc4a

File tree

8 files changed

+579
-195
lines changed

8 files changed

+579
-195
lines changed

src/ClientSession.php

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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+
use MongoDB\Driver\ReadConcern;
12+
use MongoDB\Driver\WriteConcern;
13+
use MongoDB\Driver\ReadPreference;
14+
15+
/**
16+
* ClientSession represents a client session and Commands, queries, and write operations may then be associated the session.
17+
* @see https://docs.mongodb.com/manual/release-notes/3.6/#client-sessions
18+
* Note : At least 1.4.0 mongodb php driver version is supported.
19+
* Note : At least 3.6 MongoDB version is supported.
20+
* @see https://github.com/mongodb/mongo-php-driver/releases/tag/1.4.0
21+
* @see https://docs.mongodb.com/ecosystem/drivers/php/#mongodb-compatibility
22+
* @author Abolfazl Ziaratban <[email protected]>
23+
*/
24+
class ClientSession extends \yii\base\BaseObject
25+
{
26+
27+
/**
28+
* @var Connection the database connection that this transaction is associated with.
29+
*/
30+
public $db;
31+
32+
/**
33+
* @var MongoDB\Driver\Session class represents a client session and Commands,
34+
* queries, and write operations may then be associated the session.
35+
* @see https://www.php.net/manual/en/class.mongodb-driver-session.php
36+
*/
37+
public $mongoSession;
38+
39+
/**
40+
* @var Transaction current transaction in session. this transaction can only be created once.
41+
*/
42+
private $_transaction = null;
43+
44+
/**
45+
* preapare options for some purpose
46+
* @param array by reference
47+
* convert string option to object
48+
* [
49+
* 'defaultTransactionOptions' => [
50+
* 'readConcern' => 'snapshot',
51+
* 'writeConcern' => 'majority',
52+
* 'writeConcern' => ['majority',true],
53+
* 'readPreference' => 'primary',
54+
* ],
55+
* ]
56+
* convert to :
57+
* [
58+
* 'defaultTransactionOptions' => [
59+
* 'readConcern' => new \MongoDB\Driver\ReadConcern('snapshot'),
60+
* 'writeConcern' => new \MongoDB\Driver\WriteConcern('majority'),
61+
* 'writeConcern' => new \MongoDB\Driver\WriteConcern('majority',true),
62+
* 'readPreference' => new \MongoDB\Driver\ReadPreference('primary'),
63+
* ],
64+
* ]
65+
*/
66+
public static function prepareOptions(&$options){
67+
68+
if(array_key_exists('defaultTransactionOptions',$options)){
69+
70+
#convert readConcern
71+
if(
72+
array_key_exists('readConcern',$options['defaultTransactionOptions']) &&
73+
is_string($options['defaultTransactionOptions']['readConcern'])
74+
)
75+
$options['defaultTransactionOptions']['readConcern'] = new ReadConcern($options['defaultTransactionOptions']['readConcern']);
76+
77+
#convert writeConcern
78+
if(array_key_exists('writeConcern',$options['defaultTransactionOptions'])){
79+
if(is_string($options['defaultTransactionOptions']['writeConcern']))
80+
$options['defaultTransactionOptions']['writeConcern'] = new WriteConcern($options['defaultTransactionOptions']['writeConcern']);
81+
else if(is_array($options['defaultTransactionOptions']['writeConcern']))
82+
$options['defaultTransactionOptions']['writeConcern'] = (new \ReflectionClass('\MongoDB\Driver\WriteConcern'))->newInstanceArgs($options['defaultTransactionOptions']['writeConcern']);
83+
}
84+
85+
#convert readPreference
86+
if(array_key_exists('readPreference',$options['defaultTransactionOptions'])){
87+
if(is_string($options['defaultTransactionOptions']['readPreference']))
88+
$options['defaultTransactionOptions']['readPreference'] = new ReadPreference($options['defaultTransactionOptions']['readPreference']);
89+
else if(is_array($options['defaultTransactionOptions']['readPreference']))
90+
$options['defaultTransactionOptions']['readPreference'] = (new \ReflectionClass('\MongoDB\Driver\ReadPreference'))->newInstanceArgs($options['defaultTransactionOptions']['readPreference']);
91+
}
92+
}
93+
}
94+
95+
/**
96+
* Returns the logical session ID as string for this session, which may be used to identify this session's operations on the server.
97+
* @see https://www.php.net/manual/en/mongodb-driver-session.getlogicalsessionid.php
98+
* @return string
99+
*/
100+
public function getId(){
101+
return $this->mongoSession->getLogicalSessionId()->id->jsonSerialize()['$binary'];
102+
}
103+
104+
/**
105+
* Start a new session in a connection.
106+
* @param Connection $db
107+
* @param Array $sessionOptions Creates a ClientSession for the given options
108+
* @see https://www.php.net/manual/en/mongodb-driver-manager.startsession.php#refsect1-mongodb-driver-manager.startsession-parameters
109+
* @return ClientSession return new session base on a session options for the given connection
110+
*/
111+
public static function start($db, $sessionOptions = []){
112+
self::prepareOptions($sessionOptions);
113+
Yii::debug('Starting mongodb session ...', __METHOD__);
114+
$db->trigger(Connection::EVENT_START_SESSION);
115+
$newSession = new self([
116+
'db' => $db,
117+
'mongoSession' => $db->manager->startSession($sessionOptions),
118+
]);
119+
Yii::debug('MongoDB session started.', __METHOD__);
120+
return $newSession;
121+
}
122+
123+
/**
124+
* Get current transaction of session or create a new transaction once
125+
* @return Transaction return current transaction
126+
*/
127+
public function getTransaction(){
128+
if($this->_transaction === null)
129+
return $this->_transaction = new Transaction(['clientSession' => $this]);
130+
return $this->_transaction;
131+
}
132+
133+
/**
134+
* current session has a transaction?
135+
* @return bool return true if transaction exists otherwise return false
136+
*/
137+
public function getHasTransaction(){
138+
return !empty($this->_transaction);
139+
}
140+
141+
/**
142+
* Returns whether a multi-document transaction is in progress
143+
* @return bool
144+
*/
145+
public function getInTransaction(){
146+
return $this->mongoSession->isInTransaction();
147+
}
148+
149+
/**
150+
* End current session
151+
*/
152+
public function end(){
153+
$this->mongoSession->endSession();
154+
$db->trigger(Connection::EVENT_END_SESSION);
155+
}
156+
}

0 commit comments

Comments
 (0)