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
Migrationclass underRefineryis directly extended onCI_Migration.- The created file will be in
migrationsdirectory underapplication. If it does not exists,Refinerywill 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
--targetoption, therollbackwill 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-databaseoption only exists when creating files under thecreate_*_tableprefix.
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
--sequentialoption, themigration_typein theconfig/migration.phpis also set assequential.
refinery.ymlRefinery 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_pathThis 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]
Refinerywill try to check the path specified inapp_pathif it is a validCodeigniter 3project. Then it will perform another check if theapplicationdirectory exists or if theconfigdirectory can be accessed directly from the directory defined inapp_path.