Database.php 4.98 KB
Newer Older
1 2 3 4 5 6 7
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

8
namespace yii\mongodb;
9 10 11

use yii\base\Object;
use Yii;
12
use yii\helpers\Json;
13 14 15 16

/**
 * Database represents the Mongo database information.
 *
Qiang Xue committed
17 18
 * @property file\Collection $fileCollection Mongo GridFS collection. This property is read-only.
 * @property string $name Name of this database. This property is read-only.
19
 *
20 21 22 23 24 25 26 27 28 29 30 31 32
 * @author Paul Klimov <klimov.paul@gmail.com>
 * @since 2.0
 */
class Database extends Object
{
	/**
	 * @var \MongoDB Mongo database instance.
	 */
	public $mongoDb;
	/**
	 * @var Collection[] list of collections.
	 */
	private $_collections = [];
33 34 35 36
	/**
	 * @var file\Collection[] list of GridFS collections.
	 */
	private $_fileCollections = [];
37

38 39 40 41 42 43 44 45
	/**
	 * @return string name of this database.
	 */
	public function getName()
	{
		return $this->mongoDb->__toString();
	}

46 47 48
	/**
	 * Returns the Mongo collection with the given name.
	 * @param string $name collection name
49
	 * @param boolean $refresh whether to reload the collection instance even if it is found in the cache.
50
	 * @return Collection Mongo collection instance.
51 52 53 54 55 56 57 58 59
	 */
	public function getCollection($name, $refresh = false)
	{
		if ($refresh || !array_key_exists($name, $this->_collections)) {
			$this->_collections[$name] = $this->selectCollection($name);
		}
		return $this->_collections[$name];
	}

60 61 62
	/**
	 * Returns Mongo GridFS collection with given prefix.
	 * @param string $prefix collection prefix.
63
	 * @param boolean $refresh whether to reload the collection instance even if it is found in the cache.
64
	 * @return file\Collection Mongo GridFS collection.
65 66 67 68 69 70 71 72 73
	 */
	public function getFileCollection($prefix = 'fs', $refresh = false)
	{
		if ($refresh || !array_key_exists($prefix, $this->_fileCollections)) {
			$this->_fileCollections[$prefix] = $this->selectFileCollection($prefix);
		}
		return $this->_fileCollections[$prefix];
	}

74 75 76 77 78 79 80 81
	/**
	 * Selects collection with given name.
	 * @param string $name collection name.
	 * @return Collection collection instance.
	 */
	protected function selectCollection($name)
	{
		return Yii::createObject([
82
			'class' => 'yii\mongodb\Collection',
83 84 85 86
			'mongoCollection' => $this->mongoDb->selectCollection($name)
		]);
	}

87 88 89 90 91 92 93 94
	/**
	 * Selects GridFS collection with given prefix.
	 * @param string $prefix file collection prefix.
	 * @return file\Collection file collection instance.
	 */
	protected function selectFileCollection($prefix)
	{
		return Yii::createObject([
95
			'class' => 'yii\mongodb\file\Collection',
96 97 98 99
			'mongoCollection' => $this->mongoDb->getGridFS($prefix)
		]);
	}

100 101 102 103 104 105 106
	/**
	 * Creates new collection.
	 * Note: Mongo creates new collections automatically on the first demand,
	 * this method makes sense only for the migration script or for the case
	 * you need to create collection with the specific options.
	 * @param string $name name of the collection
	 * @param array $options collection options in format: "name" => "value"
107
	 * @return \MongoCollection new Mongo collection instance.
108
	 * @throws Exception on failure.
109 110 111
	 */
	public function createCollection($name, $options = [])
	{
112 113 114 115 116 117 118 119 120 121 122
		$token = $this->getName() . '.create(' . $name . ', ' . Json::encode($options) . ')';
		Yii::info($token, __METHOD__);
		try {
			Yii::beginProfile($token, __METHOD__);
			$result = $this->mongoDb->createCollection($name, $options);
			Yii::endProfile($token, __METHOD__);
			return $result;
		} catch (\Exception $e) {
			Yii::endProfile($token, __METHOD__);
			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
		}
123
	}
124 125 126 127 128 129

	/**
	 * Executes Mongo command.
	 * @param array $command command specification.
	 * @param array $options options in format: "name" => "value"
	 * @return array database response.
130
	 * @throws Exception on failure.
131
	 */
132
	public function executeCommand($command, $options = [])
133
	{
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
		$token = $this->getName() . '.$cmd(' . Json::encode($command) . ', ' . Json::encode($options) . ')';
		Yii::info($token, __METHOD__);
		try {
			Yii::beginProfile($token, __METHOD__);
			$result = $this->mongoDb->command($command, $options);
			$this->tryResultError($result);
			Yii::endProfile($token, __METHOD__);
			return $result;
		} catch (\Exception $e) {
			Yii::endProfile($token, __METHOD__);
			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
		}
	}

	/**
	 * Checks if command execution result ended with an error.
	 * @param mixed $result raw command execution result.
	 * @throws Exception if an error occurred.
	 */
	protected function tryResultError($result)
	{
		if (is_array($result)) {
			if (!empty($result['errmsg'])) {
				$errorMessage = $result['errmsg'];
			} elseif (!empty($result['err'])) {
				$errorMessage = $result['err'];
			}
			if (isset($errorMessage)) {
				if (array_key_exists('ok', $result)) {
					$errorCode = (int)$result['ok'];
				} else {
					$errorCode = 0;
				}
				throw new Exception($errorMessage, $errorCode);
			}
		} elseif (!$result) {
			throw new Exception('Unknown error, use "w=1" option to enable error tracking');
		}
172
	}
173
}