Create and manage Doctrine migrations for schema versioning; handle migration dependencies, rollbacks, and production deployment
/plugin marketplace add MakFly/superpowers-symfony/plugin install makfly-superpowers-symfony@MakFly/superpowers-symfonyThis skill inherits all available tools. When active, it can use any tool Claude has access to.
composer require doctrine/doctrine-migrations-bundle
# Generate migration from entity changes
bin/console make:migration
# Or using doctrine directly
bin/console doctrine:migrations:diff
# Run pending migrations
bin/console doctrine:migrations:migrate
# Check status
bin/console doctrine:migrations:status
# List all migrations
bin/console doctrine:migrations:list
<?php
// src/Entity/User.php
#[ORM\Entity]
class User
{
// Add new property
#[ORM\Column(length: 255, nullable: true)]
private ?string $avatarUrl = null;
}
bin/console make:migration
Generated file:
<?php
// migrations/Version20240115120000.php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20240115120000 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add avatar_url column to user table';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE user ADD avatar_url VARCHAR(255) DEFAULT NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE user DROP avatar_url');
}
}
# Dry run first
bin/console doctrine:migrations:migrate --dry-run
# Execute
bin/console doctrine:migrations:migrate
public function up(Schema $schema): void
{
// Schema change
$this->addSql('ALTER TABLE user ADD status VARCHAR(20) NOT NULL DEFAULT \'active\'');
// Data migration
$this->addSql("UPDATE user SET status = 'inactive' WHERE last_login < DATE_SUB(NOW(), INTERVAL 1 YEAR)");
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE order ADD customer_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE order ADD CONSTRAINT FK_ORDER_CUSTOMER FOREIGN KEY (customer_id) REFERENCES customer (id)');
$this->addSql('CREATE INDEX IDX_ORDER_CUSTOMER ON order (customer_id)');
}
public function up(Schema $schema): void
{
$table = $schema->getTable('user');
$table->addColumn('avatar_url', 'string', [
'length' => 255,
'notnull' => false,
]);
$table->addIndex(['avatar_url'], 'idx_user_avatar');
}
public function up(Schema $schema): void
{
// Only for MySQL
if ($this->connection->getDatabasePlatform()->getName() === 'mysql') {
$this->addSql('ALTER TABLE user ENGINE=InnoDB');
}
}
public function preUp(Schema $schema): void
{
// Check before running
$count = $this->connection->fetchOne('SELECT COUNT(*) FROM user WHERE status IS NULL');
if ($count > 0) {
throw new \Exception('Cannot migrate: null status values exist');
}
}
public function postUp(Schema $schema): void
{
// Verify after running
$this->connection->executeQuery('ANALYZE TABLE user');
}
# Rollback last migration
bin/console doctrine:migrations:migrate prev
# Rollback to specific version
bin/console doctrine:migrations:migrate Version20240101000000
# Rollback all
bin/console doctrine:migrations:migrate first
# Mark migration as executed (without running)
bin/console doctrine:migrations:version --add Version20240115120000
# Remove from version table
bin/console doctrine:migrations:version --delete Version20240115120000
# config/packages/doctrine_migrations.yaml
doctrine_migrations:
migrations_paths:
'DoctrineMigrations': '%kernel.project_dir%/migrations'
all_or_nothing: true
transactional: true
check_database_platform: true
organize_migrations: none # none, year, year_and_month
# On staging
bin/console doctrine:migrations:migrate --dry-run
bin/console doctrine:migrations:migrate
# Verify schema
bin/console doctrine:schema:validate
# MySQL
mysqldump -u user -p database > backup_$(date +%Y%m%d_%H%M%S).sql
# PostgreSQL
pg_dump -U user database > backup_$(date +%Y%m%d_%H%M%S).sql
For large tables, consider:
// Instead of adding NOT NULL column directly
public function up(Schema $schema): void
{
// Step 1: Add nullable column
$this->addSql('ALTER TABLE user ADD status VARCHAR(20) DEFAULT NULL');
}
// In next migration after data backfill
public function up(Schema $schema): void
{
// Step 2: Make it NOT NULL
$this->addSql('ALTER TABLE user MODIFY status VARCHAR(20) NOT NULL');
}
# .github/workflows/deploy.yml
- name: Run migrations
run: |
php bin/console doctrine:migrations:migrate --no-interaction --allow-no-migration
# Validate mapping
bin/console doctrine:schema:validate
# Compare schema with entities
bin/console doctrine:schema:update --dump-sql
# Force re-run (dangerous!)
bin/console doctrine:migrations:execute Version20240115120000 --up
# Or mark as not executed
bin/console doctrine:migrations:version --delete Version20240115120000
bin/console doctrine:migrations:migrate
When multiple developers create migrations:
bin/console doctrine:migrations:migrate prevbin/console make:migrationApplies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.