Database.php 5.69 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
 * @author Paul Klimov <klimov.paul@gmail.com>
 * @since 2.0
 */
class Database extends Object
{
25 26 27 28 29 30 31 32 33 34 35 36
    /**
     * @var \MongoDB Mongo database instance.
     */
    public $mongoDb;
    /**
     * @var Collection[] list of collections.
     */
    private $_collections = [];
    /**
     * @var file\Collection[] list of GridFS collections.
     */
    private $_fileCollections = [];
37

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

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

58 59
        return $this->_collections[$name];
    }
60

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

73 74
        return $this->_fileCollections[$prefix];
    }
75

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

89 90
    /**
     * Selects GridFS collection with given prefix.
91
     * @param string $prefix file collection prefix.
92 93 94 95 96 97 98 99 100
     * @return file\Collection file collection instance.
     */
    protected function selectFileCollection($prefix)
    {
        return Yii::createObject([
            'class' => 'yii\mongodb\file\Collection',
            'mongoCollection' => $this->mongoDb->getGridFS($prefix)
        ]);
    }
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.
107 108
     * @param string $name name of the collection
     * @param array $options collection options in format: "name" => "value"
109
     * @return \MongoCollection new Mongo collection instance.
110
     * @throws Exception on failure.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
     */
    public function createCollection($name, $options = [])
    {
        $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);
        }
    }

    /**
     * Executes Mongo command.
130 131 132
     * @param array $command command specification.
     * @param array $options options in format: "name" => "value"
     * @return array database response.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
     * @throws Exception on failure.
     */
    public function executeCommand($command, $options = [])
    {
        $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.
154
     * @param mixed $result raw command execution result.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
     * @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');
        }
    }
AlexGx committed
177
}