|
| 1 | +# Database Migrations |
| 2 | + |
| 3 | +The CMS component includes database migration capabilities powered by [Phinx](https://phinx.org/). This allows you to version control your database schema and manage changes across different environments. |
| 4 | + |
| 5 | +## Configuration |
| 6 | + |
| 7 | +Add the following configuration to your `config/config.yaml`: |
| 8 | + |
| 9 | +```yaml |
| 10 | +database: |
| 11 | + # Database adapter (mysql, pgsql, sqlite) |
| 12 | + adapter: mysql |
| 13 | + |
| 14 | + # Database host |
| 15 | + host: localhost |
| 16 | + |
| 17 | + # Database name |
| 18 | + name: neuron_cms |
| 19 | + |
| 20 | + # Database username |
| 21 | + user: root |
| 22 | + |
| 23 | + # Database password |
| 24 | + pass: secret |
| 25 | + |
| 26 | + # Database port (3306 for MySQL, 5432 for PostgreSQL) |
| 27 | + port: 3306 |
| 28 | + |
| 29 | + # Character set |
| 30 | + charset: utf8mb4 |
| 31 | + |
| 32 | +migrations: |
| 33 | + # Path to migrations directory (relative to project root) |
| 34 | + path: db/migrate |
| 35 | + |
| 36 | + # Path to seeds directory (relative to project root) |
| 37 | + seeds_path: db/seed |
| 38 | + |
| 39 | + # Migration tracking table name |
| 40 | + table: phinx_log |
| 41 | +``` |
| 42 | +
|
| 43 | +See `resources/config/database.yaml.example` for a complete configuration example. |
| 44 | + |
| 45 | +## Directory Structure |
| 46 | + |
| 47 | +Migrations and seeders are stored in your project root (not in vendor): |
| 48 | + |
| 49 | +``` |
| 50 | +your-project/ |
| 51 | +├── config/ |
| 52 | +│ └── config.yaml # Database configuration |
| 53 | +├── db/ |
| 54 | +│ ├── migrate/ # Migration files |
| 55 | +│ └── seed/ # Seeder files |
| 56 | +└── vendor/ |
| 57 | + └── neuron-php/cms/ |
| 58 | +``` |
| 59 | + |
| 60 | +## Available Commands |
| 61 | + |
| 62 | +### Create Migration |
| 63 | + |
| 64 | +Create a new migration file: |
| 65 | + |
| 66 | +```bash |
| 67 | +php neuron db:migration:generate CreateUsersTable |
| 68 | +``` |
| 69 | + |
| 70 | +Options: |
| 71 | +- `--class` - Use a specific class name |
| 72 | +- `--template` - Use a custom migration template |
| 73 | +- `--config` - Path to configuration directory (defaults to auto-detection) |
| 74 | + |
| 75 | +This creates a timestamped migration file in `db/migrate/`: |
| 76 | + |
| 77 | +```php |
| 78 | +<?php |
| 79 | +
|
| 80 | +use Phinx\Migration\AbstractMigration; |
| 81 | +
|
| 82 | +class CreateUsersTable extends AbstractMigration |
| 83 | +{ |
| 84 | + public function change() |
| 85 | + { |
| 86 | + $table = $this->table('users'); |
| 87 | + $table->addColumn('email', 'string', ['limit' => 255]) |
| 88 | + ->addColumn('password', 'string', ['limit' => 255]) |
| 89 | + ->addColumn('created_at', 'datetime') |
| 90 | + ->addColumn('updated_at', 'datetime', ['null' => true]) |
| 91 | + ->addIndex(['email'], ['unique' => true]) |
| 92 | + ->create(); |
| 93 | + } |
| 94 | +} |
| 95 | +``` |
| 96 | + |
| 97 | +### Run Migrations |
| 98 | + |
| 99 | +Execute all pending migrations: |
| 100 | + |
| 101 | +```bash |
| 102 | +php neuron db:migrate |
| 103 | +``` |
| 104 | + |
| 105 | +Options: |
| 106 | +- `--target` - Migrate to a specific version |
| 107 | +- `--date` - Migrate to a specific date (YYYYMMDD format) |
| 108 | +- `--dry-run` - Show migrations without executing |
| 109 | +- `--fake` - Mark migrations as run without executing |
| 110 | + |
| 111 | +Examples: |
| 112 | + |
| 113 | +```bash |
| 114 | +# Run all pending migrations |
| 115 | +php neuron db:migrate |
| 116 | +
|
| 117 | +# Migrate to specific version |
| 118 | +php neuron db:migrate --target=20241105120000 |
| 119 | +
|
| 120 | +# Dry run to see what would be executed |
| 121 | +php neuron db:migrate --dry-run |
| 122 | +``` |
| 123 | + |
| 124 | +### Rollback Migrations |
| 125 | + |
| 126 | +Rollback the last migration: |
| 127 | + |
| 128 | +```bash |
| 129 | +php neuron db:rollback |
| 130 | +``` |
| 131 | + |
| 132 | +Options: |
| 133 | +- `--target` - Rollback to a specific version |
| 134 | +- `--date` - Rollback to a specific date |
| 135 | +- `--force` - Skip confirmation prompt |
| 136 | +- `--dry-run` - Show what would be rolled back |
| 137 | +- `--fake` - Mark as rolled back without executing |
| 138 | + |
| 139 | +Examples: |
| 140 | + |
| 141 | +```bash |
| 142 | +# Rollback last migration (with confirmation) |
| 143 | +php neuron db:rollback |
| 144 | +
|
| 145 | +# Rollback to specific version without confirmation |
| 146 | +php neuron db:rollback --target=20241105120000 --force |
| 147 | +
|
| 148 | +# Dry run to see what would be rolled back |
| 149 | +php neuron db:rollback --dry-run |
| 150 | +``` |
| 151 | + |
| 152 | +### Check Migration Status |
| 153 | + |
| 154 | +View the status of all migrations: |
| 155 | + |
| 156 | +```bash |
| 157 | +php neuron db:migrate:status |
| 158 | +``` |
| 159 | + |
| 160 | +Options: |
| 161 | +- `--format` - Output format (text or json) |
| 162 | + |
| 163 | +Output example: |
| 164 | + |
| 165 | +``` |
| 166 | +Status Migration ID Migration Name |
| 167 | +-------------------------------------- |
| 168 | + up 20241105120000 CreateUsersTable |
| 169 | + up 20241105130000 CreatePostsTable |
| 170 | + down 20241105140000 AddCommentsTable |
| 171 | +``` |
| 172 | + |
| 173 | +### Run Seeders |
| 174 | + |
| 175 | +Populate the database with test or initial data: |
| 176 | + |
| 177 | +```bash |
| 178 | +php neuron db:seed |
| 179 | +``` |
| 180 | + |
| 181 | +Options: |
| 182 | +- `--seed` or `-s` - Run a specific seeder class |
| 183 | +- `--config` - Path to configuration directory |
| 184 | + |
| 185 | +Examples: |
| 186 | + |
| 187 | +```bash |
| 188 | +# Run all seeders |
| 189 | +php neuron db:seed |
| 190 | +
|
| 191 | +# Run specific seeder |
| 192 | +php neuron db:seed --seed=UserSeeder |
| 193 | +``` |
| 194 | + |
| 195 | +Create a seeder file in `db/seed/`: |
| 196 | + |
| 197 | +```php |
| 198 | +<?php |
| 199 | +
|
| 200 | +use Phinx\Seed\AbstractSeed; |
| 201 | +
|
| 202 | +class UserSeeder extends AbstractSeed |
| 203 | +{ |
| 204 | + public function run() |
| 205 | + { |
| 206 | + $data = [ |
| 207 | + [ |
| 208 | + |
| 209 | + 'password' => password_hash('secret', PASSWORD_BCRYPT), |
| 210 | + 'created_at' => date('Y-m-d H:i:s'), |
| 211 | + ], |
| 212 | + [ |
| 213 | + |
| 214 | + 'password' => password_hash('secret', PASSWORD_BCRYPT), |
| 215 | + 'created_at' => date('Y-m-d H:i:s'), |
| 216 | + ] |
| 217 | + ]; |
| 218 | +
|
| 219 | + $users = $this->table('users'); |
| 220 | + $users->insert($data)->save(); |
| 221 | + } |
| 222 | +} |
| 223 | +``` |
| 224 | + |
| 225 | +## Migration Examples |
| 226 | + |
| 227 | +### Creating Tables |
| 228 | + |
| 229 | +```php |
| 230 | +public function change() |
| 231 | +{ |
| 232 | + $table = $this->table('posts'); |
| 233 | + $table->addColumn('title', 'string', ['limit' => 255]) |
| 234 | + ->addColumn('body', 'text') |
| 235 | + ->addColumn('user_id', 'integer') |
| 236 | + ->addColumn('published_at', 'datetime', ['null' => true]) |
| 237 | + ->addColumn('created_at', 'datetime') |
| 238 | + ->addColumn('updated_at', 'datetime', ['null' => true]) |
| 239 | + ->addForeignKey('user_id', 'users', 'id', ['delete' => 'CASCADE']) |
| 240 | + ->create(); |
| 241 | +} |
| 242 | +``` |
| 243 | + |
| 244 | +### Modifying Tables |
| 245 | + |
| 246 | +```php |
| 247 | +public function change() |
| 248 | +{ |
| 249 | + $table = $this->table('users'); |
| 250 | + $table->addColumn('phone', 'string', ['limit' => 20, 'null' => true, 'after' => 'email']) |
| 251 | + ->addColumn('status', 'string', ['limit' => 20, 'default' => 'active']) |
| 252 | + ->addIndex(['status']) |
| 253 | + ->update(); |
| 254 | +} |
| 255 | +``` |
| 256 | + |
| 257 | +### Data Migrations |
| 258 | + |
| 259 | +```php |
| 260 | +public function up() |
| 261 | +{ |
| 262 | + $this->execute("UPDATE users SET status = 'active' WHERE status IS NULL"); |
| 263 | +} |
| 264 | +
|
| 265 | +public function down() |
| 266 | +{ |
| 267 | + $this->execute("UPDATE users SET status = NULL WHERE status = 'active'"); |
| 268 | +} |
| 269 | +``` |
| 270 | + |
| 271 | +## Best Practices |
| 272 | + |
| 273 | +1. **Always test migrations** - Test both up and down migrations in a development environment |
| 274 | + |
| 275 | +2. **Use change() when possible** - Phinx can automatically reverse most migration operations |
| 276 | + |
| 277 | +3. **Use up() and down() for complex migrations** - When automatic reversal isn't possible |
| 278 | + |
| 279 | +4. **Keep migrations focused** - One logical change per migration file |
| 280 | + |
| 281 | +5. **Don't modify old migrations** - Create new migrations to change existing tables |
| 282 | + |
| 283 | +6. **Use seeders for test data** - Keep production data separate from migrations |
| 284 | + |
| 285 | +7. **Version control everything** - Commit migration files to your repository |
| 286 | + |
| 287 | +8. **Back up before rollback** - Always backup production databases before rolling back |
| 288 | + |
| 289 | +## Database Support |
| 290 | + |
| 291 | +The migration system supports the following database adapters: |
| 292 | + |
| 293 | +- **MySQL** - adapter: mysql |
| 294 | +- **PostgreSQL** - adapter: pgsql |
| 295 | +- **SQLite** - adapter: sqlite |
| 296 | + |
| 297 | +## Troubleshooting |
| 298 | + |
| 299 | +### Migrations directory not found |
| 300 | + |
| 301 | +If you see "Migrations directory not found", ensure: |
| 302 | +1. The `migrations.path` is set in your config.yaml |
| 303 | +2. The directory exists or run a migration command to auto-create it |
| 304 | + |
| 305 | +### Configuration not found |
| 306 | + |
| 307 | +If configuration is not detected automatically: |
| 308 | +1. Use the `--config` option to specify the path |
| 309 | +2. Ensure config.yaml exists in the specified directory |
| 310 | + |
| 311 | +### Database connection errors |
| 312 | + |
| 313 | +Verify your database configuration: |
| 314 | +1. Check database credentials in config.yaml |
| 315 | +2. Ensure the database exists |
| 316 | +3. Verify the database server is running |
| 317 | +4. Check network connectivity to the database host |
| 318 | + |
| 319 | +## Further Reading |
| 320 | + |
| 321 | +For advanced Phinx features and configuration options, see: |
| 322 | +- [Phinx Documentation](https://docs.phinx.org/) |
| 323 | +- [Writing Migrations](https://docs.phinx.org/en/latest/migrations.html) |
| 324 | +- [Seeding Data](https://docs.phinx.org/en/latest/seeding.html) |
0 commit comments