ORM Propel2 в числе прочего умеет проводить сравнение схемы проекта и текущей живой базы, и по результатам создавать миграции. Это работает замечательно в более старых и популярных версиях MySQL, например 5.5 но внезапно перестало в новой 5.7

После ковыряний в мануалах MySQL нашлось такое:

Prior to MySQL 5.6.6, adding and dropping a foreign key in the same ALTER TABLE statement may be problematic in some cases and is therefore unsupported. Separate statements should be used for each operation. As of MySQL 5.6.6, adding and dropping a foreign key in the same ALTER TABLE statement is supported for ALTER TABLE ... ALGORITHM=INPLACE but remains unsupported for ALTER TABLE ... ALGORITHM=COPY.

In MySQL 5.7, the server prohibits changes to foreign key columns with the potential to cause loss of referential integrity. A workaround is to use ALTER TABLE ... DROP FOREIGN KEY before changing the column definition and ALTER TABLE ... ADD FOREIGN KEY afterward.

Миграции Propel как раз формируют один большой ALTER TABLE что и не нравится новому MySQL, решение - разделить ALTER на два. Поскольку ORM весьма гибкий - на коленке родился такой Provider

<?php

use Propel\Generator\Model\Diff\TableDiff;
use Propel\Generator\Platform\MysqlPlatform as PropelMysqlPlatform;

/**
 * MySql PlatformInterface implementation for Mysql5.7
 *
 * @author Stas Dovgodko
 */
class MysqlPlatform extends PropelMysqlPlatform
{


    public function getModifyTableDDL(TableDiff $tableDiff)
    {
        $alterTableStatements '';

        $toTable $tableDiff->getToTable();

        // drop indices, foreign keys
        foreach ($tableDiff->getRemovedFks() as $fk) {
            $alterTableStatements .= $this->getDropForeignKeyDDL($fk);
        }
        foreach ($tableDiff->getModifiedFks() as $fkModification) {
            list($fromFk) = $fkModification;
            $alterTableStatements .= $this->getDropForeignKeyDDL($fromFk);
        }
        foreach ($tableDiff->getRemovedIndices() as $index) {
            $alterTableStatements .= $this->getDropIndexDDL($index);
        }
        foreach ($tableDiff->getModifiedIndices() as $indexModification) {
            list($fromIndex) = $indexModification;
            $alterTableStatements .= $this->getDropIndexDDL($fromIndex);
        }

        // alter table structure
        if ($tableDiff->hasModifiedPk()) {
            $alterTableStatements .= $this->getDropPrimaryKeyDDL($tableDiff->getFromTable());
        }
        foreach ($tableDiff->getRenamedColumns() as $columnRenaming) {
            $alterTableStatements .= $this->getRenameColumnDDL($columnRenaming[0]$columnRenaming[1]);
        }
        if ($modifiedColumns $tableDiff->getModifiedColumns()) {
            $alterTableStatements .= $this->getModifyColumnsDDL($modifiedColumns);
        }
        if ($addedColumns $tableDiff->getAddedColumns()) {
            $alterTableStatements .= $this->getAddColumnsDDL($addedColumns);
        }
        foreach ($tableDiff->getRemovedColumns() as $column) {
            $alterTableStatements .= $this->getRemoveColumnDDL($column);
        }

        // add new indices and foreign keys
        if ($tableDiff->hasModifiedPk()) {
            $alterTableStatements .= $this->getAddPrimaryKeyDDL($tableDiff->getToTable());
        }

        // create indices, foreign keys
        foreach ($tableDiff->getModifiedIndices() as $indexModification) {
            list($oldIndex$toIndex) = $indexModification;
            $alterTableStatements .= $this->getAddIndexDDL($toIndex);
        }
        foreach ($tableDiff->getAddedIndices() as $index) {
            $alterTableStatements .= $this->getAddIndexDDL($index);
        }
        foreach ($tableDiff->getModifiedFks() as $fkModification) {
            list($toFk) = $fkModification;
            $alterTableStatements .= $this->getAddForeignKeyDDL($toFk);
        }
        foreach ($tableDiff->getAddedFks() as $fk) {
            $alterTableStatements .= $this->getAddForeignKeyDDL($fk);
        }


        $ret '';
        if (trim($alterTableStatements)) {
            //merge all changes into one command. This prevents https://github.com/propelorm/Propel2/issues/1115

            $changes = explode(';'$alterTableStatements);
            $dropFragments = []$changeFragments = [];
            foreach ($changes as $change) {
                if (trim($change)) {
                    $part_sql = preg_replace(
                        sprintf('/ALTER TABLE %s /'$this->quoteIdentifier($toTable->getName())),
                        "\n\n  ",
                        trim($change)
                    );

                    if (strpos($part_sql'DROP FOREIGN KEY') !== false) {
                        $dropFragments[] = $part_sql;
                    else {
                        $changeFragments[] = $part_sql;
                    }
                }
            }

            if ($dropFragments) {
                $ret .= sprintf("
ALTER TABLE %s%s;
",
                    $this->quoteIdentifier($toTable->getName())implode(','$dropFragments)
                );
            }

            $ret .= sprintf("
ALTER TABLE %s%s;
",
                $this->quoteIdentifier($toTable->getName())implode(','$changeFragments)
            );
        }

        return $ret;
    }
}

Как подключить свой провайдер - почитайте в мане ) Бага засабмичена разработчикам Propel и надеюсь более цивилизованное решение появится 

UPD. Разработчики Propel по моему репорту багу исправили, потому все выше не актуально - просто обновите propel/propel