依托illuminate组件实现数据库迁移

2020-02-16 14:21:31 浏览数 (1)

前言

因为一些原因,我准备选用yaf框架作为我们的主力开发框架,但是我还想要将Laravel的数据库迁移功能给挪过来。所以就研究了一天相关功能。终于让我实现了。

文件简介

首先看一下项目目录:

代码语言:javascript复制
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文件的内容:

代码语言:javascript复制
{
    "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

代码语言:javascript复制
<?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

代码语言:javascript复制
<?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
);
}

执行操作

执行迁移命令:

代码语言:javascript复制
$ php bin/migrate.php up
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.11 seconds)

迁移回滚:

代码语言:javascript复制
$ 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)

创建表:

代码语言:javascript复制
$ php bin/migrate.php create create_demo_table

 [OK] Created Migration: 2019_11_06_220957_create_demo_table

查看一下目录:

代码语言:javascript复制
$ 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

查看以下里面的内容:

代码语言:javascript复制
<?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的所有都注入到容器中的想法表示敬佩。

同时对于提取了这一套迁移方法表示可以同样用在基础框架中,非常实用。

0 人点赞