Files
michaelschiemer/docs/features/database/migrations.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

203 lines
5.4 KiB
Markdown

# Migration System Quick Reference
## TL;DR
**Default**: Migrations sind forward-only (nur `up()` Methode).
**Optional**: Implementiere `SafelyReversible` nur wenn Rollback OHNE Datenverlust möglich ist.
## Quick Decision Tree
```
Is rollback safe (no data loss)?
├─ YES (e.g., create table, add nullable column, create index)
│ └─ Implement: Migration, SafelyReversible
└─ NO (e.g., drop column, transform data, delete data)
└─ Implement: Migration only
```
## Code Templates
### Forward-Only Migration (Default)
```php
use App\Framework\Database\Migration\Migration;
use App\Framework\Database\Migration\MigrationVersion;
use App\Framework\Database\ConnectionInterface;
use App\Framework\Database\Schema\Schema;
final readonly class YourMigration implements Migration
{
public function up(ConnectionInterface $connection): void
{
$schema = new Schema($connection);
// Your migration logic
$schema->execute();
}
public function getVersion(): MigrationVersion
{
return MigrationVersion::fromTimestamp("2024_12_20_100000");
}
public function getDescription(): string
{
return 'Description of what this migration does';
}
public function getDomain(): string
{
return "YourDomain";
}
}
```
### Safe Rollback Migration
```php
use App\Framework\Database\Migration\{Migration, SafelyReversible};
use App\Framework\Database\Migration\MigrationVersion;
use App\Framework\Database\ConnectionInterface;
use App\Framework\Database\Schema\Schema;
/**
* This migration is safely reversible because:
* - [Explain why rollback is safe, e.g., "Creates new empty table"]
*/
final readonly class YourSafeMigration implements Migration, SafelyReversible
{
public function up(ConnectionInterface $connection): void
{
$schema = new Schema($connection);
// Your migration logic
$schema->execute();
}
public function down(ConnectionInterface $connection): void
{
$schema = new Schema($connection);
// Reverse the changes safely
$schema->execute();
}
public function getVersion(): MigrationVersion
{
return MigrationVersion::fromTimestamp("2024_12_20_100000");
}
public function getDescription(): string
{
return 'Description of what this migration does';
}
public function getDomain(): string
{
return "YourDomain";
}
}
```
## Common Operations
### Create Migration
```bash
php console.php make:migration CreateYourTable
```
### Run Migrations
```bash
php console.php db:migrate
```
### Rollback (Only SafelyReversible)
```bash
# Rollback last migration
php console.php db:rollback
# Rollback last 3 migrations
php console.php db:rollback 3
```
### Check Status
```bash
php console.php db:status
```
## Safe vs Unsafe Cheatsheet
| Operation | Safe? | Implements |
|-----------|-------|------------|
| Create table | ✅ | Migration, SafelyReversible |
| Drop table (empty) | ✅ | Migration, SafelyReversible |
| Drop table (with data) | ❌ | Migration only |
| Add nullable column | ✅ | Migration, SafelyReversible |
| Add NOT NULL column (with default) | ⚠️ | Case by case |
| Drop column (empty) | ✅ | Migration, SafelyReversible |
| Drop column (with data) | ❌ | Migration only |
| Rename column | ✅ | Migration, SafelyReversible |
| Change column type | ❌ | Migration only |
| Create index | ✅ | Migration, SafelyReversible |
| Drop index | ✅ | Migration, SafelyReversible |
| Add foreign key | ✅ | Migration, SafelyReversible |
| Drop foreign key | ✅ | Migration, SafelyReversible |
| Transform data | ❌ | Migration only |
| Delete data | ❌ | Migration only |
| Merge tables | ❌ | Migration only |
## Error Handling
### Rollback Failed (Not SafelyReversible)
```bash
❌ Rollback failed: Migration 2024_12_20_100000 does not support safe rollback
💡 Recommendation:
Create a new forward migration to undo the changes instead:
php console.php make:migration FixYourChanges
```
### What to do:
1. Create new forward migration
2. Implement reverse logic in `up()` method
3. Run `php console.php db:migrate`
## Testing Rollback
```bash
# Test cycle in development
php console.php db:migrate
php console.php db:rollback 1
php console.php db:migrate # Should succeed again
```
## Best Practices
1.**Document why safe**: Always comment why a migration is SafelyReversible
2.**Test rollback cycle**: Test `up() → down() → up()` in development
3.**Default to forward-only**: Only add SafelyReversible if certain
4.**Never rollback in production**: Even "safe" rollbacks should be avoided
5.**Use fix-forward**: Prefer new migrations over rollback
6.**Backup before rollback**: Always backup database before rolling back
7.**Check for data**: Verify column is empty before making it SafelyReversible
## Links
- **Full Examples**: `docs/claude/examples/migrations/SafeVsUnsafeMigrations.md`
- **Database Patterns**: `docs/claude/database-patterns.md`
- **Migration Interface**: `src/Framework/Database/Migration/Migration.php`
- **SafelyReversible Interface**: `src/Framework/Database/Migration/SafelyReversible.php`
## Framework Compliance
✅ Readonly classes: `final readonly class`
✅ Composition over inheritance: Interface-based
✅ Explicit contracts: `SafelyReversible` is opt-in
✅ Type safety: Strong typing throughout
✅ No primitive obsession: Uses Value Objects (MigrationVersion)