依託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
的所有都注入到容器中的想法表示敬佩。
同時對於提取了這一套遷移方法表示可以同樣用在基礎框架中,非常實用。