123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- <?php
- /**
- * author zhepama
- */
- namespace migration\backend\controllers;
- use migration\AppUtility;
- use migration\models\MigrationUtility;
- use Yii;
- use yii\base\BaseObject;
- use yii\helpers\FileHelper;
- use yii\web\Controller;
- class DefaultController extends Controller
- {
- /**
- * @todo 没有添加事务
- *
- * @return string
- */
- public function actionIndex()
- {
- set_time_limit(0);
- $model = new MigrationUtility();
- $upStr = new OutputString();
- $downStr = new OutputString();
- if ($model->load(\Yii::$app->getRequest()
- ->post())) {
- if (! empty($model->tableSchemas)) {
- list ($up, $down) = $this->generalTableSchemas($model->tableSchemas, $model->tableOption);
- $upStr->outputStringArray = array_merge($upStr->outputStringArray, $up->outputStringArray);
- $downStr->outputStringArray = array_merge($downStr->outputStringArray, $down->outputStringArray);
- }
-
- if (! empty($model->tableDatas)) {
- list ($up, $down) = $this->generalTableDatas($model->tableDatas);
- $upStr->outputStringArray = array_merge($upStr->outputStringArray, $up->outputStringArray);
- $downStr->outputStringArray = array_merge($downStr->outputStringArray, $down->outputStringArray);
- }
-
- $path = Yii::getAlias($model->migrationPath);
- if (! is_dir($path)) {
- FileHelper::createDirectory($path);
- }
-
- $name = 'm' . gmdate('ymd_His') . '_' . $model->migrationName;
- $file = $path . DIRECTORY_SEPARATOR . $name . '.php';
-
- $content = $this->renderFile(Yii::getAlias("@backend/modules/migration/views/migration.php"), [
- 'className' => $name,
- 'up' => $upStr->output(),
- 'down' => $downStr->output()
- ]);
- file_put_contents($file, $content);
- Yii::$app->session->setFlash("success", "迁移成功,保存在" . $file);
- }
-
- if ($model->migrationPath == null) {
- $model->migrationPath = $this->module->migrationPath;
- }
-
- return $this->render('index', [
- 'model' => $model
- ]);
- }
- public function getTableName($name)
- {
- $prefix = \Yii::$app->db->tablePrefix;
-
- return str_replace($prefix, '', $name);
- }
- public function generalTableSchemas($tables, $tableOption)
- {
- $initialTabLevel = 0;
- $upStr = new OutputString([
- 'tabLevel' => $initialTabLevel
- ]);
-
- $upStr->addStr('$this->execute(\'SET foreign_key_checks = 0\');');
- $upStr->addStr(' ');
- foreach ($tables as $table) {
- $upStr->tabLevel = $initialTabLevel;
-
- $tablePrepared = $this->getTableName($table);
-
- // 添加表结构
- $upStr->addStr('$this->createTable(\'{{%' . $tablePrepared . '}}\', [');
- $upStr->tabLevel ++;
- $tableSchema = \Yii::$app->db->getTableSchema($table);
-
- foreach ($tableSchema->columns as $column) {
- $appUtility = new AppUtility($column);
- $upStr->addStr($appUtility->string . "',");
- }
- if (! empty($tableSchema->primaryKey)) {
- $upStr->addStr("'PRIMARY KEY (`" . implode("`,`", $tableSchema->primaryKey) . "`)'");
- }
-
- $upStr->tabLevel --;
- $upStr->addStr('], "' . $tableOption . '");');
-
- // 添加索引
- $tableIndexes = Yii::$app->db->createCommand('SHOW INDEX FROM `' . $table . '`')->queryAll();
- $indexs = [];
- foreach ($tableIndexes as $item) {
- if ($item['Key_name'] == 'PRIMARY') {
- continue;
- }
- if (! isset($indexs[$item["Key_name"]])) {
- $indexs[$item["Key_name"]] = [];
- $indexs[$item["Key_name"]]["unique"] = ($item['Non_unique']) ? 0 : 1;
- }
- $indexs[$item["Key_name"]]["columns"][] = $item['Column_name'];
- }
-
- if (! empty($indexs)) {
- $upStr->addStr(' ');
- }
-
- foreach ($indexs as $index => $item) {
- $str = '$this->createIndex(\'' . $index . '\',\'{{%' . $tablePrepared . '}}\',\'' . implode(', ', $item['columns']) . '\',' . $item['unique'] . ');';
- $upStr->addStr($str);
- }
-
- $upStr->addStr(' ');
- }
-
- //添加外键
- $sql = "SELECT tb1.CONSTRAINT_NAME, tb1.TABLE_NAME, tb1.COLUMN_NAME,
- tb1.REFERENCED_TABLE_NAME, tb1.REFERENCED_COLUMN_NAME, tb2.MATCH_OPTION,
-
- tb2.UPDATE_RULE, tb2.DELETE_RULE
-
- FROM information_schema.KEY_COLUMN_USAGE AS tb1
- INNER JOIN information_schema.REFERENTIAL_CONSTRAINTS AS tb2 ON
- tb1.CONSTRAINT_NAME = tb2.CONSTRAINT_NAME AND tb1.CONSTRAINT_SCHEMA = tb2.CONSTRAINT_SCHEMA
- WHERE TABLE_SCHEMA = DATABASE()
- AND REFERENCED_TABLE_SCHEMA = DATABASE() AND REFERENCED_COLUMN_NAME IS NOT NULL";
- $foreignKeys = Yii::$app->db->createCommand($sql)->queryAll();
- foreach ($foreignKeys as $fk)
- {
- $str = '$this->addForeignKey(';
- $str .= '\'' . $fk['CONSTRAINT_NAME'] . '\', ';
- $str .= '\'{{%' . $this->getTableName($fk['TABLE_NAME']) . '}}\', ';
- $str .= '\'' . $fk['COLUMN_NAME'] . '\', ';
- $str .= '\'{{%' . $this->getTableName($fk['REFERENCED_TABLE_NAME']) . '}}\', ';
- $str .= '\'' . $fk['REFERENCED_COLUMN_NAME'] . '\', ';
- $str .= '\'' . $fk['DELETE_RULE'] . '\', ';
- $str .= '\'' . $fk['UPDATE_RULE'] . '\' ';
- $str .= ');';
- $upStr->addStr($str);
- }
-
- $upStr->addStr(' ');
- $upStr->addStr('$this->execute(\'SET foreign_key_checks = 1;\');');
-
- $downStr = new OutputString();
- /* DROP TABLE */
- $downStr->addStr('$this->execute(\'SET foreign_key_checks = 0\');');
- foreach ($tables as $table) {
- if (! empty($table)) {
- $downStr->addStr('$this->dropTable(\'{{%' . $tablePrepared . '}}\');');
- }
- }
- $downStr->addStr('$this->execute(\'SET foreign_key_checks = 1;\');');
-
- return [
- $upStr,
- $downStr
- ];
- }
- public function generalTableDatas($tables)
- {
- $initialTabLevel = 0;
- $upStr = new OutputString([
- 'tabLevel' => $initialTabLevel
- ]);
- $upStr->addStr('$this->execute(\'SET foreign_key_checks = 0\');');
- $upStr->addStr(' ');
- foreach ($tables as $table) {
-
- $tablePrepared = $this->getTableName($table);
-
- $upStr->addStr('/* Table ' . $table . ' */');
- $tableSchema = \Yii::$app->db->getTableSchema($table);
- $data = Yii::$app->db->createCommand('SELECT * FROM `' . $table . '`')->queryAll();
- $out = '$this->batchInsert(\'{{%' . $tablePrepared . '}}\',[';
- foreach ($tableSchema->columns as $column) {
- $out .= "'" . $column->name . "',";
- }
- $out = rtrim($out, ',') . '],[';
- foreach ($data as $row) {
- $out .= '[';
- foreach ($row as $field) {
- if ($field === null) {
- $out .= "null,";
- } else {
- $out .= "'" . addcslashes($field, "'") . "',";
- }
- }
- $out = rtrim($out, ',') . "],\n";
- }
- $out = rtrim($out, ',') . ']);';
- $upStr->addStr($out);
- $upStr->addStr(' ');
- }
- $upStr->addStr('$this->execute(\'SET foreign_key_checks = 1;\');');
- $downStr = new OutputString();
- return [
- $upStr,
- $downStr
- ];
- }
- }
- /**
- * Class OutputString
- *
- * @author Nils Lindentals <nils@dfworks.lv>
- *
- * @package c006\utility\migration\controllers
- */
- class OutputString extends BaseObject
- {
- /**
- *
- * @var string
- */
- public $nw = "\n";
- /**
- *
- * @var string
- */
- public $tab = "\t";
- /**
- *
- * @var string
- */
- public $outputStringArray = array();
- /**
- *
- * @var int
- */
- public $tabLevel = 0;
- /**
- * Adds string to output string array with "tab" prefix
- *
- * @var string $str
- */
- public function addStr($str)
- {
- $str = str_replace($this->tab, '', $str);
- $this->outputStringArray[] = str_repeat($this->tab, $this->tabLevel) . $str;
- }
- /**
- * Returns string output
- */
- public function output()
- {
- return implode($this->nw, $this->outputStringArray);
- }
- }
|