Paul Klimov
10 years ago
4 changed files with 404 additions and 0 deletions
@ -0,0 +1,219 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\mongodb; |
||||
|
||||
use yii\base\Component; |
||||
use yii\db\MigrationInterface; |
||||
use yii\di\Instance; |
||||
use yii\helpers\Json; |
||||
|
||||
/** |
||||
* Migration is the base class for representing a MongoDB migration. |
||||
* |
||||
* Each child class of Migration represents an individual MongoDB migration which |
||||
* is identified by the child class name. |
||||
* |
||||
* Within each migration, the [[up()]] method should be overridden to contain the logic |
||||
* for "upgrading" the database; while the [[down()]] method for the "downgrading" |
||||
* logic. |
||||
* |
||||
* Migration provides a set of convenient methods for manipulating MongoDB data and schema. |
||||
* For example, the [[createIndex()]] method can be used to create a collection index. |
||||
* Compared with the same methods in [[Collection]], these methods will display extra |
||||
* information showing the method parameters and execution time, which may be useful when |
||||
* applying migrations. |
||||
* |
||||
* @author Klimov Paul <klimov@zfort.com> |
||||
* @since 2.0 |
||||
*/ |
||||
abstract class Migration extends Component implements MigrationInterface |
||||
{ |
||||
/** |
||||
* @var Connection|string the MongoDB connection object or the application component ID of the MongoDB connection |
||||
* that this migration should work with. |
||||
*/ |
||||
public $db = 'mongodb'; |
||||
|
||||
/** |
||||
* Initializes the migration. |
||||
* This method will set [[db]] to be the 'db' application component, if it is null. |
||||
*/ |
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
$this->db = Instance::ensure($this->db, Connection::className()); |
||||
} |
||||
|
||||
/** |
||||
* Creates new collection with the specified options. |
||||
* @param string|array $collection name of the collection |
||||
* @param array $options collection options in format: "name" => "value" |
||||
*/ |
||||
public function createCollection($collection, $options = []) |
||||
{ |
||||
if (is_array($collection)) { |
||||
list($database, $collectionName) = $collection; |
||||
} else { |
||||
$database = null; |
||||
$collectionName = $collection; |
||||
} |
||||
echo " > create collection " . $this->composeCollectionLogName($collection) . " ..."; |
||||
$time = microtime(true); |
||||
$this->db->getDatabase($database)->createCollection($collectionName, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Drops existing collection. |
||||
* @param string|array $collection name of the collection |
||||
*/ |
||||
public function dropCollection($collection) |
||||
{ |
||||
echo " > drop collection " . $this->composeCollectionLogName($collection) . " ..."; |
||||
$time = microtime(true); |
||||
$this->db->getCollection($collection)->drop(); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Creates an index on the collection and the specified fields. |
||||
* @param string|array $collection name of the collection |
||||
* @param array|string $columns column name or list of column names. |
||||
* @param array $options list of options in format: optionName => optionValue. |
||||
*/ |
||||
public function createIndex($collection, $columns, $options = []) |
||||
{ |
||||
echo " > create index on " . $this->composeCollectionLogName($collection) . " (" . Json::encode((array)$columns) . empty($options) ? "" : ", " . Json::encode($options) . ") ..."; |
||||
$time = microtime(true); |
||||
$this->db->getCollection($collection)->createIndex($columns, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Drop indexes for specified column(s). |
||||
* @param string|array $collection name of the collection |
||||
* @param string|array $columns column name or list of column names. |
||||
*/ |
||||
public function dropIndex($collection, $columns) |
||||
{ |
||||
echo " > drop index on " . $this->composeCollectionLogName($collection) . " (" . Json::encode((array)$columns) . ") ..."; |
||||
$time = microtime(true); |
||||
$this->db->getCollection($collection)->dropIndex($columns); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Drops all indexes for specified collection. |
||||
* @param string|array $collection name of the collection. |
||||
*/ |
||||
public function dropAllIndexes($collection) |
||||
{ |
||||
echo " > drop all indexes on " . $this->composeCollectionLogName($collection) . ") ..."; |
||||
$time = microtime(true); |
||||
$this->db->getCollection($collection)->dropAllIndexes(); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
} |
||||
|
||||
/** |
||||
* Inserts new data into collection. |
||||
* @param array|string $collection collection name. |
||||
* @param array|object $data data to be inserted. |
||||
* @param array $options list of options in format: optionName => optionValue. |
||||
* @return \MongoId new record id instance. |
||||
*/ |
||||
public function insert($collection, $data, $options = []) |
||||
{ |
||||
echo " > insert into " . $this->composeCollectionLogName($collection) . ") ..."; |
||||
$time = microtime(true); |
||||
$id = $this->db->getCollection($collection)->insert($data, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
return $id; |
||||
} |
||||
|
||||
/** |
||||
* Inserts several new rows into collection. |
||||
* @param array|string $collection collection name. |
||||
* @param array $rows array of arrays or objects to be inserted. |
||||
* @param array $options list of options in format: optionName => optionValue. |
||||
* @return array inserted data, each row will have "_id" key assigned to it. |
||||
*/ |
||||
public function batchInsert($collection, $rows, $options = []) |
||||
{ |
||||
echo " > insert into " . $this->composeCollectionLogName($collection) . ") ..."; |
||||
$time = microtime(true); |
||||
$rows = $this->db->getCollection($collection)->batchInsert($rows, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
return $rows; |
||||
} |
||||
|
||||
/** |
||||
* Updates the rows, which matches given criteria by given data. |
||||
* Note: for "multiple" mode Mongo requires explicit strategy "$set" or "$inc" |
||||
* to be specified for the "newData". If no strategy is passed "$set" will be used. |
||||
* @param array|string $collection collection name. |
||||
* @param array $condition description of the objects to update. |
||||
* @param array $newData the object with which to update the matching records. |
||||
* @param array $options list of options in format: optionName => optionValue. |
||||
* @return integer|boolean number of updated documents or whether operation was successful. |
||||
*/ |
||||
public function update($collection, $condition, $newData, $options = []) |
||||
{ |
||||
echo " > update " . $this->composeCollectionLogName($collection) . ") ..."; |
||||
$time = microtime(true); |
||||
$result = $this->db->getCollection($collection)->update($condition, $newData, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Update the existing database data, otherwise insert this data |
||||
* @param array|string $collection collection name. |
||||
* @param array|object $data data to be updated/inserted. |
||||
* @param array $options list of options in format: optionName => optionValue. |
||||
* @return \MongoId updated/new record id instance. |
||||
*/ |
||||
public function save($collection, $data, $options = []) |
||||
{ |
||||
echo " > save " . $this->composeCollectionLogName($collection) . ") ..."; |
||||
$time = microtime(true); |
||||
$id = $this->db->getCollection($collection)->save($data, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
return $id; |
||||
} |
||||
|
||||
/** |
||||
* Removes data from the collection. |
||||
* @param array|string $collection collection name. |
||||
* @param array $condition description of records to remove. |
||||
* @param array $options list of options in format: optionName => optionValue. |
||||
* @return integer|boolean number of updated documents or whether operation was successful. |
||||
*/ |
||||
public function remove($collection, $condition = [], $options = []) |
||||
{ |
||||
echo " > remove " . $this->composeCollectionLogName($collection) . ") ..."; |
||||
$time = microtime(true); |
||||
$result = $this->db->getCollection($collection)->remove($condition, $options); |
||||
echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Composes string representing collection name. |
||||
* @param array|string $collection collection name. |
||||
* @return string collection name. |
||||
*/ |
||||
protected function composeCollectionLogName($collection) |
||||
{ |
||||
if (is_array($collection)) { |
||||
list($database, $collection) = $collection; |
||||
return $database . '.' . $collection; |
||||
} else { |
||||
return $collection; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,160 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\mongodb\console\controllers; |
||||
|
||||
use Yii; |
||||
use yii\console\controllers\BaseMigrateController; |
||||
use yii\console\Exception; |
||||
use yii\mongodb\Connection; |
||||
use yii\mongodb\Query; |
||||
use yii\helpers\ArrayHelper; |
||||
|
||||
/** |
||||
* Manages application MongoDB migrations. |
||||
* |
||||
* This is an analog of [[\yii\console\controllers|MigrateController]] for MongoDB. |
||||
* |
||||
* This command provides support for tracking the migration history, upgrading |
||||
* or downloading with migrations, and creating new migration skeletons. |
||||
* |
||||
* The migration history is stored in a MongoDB collection named |
||||
* as [[migrationCollection]]. This collection will be automatically created the first time |
||||
* this command is executed, if it does not exist. |
||||
* |
||||
* In order to enable this command you should adjust the configuration of your console application: |
||||
* |
||||
* ~~~ |
||||
* return [ |
||||
* // ... |
||||
* 'controllerMap' => [ |
||||
* 'mongodb-migrate' => 'yii\mongodb\console\controllers\MigrateController' |
||||
* ], |
||||
* ]; |
||||
* ~~~ |
||||
* |
||||
* Below are some common usages of this command: |
||||
* |
||||
* ~~~ |
||||
* # creates a new migration named 'create_user_table' |
||||
* yii mongodb-migrate/create create_user_table |
||||
* |
||||
* # applies ALL new migrations |
||||
* yii mongodb-migrate |
||||
* |
||||
* # reverts the last applied migration |
||||
* yii mongodb-migrate/down |
||||
* ~~~ |
||||
* |
||||
* @author Klimov Paul <klimov@zfort.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class MigrateController extends BaseMigrateController |
||||
{ |
||||
/** |
||||
* @var string|array the name of the collection for keeping applied migration information. |
||||
*/ |
||||
public $migrationCollection = 'migration'; |
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public $templateFile = '@yii/mongodb/views/migration.php'; |
||||
/** |
||||
* @var Connection|string the DB connection object or the application |
||||
* component ID of the DB connection. |
||||
*/ |
||||
public $db = 'mongodb'; |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function options($actionId) |
||||
{ |
||||
return array_merge( |
||||
parent::options($actionId), |
||||
['migrationCollection', 'db'] // global for all actions |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* This method is invoked right before an action is to be executed (after all possible filters.) |
||||
* It checks the existence of the [[migrationPath]]. |
||||
* @param \yii\base\Action $action the action to be executed. |
||||
* @throws Exception if db component isn't configured |
||||
* @return boolean whether the action should continue to be executed. |
||||
*/ |
||||
public function beforeAction($action) |
||||
{ |
||||
if (parent::beforeAction($action)) { |
||||
if ($action->id !== 'create') { |
||||
if (is_string($this->db)) { |
||||
$this->db = Yii::$app->get($this->db); |
||||
} |
||||
if (!$this->db instanceof Connection) { |
||||
throw new Exception("The 'db' option must refer to the application component ID of a MongoDB connection."); |
||||
} |
||||
} |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Creates a new migration instance. |
||||
* @param string $class the migration class name |
||||
* @return \yii\mongodb\Migration the migration instance |
||||
*/ |
||||
protected function createMigration($class) |
||||
{ |
||||
$file = $this->migrationPath . DIRECTORY_SEPARATOR . $class . '.php'; |
||||
require_once($file); |
||||
|
||||
return new $class(['db' => $this->db]); |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
protected function getMigrationHistory($limit) |
||||
{ |
||||
$query = new Query; |
||||
$rows = $query->select(['version', 'apply_time']) |
||||
->from($this->migrationCollection) |
||||
->orderBy('version DESC') |
||||
->limit($limit) |
||||
->all($this->db); |
||||
$history = ArrayHelper::map($rows, 'version', 'apply_time'); |
||||
if (empty($history)) { |
||||
$this->addMigrationHistory(self::BASE_MIGRATION); |
||||
} |
||||
unset($history[self::BASE_MIGRATION]); |
||||
|
||||
return $history; |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
protected function addMigrationHistory($version) |
||||
{ |
||||
$this->db->getCollection($this->migrationCollection)->insert([ |
||||
'version' => $version, |
||||
'apply_time' => time(), |
||||
]); |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
protected function removeMigrationHistory($version) |
||||
{ |
||||
$this->db->getCollection($this->migrationCollection)->remove([ |
||||
'version' => $version, |
||||
]); |
||||
} |
||||
} |
@ -0,0 +1,24 @@
|
||||
<?php |
||||
/** |
||||
* This view is used by console/controllers/MigrateController.php |
||||
* The following variables are available in this view: |
||||
* |
||||
* @var string $className the new migration class name |
||||
*/ |
||||
echo "<?php\n";
|
||||
?> |
||||
|
||||
class <?= $className ?> extends \yii\mongodb\Migration
|
||||
{ |
||||
public function up() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function down() |
||||
{ |
||||
echo "<?= $className ?> cannot be reverted.\n";
|
||||
|
||||
return false; |
||||
} |
||||
} |
Loading…
Reference in new issue