Create database migrations in Codeigniter 3 easily using a command line interface.
Refinery
is a console-based package of Migrations Class for the Codeigniter 3. It uses the Describe package for retrieving the database tables for creating database migrations.
From an existing Codeigniter 3
project, the Refinery
package can be installed through Composer:
$ composer require rougin/refinery --dev
// ciacme/composer.json
{
// ...
"require-dev":
{
"mikey179/vfsstream": "1.6.*",
"phpunit/phpunit": "4.* || 5.* || 9.*",
"rougin/refinery": "~0.4"
}
}
Then configure the project's database connectivity settings:
// ciacme/application/config/database.php
// ...
$db['default'] = array(
'dsn' => '',
'hostname' => 'localhost',
'username' => '',
'password' => '',
'database' => '',
'dbdriver' => 'mysqli',
// ...
);
[!NOTE] Although using database connection is not required in using
Refinery
, this is only applicable when creating migration files based on an existing database. Please see Creating from database below for its usage.
To create a new database migration, kindly run the create
command:
$ vendor/bin/refinery create create_users_table
[PASS] "20241019044009_create_users_table.php" successfully created!
// ciacme/application/migrations/20241019044009_create_users_table.php
use Rougin\Refinery\Migration;
class Migration_create_users_table extends Migration
{
/**
* @return void
*/
public function up()
{
$data = array('id' => array());
$data['id']['type'] = 'integer';
$data['id']['auto_increment'] = true;
$data['id']['constraint'] = 10;
$this->dbforge->add_field($data);
$this->dbforge->add_key('id', true);
$this->dbforge->create_table('users');
}
/**
* @return void
*/
public function down()
{
$this->dbforge->drop_table('users');
}
}
[!NOTE]
- The
Migration
class underRefinery
is directly extended onCI_Migration
.- The created file will be in
migrations
directory underapplication
. If it does not exists,Refinery
will automatically create the specified directory.
When creating database migrations, Refinery
will try to guess the expected output of up
and down
methods of a migration file based on its name (e.g., add_name_in_users_table
):
$ vendor/bin/refinery create add_name_in_users_table
"20241019044035_add_name_in_users_table.php" has been created.
// ciacme/application/migrations/20241019044035_add_name_in_users_table.php
use Rougin\Refinery\Migration;
class Migration_add_name_in_users_table extends Migration
{
/**
* @return void
*/
public function up()
{
$data = array('name' => array());
$data['name']['type'] = 'varchar';
$data['name']['auto_increment'] = false;
$data['name']['constraint'] = 100;
$data['name']['default'] = null;
$data['name']['null'] = true;
$data['name']['unsigned'] = false;
$this->dbforge->add_column('users', $data);
}
/**
* @return void
*/
public function down()
{
$this->dbforge->drop_column('users', 'name');
}
}
Please see the accepted keywords below when creating database migration files:
Keyword | Description | Example |
---|---|---|
add | Adds new column to a table | add_name_in_users_table |
create | Creates new table with id as the primary key | create_users_table |
delete | Deletes a column from a table | delete_name_in_users_table |
modify | Updates a column of a table | modify_name_in_users_table |
Kindly use the migrate
command to use the files for database migrations:
$ vendor/bin/refinery migrate
[INFO] Migrating "create_users_table"...
[PASS] "create_users_table" migrated!
[INFO] Migrating "add_name_in_users_table"...
[PASS] "add_name_in_users_table" migrated!
When running this command, the target timestamp (--target
) will always be the latest file in the migrations
directory if not specified (e.g., add_name_in_users_table
). Use the --target
option to migrate to a specific version:
$ vendor/bin/refinery migrate --target=20241019044009
[INFO] Migrating "create_users_table"...
[PASS] "create_users_table" migrated!
To rollback a database, kindly use the rollback
command:
$ vendor/bin/refinery rollback
[INFO] Rolling back "add_name_in_users_table"...
[PASS] "add_name_in_users_table" rolled back!
[!NOTE] Without a
--target
option, therollback
will only revert to its previous version (e.g.,create_users_table
).
To reset back the database schema to version 0
, the reset
command can be used:
$ vendor/bin/refinery migrate
[INFO] Migrating "add_name_in_users_table"...
[PASS] "add_name_in_users_table" migrated!
$ vendor/bin/refinery reset
[INFO] Rolling back "add_name_in_users_table"...
[PASS] "add_name_in_users_table" rolled back!
[INFO] Rolling back "create_users_table"...
[PASS] "create_users_table" rolled back!
Refinery
also allows to create a database migration based on the existing database table. Prior in creating its database migration, kindly ensure that the specified table already exists in the database schema:
CREATE TABLE IF NOT EXISTS `users` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
After checking the database table exists, run the same create
command with the --from-database
option:
$ vendor/bin/refinery create create_users_table --from-database
"20241019044729_create_users_table.php" has been created.
// ciacme/application/migrations/20241019044729_create_users_table.php
use Rougin\Refinery\Migration;
class Migration_create_users_table extends Migration
{
/**
* @return void
*/
public function up()
{
$data = array('id' => array());
$data['id']['type'] = 'integer';
$data['id']['auto_increment'] = true;
$data['id']['constraint'] = 10;
$this->dbforge->add_field($data);
$this->dbforge->add_key('id', true);
$data = array('name' => array());
$data['name']['type'] = 'varchar';
$data['name']['auto_increment'] = false;
$data['name']['constraint'] = 100;
$data['name']['default'] = null;
$data['name']['null'] = true;
$data['name']['unsigned'] = false;
$this->dbforge->add_field($data);
$this->dbforge->create_table('users');
}
/**
* @return void
*/
public function down()
{
$this->dbforge->drop_table('users');
}
}
[!NOTE] The
--from-database
option only exists when creating files under thecreate_*_table
prefix.
By default, Refinery
uses a timestamp prefix as its numbering style when creating migration files. To change it to a sequential numbering, kindly update the value of migration_type
in the config/migration.php
to sequential
:
// ciacme/application/config/migration.php
/*
|--------------------------------------------------------------------------
| Migration Type
|--------------------------------------------------------------------------
|
| Migration file names may be based on a sequential identifier or on
| a timestamp. Options are:
|
| 'sequential' = Sequential migration naming (001_add_blog.php)
| 'timestamp' = Timestamp migration naming (20121031104401_add_blog.php)
| Use timestamp format YYYYMMDDHHIISS.
|
| Note: If this configuration value is missing the Migration library
| defaults to 'sequential' for backward compatibility with CI2.
|
*/
$config['migration_type'] = 'sequential';
Then run the create
command to generate a migration file in sequential migration:
$ vendor/bin/refinery create create_users_table
[PASS] "001_create_users_table.php" successfully created!
Alternatively, the --sequential
option can also be added in the create
command to update the said configuration:
$ vendor/bin/refinery create add_name_in_users_table --sequential
[PASS] "002_add_name_in_users_table.php" successfully created!
[!NOTE] When using the
--sequential
option, themigration_type
in theconfig/migration.php
is also set assequential
.
refinery.yml
Refinery
currently works out of the box after the configuration based on Installation
. However, using a refinery.yml
can be used for complex setups like specifying the new application path:
# refinery.yml
app_path: %%CURRENT_DIRECTORY%%
To create a refinery.yml
, simply run the initialize
command:
$ vendor/bin/refinery initialize
[PASS] "refinery.yml" added successfully!
[!NOTE]
%%CURRENT_DIRECTORY%%
is a placeholder variable which is the current directory ofrefinery.yml
.
app_path
This property specifies the application
directory. It may updated to any directory (e.g., ciacme/application
, ciacme/config
, etc.) as long it can detect the config/config.php
file from the defined directory:
# refinery.yml
app_path: %%CURRENT_DIRECTORY%%/Sample
# ...
[!NOTE]
Refinery
will try to check the path specified inapp_path
if it is a validCodeigniter 3
project. Then it will perform another check if theapplication
directory exists or if theconfig
directory can be accessed directly from the directory defined inapp_path
.