Codeigniter 4 - 如何 运行 一个特定的迁移文件?

Codeigniter 4 - How to run one specific migration file?

我有一个项目有多个迁移文件,根据项目的不同模块。我想传递一个键(关联数组)和 运行 该索引上的所有文件。

//EXAMPLE

$files = [
    'blog' => [
        //array of file names
    ],
    'storage' => [
        //array of file names
    ],
    'sales' => [
        //array of file names
    ],
]

runAll($files['sales'])

我读过 docs 但它只允许在终端中指定 class 名称。

编辑:刚刚再次检查,迁移命令允许 class 名称但命名空间。

您可以使用 method force(string $path, string $namespace, ?string $group = null) available within the MigrationRunner class.

迁移单个文件,而不考虑顺序或批次

force($path, $namespace, $group)

This forces a single file to migrate regardless of order or batches. Method “up” or “down” is detected based on whether it has already been migrated.

Note:

This method is recommended only for testing and could cause data consistency issues.

因此,在您的情况下,当您在 force(...) 方法中传递预期参数时,您只需 运行 一个 for 循环遍历文件。即:

假设你的$files数组的数组键代表项目的各种'modules'

$migrate = \Config\Services::migrations();
$psr4 = config(\Config\Autoload::class)->psr4;

foreach ($files as $module => $filenames) {

    $namespace = "Modules\" . ucwords($module);

    foreach ($filenames as $filename) {
        try {
            $migrate->force($psr4[$namespace] . "\" . $filename, $namespace);
        } catch (\Throwable $e) {
            // Do something with the error here...
        }
    }
}

注意事项:

上述解决方案假定您已经将应用程序模块中的 $psr4 命名空间映射到它们在文件系统上的相应位置:即:

文件:app/Config/Autoload.php

// ...

    public $psr4 = [
        APP_NAMESPACE => APPPATH, // For custom app namespace
        'Config' => APPPATH . 'Config',
        'Modules\Blog' => ROOTPATH . 'module/blog',
        'Modules\Storage' => ROOTPATH . 'module/storage',
        'Modules\Sales' => ROOTPATH . 'module/sales',
    ];

// ...

对于那些想知道如何在 Codeigniter 4 中 运行 一个特定的迁移文件 的人:

不幸的是,在撰写本文时 post,我找不到直接 command/way 来处理此任务。

幸运的是,您可以在自己的源代码中访问 MigrationRunner class 中可用的方法。

Usage Example Here

更好的是,你有能力create your own custom commands

考虑到这一点,我创建了一个自定义命令来支持 运行宁 单个迁移文件

自定义命令

第 1 步:
通过 运行 在您的终端中输入以下命令来生成基本命令文件:

php spark make:command MigrateFile --command migrate:file --group Database --suffix Command

这将create/generate路径中的命令文件:APPPATH\Commands\MigrateFileCommand.php

第 2 步:
将此新命令文件 (app/Commands/MigrateFileCommand.php) 编辑为类似于以下源代码的内容:

<?php

namespace App\Commands;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Services;

class MigrateFileCommand extends BaseCommand
{
    /**
     * The Command's Group
     *
     * @var string
     */
    protected $group = 'Database';

    /**
     * The Command's Name
     *
     * @var string
     */
    protected $name = 'migrate:file';

    /**
     * The Command's Description
     *
     * @var string
     */
    protected $description = 'Migrates a single migration file.';

    /**
     * The Command's Usage
     *
     * @var string
     */
    protected $usage = 'migrate:file [arguments] [options]';

    /**
     * The Command's Arguments
     *
     * @var array
     */
    protected $arguments = [
        'name' => 'The valid migration file path beginning from the ROOTPATH. For example: php spark migrate:file "app\Database\Migrations22-02-16-101819_AddBlogMigration.php"'
    ];

    /**
     * The Command's Options
     *
     * @var array
     */
    protected $options = [
        '--namespace' => 'Set migration namespace. Default: "App".',
        '--dbgroup' => 'Set database group. Default: "default".',
    ];

    /**
     * Actually execute a command.
     *
     * @param array $params
     */
    public function run(array $params)
    {
        CLI::write("Running migration...", 'yellow');

        $message = "";
        $paramsSize = count($params);

        if (!$paramsSize) {
            $message = 'Too few arguments passed. Missing "migration file path."';
        } else if ($paramsSize > 1) {
            $message = 'Too many arguments passed.';
        }

        if ($paramsSize !== 1) {
            CLI::write(sprintf('Invalid Params: %s', $message), 'red');
            CLI::newLine();
            $this->showHelp();
            return;
        }

        $runner = Services::migrations();
        $namespace = ($params['namespace'] ?? CLI::getOption('namespace')) ?: "App";
        $dbgroup = ($params['dbgroup'] ?? CLI::getOption('dbgroup')) ?: "default";

        try {
            if (!$runner->force(ROOTPATH . $params[0], $namespace, $dbgroup)) {
                CLI::error(lang('Migrations.generalFault'), 'light_gray', 'red'); // @codeCoverageIgnore
            }

            $messages = $runner->getCliMessages();

            foreach ($messages as $message) {
                CLI::write($message);
            }

            CLI::write('Done migration.', 'green');

            // @codeCoverageIgnoreStart
        } catch (\Throwable $e) {
            $this->showError($e);
            // @codeCoverageIgnoreEnd
        }
    }
}

上面的源代码本质上是利用force(...) method来执行单个迁移文件。

第 3 步:
现在继续前进,您可以在终端中使用以下命令轻松 运行 单个迁移文件。

 php spark migrate:file "app\Database\Migrations22-02-16-101819_AddBlogMigration.php"

示例输出:

CodeIgniter v4.1.4 Command Line Tool - Server Time: 2022-02-16 13:09:34 UTC+01:00

Running migration...
        Running: (App) 2022-02-16-101819_App\Database\Migrations\AddBlogMigration
Done migration.

如果您的迁移文件驻留在 App 以外的其他命名空间中,例如在不同的模块中 ('Modules\Sales'),您可以传递定义特定命名空间的选项。 该命令还支持传递不同于 'default' 的不同数据库组。即:

php spark migrate:file "app\Database\Migrations22-02-16-101819_AddBlogMigration.php" --namespace "Modules\Sales" --dbgroup "tests"

您可以通过运行以下命令查看新命令的文档:

php spark help migrate:file

示例输出:

CodeIgniter v4.1.4 Command Line Tool - Server Time: 2022-02-16 15:16:31 UTC+01:00

Usage:
  migrate:file [arguments] [options]

Description:
  Migrates a single migration file.

Arguments:
  name  The valid migration file path beginning from the ROOTPATH. For example: php spark migrate:file "app\Database\Migrations22-02-16-101819_AddBlogMigration.php"

Options:
  --namespace  Set migration namespace. Default: "App".
  --dbgroup    Set database group. Default: "default".

奖金提示

如果出于某种原因您希望 run the new command from within your own code 或 Controller,可以使用:

echo command('migrate:file "app\Database\Migrations22-02-16-101819_AddBlogMigration.php"');

让我们像我一样, 逐步查看代码

这是我的代码模块

在 app/config/autoload.php

<?php

namespace Config;

use CodeIgniter\Config\AutoloadConfig;

/**
 * -------------------------------------------------------------------
 * AUTOLOADER CONFIGURATION
 * -------------------------------------------------------------------
 *
 * This file defines the namespaces and class maps so the Autoloader
 * can find the files as needed.
 *
 * NOTE: If you use an identical key in $psr4 or $classmap, then
 * the values in this file will overwrite the framework's values.
 */
class Autoload extends AutoloadConfig
{
    /**
     * -------------------------------------------------------------------
     * Namespaces
     * -------------------------------------------------------------------
     * This maps the locations of any namespaces in your application to
     * their location on the file system. These are used by the autoloader
     * to locate files the first time they have been instantiated.
     *
     * The '/app' and '/system' directories are already mapped for you.
     * you may change the name of the 'App' namespace if you wish,
     * but this should be done prior to creating any namespaced classes,
     * else you will need to modify all of those classes for this to work.
     *
     * Prototype:
     *```
     *   $psr4 = [
     *       'CodeIgniter' => SYSTEMPATH,
     *       'App'         => APPPATH
     *   ];
     *```
     *
     * @var array<string, string>
     */
    public $psr4 = [
        APP_NAMESPACE => APPPATH, // For custom app namespace
        'Config'      => APPPATH . 'Config',
        'Myth\Auth'   => APPPATH .'ThirdParty/myth-auth/src',
        'Modules\Shared' => ROOTPATH . 'module/shared',
        'Modules\Common' => ROOTPATH . 'module/common',
        'Modules\Auth' => ROOTPATH . 'module/auth',
        'Modules\Home' => ROOTPATH . 'module/home',
        'Modules\Payment' => ROOTPATH . 'module/payment',
        'Modules\App' => ROOTPATH . 'module/app',
    ];

    /**
     * -------------------------------------------------------------------
     * Class Map
     * -------------------------------------------------------------------
     * The class map provides a map of class names and their exact
     * location on the drive. Classes loaded in this manner will have
     * slightly faster performance because they will not have to be
     * searched for within one or more directories as they would if they
     * were being autoloaded through a namespace.
     *
     * Prototype:
     *```
     *   $classmap = [
     *       'MyClass'   => '/path/to/class/file.php'
     *   ];
     *```
     *
     * @var array<string, string>
     */
    public $classmap = [];

    /**
     * -------------------------------------------------------------------
     * Files
     * -------------------------------------------------------------------
     * The files array provides a list of paths to __non-class__ files
     * that will be autoloaded. This can be useful for bootstrap operations
     * or for loading functions.
     *
     * Prototype:
     * ```
     *    $files = [
     *         '/path/to/my/file.php',
     *    ];
     * ```
     *
     * @var array<int, string>
     */
    public $files = [];
}



这是我的迁移 路径文件=Modules\Common\Database\Migrations\Settting


<?php namespace Modules\Common\Database\Migrations;

use CodeIgniter\Database\Migration;

class Setting extends Migration
{
    public function up()
    {
        //

        /*
        * Setting
        */
        $this->forge->addField([
            'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
            'key' => ['type' => 'varchar', 'constraint' => 255],
            'value' => ['type' => 'varchar', 'constraint' => 255],
            'description' => ['type' => 'varchar', 'constraint' => 300],
            'status' => ['type' => 'tinyint', 'constraint' => 1, 'null' => 0, 'default' => 1],
            'created_at' => ['type' => 'datetime', 'null' => true],
            'updated_at' => ['type' => 'datetime', 'null' => true],
            'deleted_at' => ['type' => 'datetime', 'null' => true],
        ]);

        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey('key');
        $this->forge->createTable('setting', true);

    }

    //--------------------------------------------------------------------

    public function down()
    {
        // drop constraints first to prevent errors
       

        $this->forge->dropTable('setting', true);
    }
}


调用它


 php spark migrate  setting -n 'Module\Common'

如需更多信息,请前往此处

https://codeigniter.com/user_guide/dbmgmt/migration.html