Database.php 5.79 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 48 49 50 51 52 53 54 55 56
    /**
     * Returns the Mongo collection with the given name.
     * @param  string     $name    collection name
     * @param  boolean    $refresh whether to reload the collection instance even if it is found in the cache.
     * @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 63 64 65 66 67 68 69 70 71
    /**
     * Returns Mongo GridFS collection with given prefix.
     * @param  string          $prefix  collection prefix.
     * @param  boolean         $refresh whether to reload the collection instance even if it is found in the cache.
     * @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 78 79 80 81 82 83 84 85 86 87
    /**
     * Selects collection with given name.
     * @param  string     $name collection name.
     * @return Collection collection instance.
     */
    protected function selectCollection($name)
    {
        return Yii::createObject([
            'class' => 'yii\mongodb\Collection',
            'mongoCollection' => $this->mongoDb->selectCollection($name)
        ]);
    }
88

89 90 91 92 93 94 95 96 97 98 99 100
    /**
     * 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([
            'class' => 'yii\mongodb\file\Collection',
            'mongoCollection' => $this->mongoDb->getGridFS($prefix)
        ]);
    }
101

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 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 172 173 174 175 176
    /**
     * 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"
     * @return \MongoCollection new Mongo collection instance.
     * @throws Exception        on failure.
     */
    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.
     * @param  array     $command command specification.
     * @param  array     $options options in format: "name" => "value"
     * @return array     database response.
     * @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.
     * @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');
        }
    }
AlexGx committed
177
}