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 中可用的方法。
更好的是,你有能力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'
如需更多信息,请前往此处
我有一个项目有多个迁移文件,根据项目的不同模块。我想传递一个键(关联数组)和 运行 该索引上的所有文件。
//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 中可用的方法。
更好的是,你有能力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'
如需更多信息,请前往此处