Database Migrations
This document describes how to manage database migrations in WebFramework, including file organization, versioning, and the actions supported by the DatabaseManager class.
Migration File Organization
Database migration files should be placed in the db_scheme
directory of your application. Each migration file should be numbered incrementally and have a .php
extension. For example:
db_scheme/
├── 1.php # Initial schema
├── 2.php # Add user roles
├── 3.php # Add email verification
└── 4.php # Add user preferences
File Naming
- Files should be numbered incrementally (1.php, 2.php, 3.php, etc.)
- Each number represents a database version
- Files must be applied in order
- No gaps in numbering are allowed
Version Management
After adding a new migration file, you must update the required database version in your config/config.php
:
return [
// Other configuration settings...
'versions' => [
'required_app_db' => 4, // Should match your latest migration file number
],
];
This ensures that the application knows which database version it requires to function correctly.
Migration Actions
The DatabaseManager supports various actions for modifying the database schema. Here are all the supported actions:
Create Table
Creates a new table in the database.
Fields
type
(required): Must be "create_table"table_name
(required): The name of the table to createfields
(required): An array of field definitionsconstraints
(required): An array of constraint definitions
Field Definition
Each field definition is an associative array that can include the following keys:
- name
(required): The name of the field
- type
(required): The data type of the field. Common types include:
- String types (require quotes for default values):
- varchar
: Variable-length string (requires size)
- char
: Fixed-length string (requires size)
- text
: Text field
- tinytext
: Small text field
- mediumtext
: Medium text field
- longtext
: Large text field
- enum
: Enumerated values
- set
: Set of values
- json
: JSON data
- Binary types (require quotes for default values):
- binary
: Fixed-length binary (requires size)
- varbinary
: Variable-length binary (requires size)
- blob
: Binary large object
- tinyblob
: Small binary large object
- mediumblob
: Medium binary large object
- longblob
: Large binary large object
- Date/Time types (require quotes for default values unless using functions):
- datetime
: Date and time
- timestamp
: Timestamp
- date
: Date
- time
: Time
- Numeric types (no quotes for default values):
- int
: Integer (optional size)
- tinyint
: Small integer (optional size)
- smallint
: Small integer (optional size)
- mediumint
: Medium integer (optional size)
- bigint
: Large integer (optional size)
- decimal
: Decimal number (optional size)
- numeric
: Numeric value (optional size)
- float
: Floating point number
- double
: Double precision number
- Special types:
- foreign_key
: Foreign key reference
- size
(required/optional): The size or length of the field:
- Required for: varchar, char, binary, varbinary
- Optional for: int, tinyint, smallint, mediumint, bigint, decimal, numeric
- Not used for: text, datetime, timestamp, date, time, json
- default
(optional): The default value for the field. Can be either:
- A string or number value: Will be quoted automatically based on the field type
- An array with a 'function' key: The value will be used as-is without quotes as a SQL function
Example with Various Types and Defaults
<?php
return [
'target_version' => 1,
'actions' => [
[
'type' => 'create_table',
'table_name' => 'items',
'fields' => [
[
'name' => 'name',
'type' => 'varchar',
'size' => 255,
'default' => 'Unnamed Item', // Will be: DEFAULT 'Unnamed Item'
],
[
'name' => 'created_at',
'type' => 'datetime',
'default' => ['function' => 'CURRENT_TIMESTAMP'], // Will be: DEFAULT CURRENT_TIMESTAMP
],
[
'name' => 'status',
'type' => 'enum',
'default' => 'pending', // Will be: DEFAULT 'pending'
],
[
'name' => 'count',
'type' => 'int',
'default' => 0, // Will be: DEFAULT 0
],
[
'name' => 'metadata',
'type' => 'json',
'default' => '{}', // Will be: DEFAULT '{}'
],
[
'name' => 'type_id',
'type' => 'foreign_key',
'foreign_table' => 'item_types',
'foreign_field' => 'id',
'on_delete' => 'SET NULL',
'on_update' => 'CASCADE',
],
],
'constraints' => [
[
'type' => 'unique',
'values' => ['name'],
],
],
],
],
];
Create Trigger
Creates a new trigger in the database.
Fields
type
(required): Must be "create_trigger"table_name
(required): The name of the table for the triggertrigger
(required): An array containing trigger detailsname
(required): The name of the triggertime
(required): The trigger time (BEFORE or AFTER)event
(required): The trigger event (INSERT, UPDATE, or DELETE)action
(required): The SQL statement to execute when the trigger fires
Example
<?php
return [
'target_version' => 2,
'actions' => [
[
'type' => 'create_trigger',
'table_name' => 'users',
'trigger' => [
'name' => 'update_last_modified',
'time' => 'BEFORE',
'event' => 'UPDATE',
'action' => 'SET NEW.updated_at = CURRENT_TIMESTAMP',
],
],
],
];
Add Column
Adds a new column to an existing table.
Fields
type
(required): Must be "add_column"table_name
(required): The name of the table to alterfield
(required): An array containing the new column details
Example
<?php
return [
'target_version' => 3,
'actions' => [
[
'type' => 'add_column',
'table_name' => 'users',
'field' => [
'name' => 'last_login',
'type' => 'datetime',
'null' => true,
],
],
],
];
Add Constraint
Adds a new constraint to an existing table.
Fields
type
(required): Must be "add_constraint"table_name
(required): The name of the table to alterconstraint
(required): An array containing the constraint details
Example
<?php
return [
'target_version' => 4,
'actions' => [
[
'type' => 'add_constraint',
'table_name' => 'users',
'constraint' => [
'type' => 'unique',
'values' => ['username', 'email'],
],
],
],
];
Insert Row
Inserts a new row into a table.
Fields
type
(required): Must be "insert_row"table_name
(required): The name of the table to insert intovalues
(required): An array of column-value pairs to insert
Example
<?php
return [
'target_version' => 5,
'actions' => [
[
'type' => 'insert_row',
'table_name' => 'users',
'values' => [
'username' => 'admin',
'email' => 'admin@example.com',
'created_at' => '2023-04-01 00:00:00',
],
],
],
];
Modify Column Type
Modifies the type or attributes of an existing column.
Fields
type
(required): Must be "modify_column_type"table_name
(required): The name of the table to alterfield
(required): An array containing the modified column details
Example
<?php
return [
'target_version' => 6,
'actions' => [
[
'type' => 'modify_column_type',
'table_name' => 'users',
'field' => [
'name' => 'username',
'type' => 'varchar',
'size' => 100,
'null' => false,
],
],
],
];
Rename Column
Renames an existing column in a table.
Fields
type
(required): Must be "rename_column"table_name
(required): The name of the table to altername
(required): The current name of the columnnew_name
(required): The new name for the column
Example
<?php
return [
'target_version' => 7,
'actions' => [
[
'type' => 'rename_column',
'table_name' => 'users',
'name' => 'email',
'new_name' => 'user_email',
],
],
];
Rename Table
Renames an existing table.
Fields
type
(required): Must be "rename_table"table_name
(required): The current name of the tablenew_name
(required): The new name for the table
Example
<?php
return [
'target_version' => 8,
'actions' => [
[
'type' => 'rename_table',
'table_name' => 'users',
'new_name' => 'app_users',
],
],
];
Raw Query
Executes a raw SQL query.
Fields
type
(required): Must be "raw_query"query
(required): The raw SQL query to executeparams
(required): An array of parameters for the query (can be empty)
Example
<?php
return [
'target_version' => 9,
'actions' => [
[
'type' => 'raw_query',
'query' => 'UPDATE users SET status = ? WHERE last_login < ?',
'params' => ['inactive', '2023-01-01 00:00:00'],
],
],
];
Run Task
Executes a custom task defined in a separate class.
Fields
type
(required): Must be "run_task"task
(required): The fully qualified class name of the task to run
Example
<?php
return [
'target_version' => 10,
'actions' => [
[
'type' => 'run_task',
'task' => 'App\Tasks\CustomMigrationTask',
],
],
];
Note: The custom task class must implement the TaskInterface
and be registered in the dependency injection container.