Doctrine DBAL, команда diff и тип перечисления
Я работаю с symfony 5.1, doctrine-bundle 2.1.2 и doctrine-migrations-bundle 2.2. Я НЕ работаю с ORM и определяю свои собственные схемы. Чтобы добавить типы Enum, я использую следующий код:
abstract class EnumType extends Type
{
protected string $name;
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
$values = $this->getValues();
$maxLength = max(array_map('strlen', $values));
$columnName = $fieldDeclaration['name'];
$implodedValues = implode(', ', array_map(function($value) {return "'$value'";}, $values));
if ($platform instanceof MySqlPlatform) {
return "ENUM($implodedValues)";
}
if (
$platform instanceof SQLServer2012Platform
|| $platform instanceof PostgreSQL94Platform
) {
return "VARCHAR($maxLength) CHECK ({$columnName} IN ($implodedValues))";
}
if ($platform instanceof SqlitePlatform) {
return "TEXT CHECK ({$columnName} IN ($implodedValues))";
}
throw DBALException::invalidPlatformType($platform);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return $value;
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if (!in_array($value, $this->getValues())) {
throw new \InvalidArgumentException("Invalid '" . $this->name . "' value: " . (string)$value);
}
return $value;
}
public function getName()
{
return $this->name;
}
public function requiresSQLCommentHint(AbstractPlatform $platform)
{
return true;
}
abstract function getValues(): array;
}
Затем каждое перечисление расширяет этот абстрактный класс для установки значений.
Создание не проблема. Когда я запускаю команду миграции diff, я получаю следующее сообщение об ошибке:
Запрошено перечисление неизвестного типа базы данных, Doctrine\DBAL\Platforms\MySQL57Platform может не поддерживать его.
Любые идеи, как я могу создать разницу, которая также включает любые изменения в самом перечислении?
1 ответ
Я решил это, создав свой собственный diff, который сначала добавляет тип enum, если его еще нет, используя:
if ($connection->getDatabasePlatform() instanceof MySqlPlatform) {
if (!Type::hasType('enum')) {
Type::addType('enum', StringType::class);
}
$connection->getDatabasePlatform()->registerDoctrineTypeMapping('enum', Types::STRING);
}
После этого я пытаюсь прочитать все доступные таблицы и перехватить любое исключение для типа, который не определен, определить его как строку, а затем повторить попытку:
$schemaManager = $this->connection->getSchemaManager();
do {
try {
return new Schema($schemaManager->listTables(), [], $schemaManager->createSchemaConfig());
} catch (Exception $exception) {
$hasErrors = true;
$message = $exception->getMessage();
$parts = explode('"', $message);
// convert any removed custom type to string
Type::addType($parts[1], StringType::class);
}
} while ($hasErrors);
Это вернет текущую схему БД. Из которого можно создать различие с новой схемой.