Home

Published

- 2 min read

Doctrine and SQLite migrations: How to disable foreign keys in PHP 8.4

Doctrine and SQLite migrations: How to disable foreign keys in PHP 8.4

SQLite has limited capabilities for modifying tables—often, you must drop the original table and recreate it, which can break your foreign keys. PHP 8.4 provides a cool solution for that.

The problem

If you use a SQLite database in a Doctrine project and enable foreign key checks, you’ll run into an issue with table-modifying migrations: You often need to drop and fully recreate the table. If that table is referenced by others, the migration will fail unless you disable the foreign key checks. Furthermore, the entire migration runs inside a transaction, and SQLite doesn’t allow changing foreign key checks during a transaction.

The solution

There are several possible solutions, but here’s a particularly neat one made possible by PHP 8.4’s new property hooks:

final class VersionXXXXXXXXXXXXXX extends AbstractMigration
{
    protected $connection {
        get {
            $this->connection->executeStatement('PRAGMA foreign_keys = OFF');
            return $this->connection;
        }
        set => $this->connection = $value;
    }

    public function up(Schema $schema): void
    {
        // TODO create migration
    }

    public function down(Schema $schema): void
    {
        // TODO create migration
    }
}

The code above overrides the $connection property from the parent class with a property hook, so every time the migration system requests a connection, the foreign key checks are disabled.

© 2024 Dominik Chrástecký. All rights reserved.