'Codeigniter 4 - How to run one specific migration file?

I have a project with multiple migration files, according to different modules of the project. I want to pass a key (associative array) and run all the files on that index.

//EXAMPLE

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

runAll($files['sales'])

I've read the docs but it just allow specified class name in terminal.

Edit: Just checked again and it either allow class name but namespace on migrate command.



Solution 1:[1]

For those coming here wondering how to run one specific migration file in Codeigniter 4:

Unfortunately, at the time of writing this post, I couldn't find a direct command/way to handle this task.

Luckily, you can have access to the methods available within the MigrationRunner class in your own source code.

Usage Example Here

Even better, you have the ability to create your own custom commands.

With that in mind, I created a custom command to support running a single migration file.

Custom Command

Step 1:
Generate the basic command file by running the command below in your terminal:

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

This will create/generate a command file in the path: APPPATH\Commands\MigrateFileCommand.php

Step 2:
Edit this new command file (app/Commands/MigrateFileCommand.php) to something similar to the source code below:

<?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\Migrations\2022-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
        }
    }
}

The source code above is essentially making use of the force(...) method to execute a single migration file.

Step 3:
Now moving forward, you can easily run a single migration file using the command below in your terminal.

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

Sample Output:

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.

If in case your migration file resides in a different namespace other than App, for example in a different module ('Modules\Sales'), you can pass an option defining the specific namespace. The command also supports passing a different database group other than 'default'. I.e:

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

You can view the documentation of the new command by running the command below:

php spark help migrate:file

Sample Output:

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\Migrations\2022-02-16-101819_AddBlogMigration.php"

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

Bonus Tip

If for some reason you wish to run the new command from within your own code or Controller, this is possible by using:

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

Solution 2:[2]

let's do it like me, see codes step by step

this my codes modules

in 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 = [];
}



this is my migration path file =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);
    }
}


to call it


 php spark migrate  setting -n 'Module\Common'

for more info go there

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 steven7mwesigwa
Solution 2 paliz