依託illuminate組件實現資料庫遷移

  • 2020 年 2 月 16 日
  • 筆記

前言

因為一些原因,我準備選用yaf框架作為我們的主力開發框架,但是我還想要將Laravel的資料庫遷移功能給挪過來。所以就研究了一天相關功能。終於讓我實現了。

文件簡介

首先看一下項目目錄:

yaf-base/  ├── app  │   ├── Bootstrap.php  │   ├── controllers  │   │   └── Index.php  │   └── Models  │       └── UserBase.php  ├── app.ini  ├── bin  │   └── migrate.php  ├── composer.json  ├── composer.lock  ├── migrations  │   └── 2014_10_12_000000_create_users_table.php  ├── public  │   └── index.php  ├── README.md  └── vendor

這裡是composer.json文件的內容:

{      "require":{          "php":">=7.2",          "illuminate/database":"^6.4",          "illuminate/filesystem":"^6.4",          "illuminate/events":"^6.4",          "illuminate/config":"^6.4",          "illuminate/console":"^6.4"      },      "repositories":{          "packagist":{              "type":"composer",              "url":"https://mirrors.aliyun.com/composer/"          }      }  }

然後下面是migrations/2014_10_12_000000_create_users_table.php

<?php    use IlluminateContainerContainer;  use IlluminateSupportFacadesSchema;  use IlluminateDatabaseSchemaBlueprint;  use IlluminateDatabaseMigrationsMigration;    class CreateUsersTable extends Migration  {      /**       * Run the migrations.       *       * @return void       */      public function up()      {          Schema::create('users', function (Blueprint $table) {              $table->bigIncrements('id');              $table->string('name');              $table->string('email')->unique();              $table->timestamp('email_verified_at')->nullable();              $table->string('password');              $table->rememberToken();              $table->timestamps();          });      }        /**       * Reverse the migrations.       *       * @return void       */      public function down()      {          Schema::dropIfExists('users');      }  }

可以看到這個跟Laravel的遷移文件是一樣的。

第三個文件就是bin/migrate.php

<?php    use IlluminateConfigRepository;  use IlluminateConsoleOutputStyle;  use IlluminateContainerContainer;  use IlluminateDatabaseConnectorsConnectionFactory;  use IlluminateDatabaseConsoleMigrationsTableGuesser;  use IlluminateDatabaseDatabaseManager;  use IlluminateDatabaseMigrationsDatabaseMigrationRepository;  use IlluminateDatabaseMigrationsMigrationCreator;  use IlluminateDatabaseMigrationsMigrator;  use IlluminateDatabaseSchemaBuilder;  use IlluminateEventsDispatcher;  use IlluminateFilesystemFilesystem;  use IlluminateSupportFacadesFacade;  use IlluminateSupportStr;  use SymfonyComponentConsoleInputArgvInput;  use SymfonyComponentConsoleOutputConsoleOutput;    define("ROOT_PATH", realpath(__DIR__ . "/../"));    require ROOT_PATH . "/vendor/autoload.php";    if (!isset($argv[1])) {      $argv[1] = null;  }    $container = new Container();    $config = new Repository();    $config->set("database", [      "default" => "mysql",      "connections" => [          "mysql" => [              'driver' => 'mysql',              'url' => "",              'host' => "127.0.0.1",              'port' => "3306",              'database' => "test",              'username' => "root",              'password' => "baoguoxiao",              'unix_socket' => '',              'charset' => 'utf8mb4',              'collation' => 'utf8mb4_unicode_ci',              'prefix' => '',              'prefix_indexes' => true,              'strict' => true,              'engine' => null,              'options' => [],          ]      ]  ]);    $container->instance("config", $config);    $file = new Filesystem();    $container->singleton("db", function ($container) {      $db = new DatabaseManager($container, new ConnectionFactory($container));      $db->connection("mysql");      return $db;  });    Facade::setFacadeApplication($container);    Container::setInstance($container);    /**   * 執行遷移命令如果出現 SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes 錯誤則開啟此行程式碼即可解決問題   */  //Builder::defaultStringLength(191);    $repository = new DatabaseMigrationRepository($container["db"], "migrations");    $event = new Dispatcher($container);    $migrator = new Migrator($repository, $container["db"], $file, $event);    $output = new OutputStyle(new ArgvInput(), new ConsoleOutput());    if ($argv[1] == "create") {      $creator = new MigrationCreator($file);      $name = Str::snake($argv[2]);        [$table, $create] = TableGuesser::guess($name);        try {          $file_path = $creator->create($name, ROOT_PATH . "/migrations", $table, $create);          $file_path = pathinfo($file_path, PATHINFO_FILENAME);            $output->success("Created Migration: {$file_path}");      } catch (InvalidArgumentException $exception) {          $output->error($exception->getMessage());      }  } elseif ($argv[1] == "up") {      if (!$migrator->repositoryExists()) { // migrate:install          $repository->createRepository();      }        $migrator->setOutput($output)->run(ROOT_PATH . "/migrations", [          "pretend" => false,          "step" => false      ]);  } elseif ($argv[1] == "down") {      if (!$migrator->repositoryExists()) { // migrate:install          $repository->createRepository();      }        $migrator->setOutput($output)->rollback(ROOT_PATH . "/migrations", [          "pretend" => false,          "step" => 0      ]);  }else {      $output->text(<<<EOF  操作方法:  php bin/migrate.php create {xxx} 創建遷移,命名規則為Laravel  php bin/migrate.php up 執行遷移  php bin/migrate.php down 回滾遷移  EOF  );  }

執行操作

執行遷移命令:

$ php bin/migrate.php up  Migrating: 2014_10_12_000000_create_users_table  Migrated:  2014_10_12_000000_create_users_table (0.11 seconds)

遷移回滾:

$ php bin/migrate.php down  Rolling back: 2014_10_12_000000_create_users_table  Rolled back:  2014_10_12_000000_create_users_table (0.03 seconds)

創建表:

$ php bin/migrate.php create create_demo_table     [OK] Created Migration: 2019_11_06_220957_create_demo_table

查看一下目錄:

$ tree -L 2 ./yaf-base/  ./yaf-base/  ├── app  │   ├── Bootstrap.php  │   ├── controllers  │   └── Models  ├── app.ini  ├── bin  │   └── migrate.php  ├── composer.json  ├── composer.lock  ├── migrations  │   ├── 2014_10_12_000000_create_users_table.php  │   └── 2019_11_06_220957_create_demo_table.php  ├── public  │   └── index.php  ├── README.md  └── vendor

可以看到多了一個2019_11_06_220957_create_demo_table.php

查看以下裡面的內容:

<?php    use IlluminateDatabaseMigrationsMigration;  use IlluminateDatabaseSchemaBlueprint;  use IlluminateSupportFacadesSchema;    class CreateDemoTable extends Migration  {      /**       * Run the migrations.       *       * @return void       */      public function up()      {          Schema::create('demo', function (Blueprint $table) {              $table->bigIncrements('id');              $table->timestamps();          });      }        /**       * Reverse the migrations.       *       * @return void       */      public function down()      {          Schema::dropIfExists('demo');      }  }

Laravel絲毫不差。

總結

通過此次的重現,我對於Laravel的容器理解更加深刻了。對於Laravel的所有都注入到容器中的想法表示敬佩。

同時對於提取了這一套遷移方法表示可以同樣用在基礎框架中,非常實用。