为什么Doctrine 2迁移在Symfony项目中无声地失败?

时间:2016-09-08 15:46:00

标签: mysql doctrine-orm doctrine symfony

我的问题是:

  1. 为什么Symfony中的doctrine migration命令无法报告我在下面列出的SQL错误
  2. 如何让它报告此类错误,而不是看起来已成功。
  3. 要明确 - 我知道为什么SQL本身会失败。这很容易。失败的沉默本质就是问题。

    我在PHP文件中有一个学说迁移,如下所示:

    [... boilerplate ...]
    
    public function up(Schema $schema)
    {
        $this->addSql(<<<SQL
    
        -- This runs fine
        CREATE TABLE [[redacted - this part runs fine]];
    
        -- This fails with a unique key constraint
        INSERT INTO `users_orgs` (`org_id`, `user_id`, `active`)
        SELECT `oid`, `uid`, 1 as `active` FROM `orgs`;
    
        -- Never gets here
        ALTER TABLE `orgs` CHANGE `uid` `primary_user_id` int(11) unsigned DEFAULT NULL;
    
    SQL
        );
    }
    
    [... boilerplate ...]
    

    实际结果

    由于一个独特的键约束(例如&#34;重复输入&#39; 6-3&#39;用于键&#39; PRIMARY&#39;&#39; - 它&#39;复合键)但未报告错误。我知道它失败了,因为它很清楚最后的语句永远不会运行,如果我手动运行违规语句,它就会失败。我跑的时候:

    ./bin/console doctrine:migrations:migrate
    

    从我的Symfony应用程序中调用doctrine迁移代码,它报告:

    $ ./bin/console doctrine:migrations:migrate
    
                    Application Migrations                    
    
    
    WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)y
    Migrating up to 20160822090333 from 20160820232349
    
      ++ migrating 20160822090333
    
         -> CREATE TABLE [[redacted - works fine]];
    
    INSERT INTO `users_orgs` (`org_id`, `user_id`, `active`)
    SELECT `oid`, `uid`, 1 as `active` FROM `orgs`;
    
    ALTER TABLE `orgs` CHANGE `uid` `primary_user_id` int(11) unsigned  DEFAULT NULL;
    
    
      ++ migrated (0.1s)
    
      ------------------------
    
      ++ finished in 0.1s
      ++ 1 migrations executed
      ++ 1 sql queries
    

    预期结果

    我希望它报告错误。作为测试,我创建了一个带有主键的单列表。我尝试插入一条记录,该记录会在迁移中生成唯一的约束违规。当我执行迁移时,学说报告了这个:

    Migration 20160908112332 failed during Execution. Error An exception occurred while executing '        insert into FOO values (1)':
    
    SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'
    

    我的配置

    这是我安装的内容(通过作曲家):

    doctrine/annotations                 v1.2.7             Docblock Annotations Parser
    doctrine/cache                       v1.6.0             Caching library offering an object-oriented API for many cache backends
    doctrine/collections                 v1.3.0             Collections Abstraction library
    doctrine/common                      v2.6.1             Common Library for Doctrine projects
    doctrine/dbal                        v2.5.4             Database Abstraction Layer
    doctrine/doctrine-bundle             1.6.4              Symfony DoctrineBundle
    doctrine/doctrine-cache-bundle       1.3.0              Symfony Bundle for Doctrine Cache
    doctrine/doctrine-migrations-bundle  v1.2.0             Symfony DoctrineMigrationsBundle
    doctrine/inflector                   v1.1.0             Common String Manipulations with regard to casing and singular/plural rules.
    doctrine/lexer                       v1.0.1             Base library for a lexer that can be used in Top-Down, Recursive Descent Pa...
    doctrine/migrations                  1.4.1              Database Schema migrations using Doctrine DBAL
    symfony/symfony                      v3.0.9
    

    MySQL的:

    mysql Ver 14.14 Distrib 5.6.27, for Linux (x86_64) using  EditLine wrapper
    

    我尝试了什么

    我搜索了#34;沉默的教条失败&#34;,&#34;沉默的教条迁移失败&#34;谷歌和这里,我没有看到任何东西。任何见解都将不胜感激。

1 个答案:

答案 0 :(得分:2)

它将与在一个查询中执行多个语句有关。

Doctrine migrations documentation说:

  

在内部,addSql调用将传递给executeQuery

我尝试用/** @var \Doctrine\DBAL\Connection $connection */ $connection = $this->getDoctrine()->getConnection(); $createTable = "CREATE TABLE test (org_id int not null, user_id int not null, PRIMARY KEY(org_id, user_id));"; $insert = "INSERT INTO test (org_id, user_id) VALUES (1, 1);"; // this will create the table (if doesn't exist) and add a record, the second insert silently fails. $connection->executeQuery("{$createTable}{$insert}{$insert}"); 执行多个语句,其行为方式与您相同。 (我有不同的软件包版本,但只是补丁级别不同)。当我有多个语句时,如果第一个语句失败,它只会抛出一个错误。

考虑这个例子:

// ... same as above except for executeQuery
$connection->executeQuery("{$createTable}");
$connection->executeQuery("{$insert}");
$connection->executeQuery("{$insert}"); // <- duplicate key error is thrown

可是:

addSql()

我想要达到的目的是为每个陈述使用单独的[... boilerplate ...] public function up(Schema $schema) { $this->addSql("CREATE TABLE [[redacted - this part runs fine]];"); $this->addSql("INSERT INTO `users_orgs` (`org_id`, `user_id`, `active`) SELECT `oid`, `uid`, 1 as `active` FROM `orgs`;"); $this->addSql("ALTER TABLE `orgs` CHANGE `uid` `primary_user_id` int(11) unsigned DEFAULT NULL;"); } [... boilerplate ...] 语句。

{{1}}