使用Doctrine 2检查重复键

tom*_*tom 49 doctrine doctrine-orm

在进行刷新之前,是否有一种简单的方法可以检查Doctrine 2的重复键?

Don*_*sto 49

你可以这样抓住UniqueConstraintViolationException:

use Doctrine\DBAL\Exception\UniqueConstraintViolationException;

// ...

try {
   // ...
   $em->flush();
}
catch (UniqueConstraintViolationException $e) {
    // ....
}
Run Code Online (Sandbox Code Playgroud)

  • @JohnLinhart如果要继续使用em,则必须在catch块内重置它,例如通过`$ this-> getDoctrine()-> resetManager();` (2认同)

Pet*_*son 20

我使用此策略在flush()之后检查唯一约束,可能不是您想要的,但可能会帮助其他人.


当您调用flush()时,如果唯一约束失败,则抛出PDOException,代码为23000.

try {
    // ...
    $em->flush();
}
catch( \PDOException $e )
{
    if( $e->getCode() === '23000' )
    {
        echo $e->getMessage();

        // Will output an SQLSTATE[23000] message, similar to:
        // Integrity constraint violation: 1062 Duplicate entry 'x'
        // ... for key 'UNIQ_BB4A8E30E7927C74'
    }

    else throw $e;
}
Run Code Online (Sandbox Code Playgroud)

如果需要获取失败列的名称:

使用带前缀的名称创建表索引,例如.'独特_'

 * @Entity
 * @Table(name="table_name",
 *      uniqueConstraints={
 *          @UniqueConstraint(name="unique_name",columns={"name"}),
 *          @UniqueConstraint(name="unique_email",columns={"email"})
 *      })
Run Code Online (Sandbox Code Playgroud)

请勿在@Column定义中将列指定为唯一

这似乎用随机的一个覆盖索引名称......

 **ie.** Do not have 'unique=true' in your @Column definition
Run Code Online (Sandbox Code Playgroud)

重新生成表后(可能需要删除它并重建),您应该能够从异常消息中提取列名.

// ...
if( $e->getCode() === '23000' )
{
    if( \preg_match( "%key 'unique_(?P<key>.+)'%", $e->getMessage(), $match ) )
    {
        echo 'Unique constraint failed for key "' . $match[ 'key' ] . '"';
    }

    else throw $e;
}

else throw $e;
Run Code Online (Sandbox Code Playgroud)

不完美,但它有效......

  • 我想Doctrine不久前改变了异常处理.对于这种情况,我在\ Doctrine\DBAL\DBALException中得到一个PDOException.上面的代码类似于catch(\ Doctrine\DBAL\DBALException $ e){if($ e-> getPrevious() - > getCode()==='23000'){/*do stuff*/}}.需要注意的是,捕获此异常是处理高并发性的一些情况的唯一方法.一个选择查询验证它还不够 (4认同)

Elv*_*tti 7

如果在插入之前运行SELECT查询不是您想要的,则只能运行flush()并捕获异常.

在Doctrine DBAL 2.3中,您可以通过查看PDO异常错误代码(MySQL为23000,Postgres为23050)安全地理解唯一约束错误,该错误代码由Doctrine DBALException包装:

        try {
            $em->flush($user);
        } catch (\Doctrine\DBAL\DBALException $e) {
            if ($e->getPrevious() &&  0 === strpos($e->getPrevious()->getCode(), '23')) {
                throw new YourCustomException();
            }
        }
Run Code Online (Sandbox Code Playgroud)