MongoClient.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. <?php
  2. /*
  3. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. */
  15. use Alcaeus\MongoDbAdapter\Helper;
  16. use MongoDB\Client;
  17. /**
  18. * A connection between PHP and MongoDB. This class is used to create and manage connections
  19. * See MongoClient::__construct() and the section on connecting for more information about creating connections.
  20. * @link http://www.php.net/manual/en/class.mongoclient.php
  21. */
  22. class MongoClient
  23. {
  24. use Helper\ReadPreference;
  25. use Helper\WriteConcern;
  26. const VERSION = '1.6.12';
  27. const DEFAULT_HOST = "localhost" ;
  28. const DEFAULT_PORT = 27017 ;
  29. const RP_PRIMARY = "primary" ;
  30. const RP_PRIMARY_PREFERRED = "primaryPreferred" ;
  31. const RP_SECONDARY = "secondary" ;
  32. const RP_SECONDARY_PREFERRED = "secondaryPreferred" ;
  33. const RP_NEAREST = "nearest" ;
  34. /**
  35. * @var bool
  36. * @deprecated This will not properly work as the underlying driver connects lazily
  37. */
  38. public $connected = false;
  39. /**
  40. * @var
  41. */
  42. public $status;
  43. /**
  44. * @var string
  45. */
  46. protected $server;
  47. /**
  48. * @var
  49. */
  50. protected $persistent;
  51. /**
  52. * @var Client
  53. */
  54. private $client;
  55. /**
  56. * @var \MongoDB\Driver\Manager
  57. */
  58. private $manager;
  59. /**
  60. * Creates a new database connection object
  61. *
  62. * @link http://php.net/manual/en/mongo.construct.php
  63. * @param string $server The server name.
  64. * @param array $options An array of options for the connection.
  65. * @param array $driverOptions An array of options for the MongoDB driver.
  66. * @throws MongoConnectionException
  67. */
  68. public function __construct($server = 'default', array $options = ['connect' => true], array $driverOptions = [])
  69. {
  70. if ($server === 'default') {
  71. $server = 'mongodb://' . self::DEFAULT_HOST . ':' . self::DEFAULT_PORT;
  72. }
  73. $this->server = $server;
  74. $this->client = new Client($server, $options, $driverOptions);
  75. $info = $this->client->__debugInfo();
  76. $this->manager = $info['manager'];
  77. if (isset($options['connect']) && $options['connect']) {
  78. $this->connect();
  79. }
  80. }
  81. /**
  82. * Closes this database connection
  83. *
  84. * @link http://www.php.net/manual/en/mongoclient.close.php
  85. * @param boolean|string $connection
  86. * @return boolean If the connection was successfully closed.
  87. */
  88. public function close($connection = null)
  89. {
  90. $this->connected = false;
  91. return false;
  92. }
  93. /**
  94. * Connects to a database server
  95. *
  96. * @link http://www.php.net/manual/en/mongoclient.connect.php
  97. *
  98. * @throws MongoConnectionException
  99. * @return boolean If the connection was successful.
  100. */
  101. public function connect()
  102. {
  103. $this->connected = true;
  104. return true;
  105. }
  106. /**
  107. * Drops a database
  108. *
  109. * @link http://www.php.net/manual/en/mongoclient.dropdb.php
  110. * @param mixed $db The database to drop. Can be a MongoDB object or the name of the database.
  111. * @return array The database response.
  112. * @deprecated Use MongoDB::drop() instead.
  113. */
  114. public function dropDB($db)
  115. {
  116. return $this->selectDB($db)->drop();
  117. }
  118. /**
  119. * Gets a database
  120. *
  121. * @link http://php.net/manual/en/mongoclient.get.php
  122. * @param string $dbname The database name.
  123. * @return MongoDB The database name.
  124. */
  125. public function __get($dbname)
  126. {
  127. return $this->selectDB($dbname);
  128. }
  129. /**
  130. * Gets the client for this object
  131. *
  132. * @internal This part is not of the ext-mongo API and should not be used
  133. * @return Client
  134. */
  135. public function getClient()
  136. {
  137. return $this->client;
  138. }
  139. /**
  140. * Get connections
  141. *
  142. * Returns an array of all open connections, and information about each of the servers
  143. *
  144. * @return array
  145. */
  146. static public function getConnections()
  147. {
  148. return [];
  149. }
  150. /**
  151. * Get hosts
  152. *
  153. * This method is only useful with a connection to a replica set. It returns the status of all of the hosts in the
  154. * set. Without a replica set, it will just return an array with one element containing the host that you are
  155. * connected to.
  156. *
  157. * @return array
  158. */
  159. public function getHosts()
  160. {
  161. $this->forceConnect();
  162. $servers = [];
  163. foreach ($this->manager->getServers() as $server) {
  164. $key = sprintf('%s:%d', $server->getHost(), $server->getPort());
  165. $info = $server->getInfo();
  166. switch ($server->getType()) {
  167. case \MongoDB\Driver\Server::TYPE_RS_PRIMARY:
  168. $state = 1;
  169. break;
  170. case \MongoDB\Driver\Server::TYPE_RS_SECONDARY:
  171. $state = 2;
  172. break;
  173. default:
  174. $state = 0;
  175. }
  176. $servers[$key] = [
  177. 'host' => $server->getHost(),
  178. 'port' => $server->getPort(),
  179. 'health' => (int) $info['ok'],
  180. 'state' => $state,
  181. 'ping' => $server->getLatency(),
  182. 'lastPing' => null,
  183. ];
  184. }
  185. return $servers;
  186. }
  187. /**
  188. * Kills a specific cursor on the server
  189. *
  190. * @link http://www.php.net/manual/en/mongoclient.killcursor.php
  191. * @param string $server_hash The server hash that has the cursor.
  192. * @param int|MongoInt64 $id The ID of the cursor to kill.
  193. * @return bool
  194. */
  195. public function killCursor($server_hash , $id)
  196. {
  197. $this->notImplemented();
  198. }
  199. /**
  200. * Lists all of the databases available
  201. *
  202. * @link http://php.net/manual/en/mongoclient.listdbs.php
  203. * @return array Returns an associative array containing three fields. The first field is databases, which in turn contains an array. Each element of the array is an associative array corresponding to a database, giving the database's name, size, and if it's empty. The other two fields are totalSize (in bytes) and ok, which is 1 if this method ran successfully.
  204. */
  205. public function listDBs()
  206. {
  207. $databaseInfoIterator = $this->client->listDatabases();
  208. $databases = [
  209. 'databases' => [],
  210. 'totalSize' => 0,
  211. 'ok' => 1.0,
  212. ];
  213. foreach ($databaseInfoIterator as $databaseInfo) {
  214. $databases['databases'][] = $databaseInfo->getName();
  215. $databases['totalSize'] += $databaseInfo->getSizeOnDisk();
  216. }
  217. return $databases;
  218. }
  219. /**
  220. * Gets a database collection
  221. *
  222. * @link http://www.php.net/manual/en/mongoclient.selectcollection.php
  223. * @param string $db The database name.
  224. * @param string $collection The collection name.
  225. * @return MongoCollection Returns a new collection object.
  226. * @throws Exception Throws Exception if the database or collection name is invalid.
  227. */
  228. public function selectCollection($db, $collection)
  229. {
  230. return new MongoCollection($this->selectDB($db), $collection);
  231. }
  232. /**
  233. * Gets a database
  234. *
  235. * @link http://www.php.net/manual/en/mongo.selectdb.php
  236. * @param string $name The database name.
  237. * @return MongoDB Returns a new db object.
  238. * @throws InvalidArgumentException
  239. */
  240. public function selectDB($name)
  241. {
  242. return new MongoDB($this, $name);
  243. }
  244. /**
  245. * {@inheritdoc}
  246. */
  247. public function setReadPreference($readPreference, $tags = null)
  248. {
  249. return $this->setReadPreferenceFromParameters($readPreference, $tags);
  250. }
  251. /**
  252. * {@inheritdoc}
  253. */
  254. public function setWriteConcern($wstring, $wtimeout = 0)
  255. {
  256. return $this->setWriteConcernFromParameters($wstring, $wtimeout);
  257. }
  258. /**
  259. * Choose a new secondary for slaveOkay reads
  260. *
  261. * @link www.php.net/manual/en/mongo.switchslave.php
  262. * @return string The address of the secondary this connection is using for reads. This may be the same as the previous address as addresses are randomly chosen. It may return only one address if only one secondary (or only the primary) is available.
  263. * @throws MongoException (error code 15) if it is called on a non-replica-set connection. It will also throw MongoExceptions if it cannot find anyone (primary or secondary) to read from (error code 16).
  264. */
  265. public function switchSlave()
  266. {
  267. $this->notImplemented();
  268. }
  269. /**
  270. * String representation of this connection
  271. *
  272. * @link http://www.php.net/manual/en/mongoclient.tostring.php
  273. * @return string Returns hostname and port for this connection.
  274. */
  275. public function __toString()
  276. {
  277. return $this->server;
  278. }
  279. /**
  280. * Forces a connection by executing the ping command
  281. */
  282. private function forceConnect()
  283. {
  284. $command = new \MongoDB\Driver\Command(['ping' => 1]);
  285. $this->manager->executeCommand('db', $command);
  286. }
  287. private function notImplemented()
  288. {
  289. throw new \Exception('Not implemented');
  290. }
  291. }