在Symfony / Doctrine

时间:2017-07-18 09:01:23

标签: php mysql symfony doctrine-orm doctrine

我正在开展Symfony 2.8项目,允许注册用户管理联系人,文档,约会等。

现在我想实现一个允许用户重置/删除所有数据的功能。因此,用户帐户本身应保持不变,但应删除所有数据实体。

目前我使用Doctrine / ORM方法循环浏览所有实体并删除它们:

public function deleteAllData($user) {
    $this->currentBatch = 0;
    $this->deleteEntities('MyBundle:Contact', $user);
    $this->deleteEntities('MyBundle:Document', $user);
    ...
    $this->deleteEntities('MyBundle:...', $user);

    $this->flushIfNecessary(true);
}

private function deleteEntities($type, $user) {
   $repo = $this->em->getRepository($type);
   $entities = $repo->findByUser($user);

   foreach ($entities as $entity) {
       $repo->delete($entity);
       $this->flushIfNecessary();
   }
}

private function flushIfNecessary($force = false) {
    $this->currentBatch++;

    if ($force || $this->currentBatch % 100 == 0) {
        $this->em->flush();
        $this->em->clear();
    }
}

虽然这很好,但非常慢。使用不同的批量大小我能够加快一点进程,但删除大量条目仍需要很长时间。当然这是由于在后台完成的所有ORM处理。

使用简单的SQL查询会快得多:

private function deleteEntities($type, $user) {
   $tableName = null;
   $userId = $user->getId();

   switch ($type) {
       case 'MyBundle:Document':
           $tableName = 'document';
           break;
       ...
   }

   if ($tableName && $userId) {
       $this->em->getConnection()->query("
           DELETE FROM $tableName 
           WHERE user_id = '$userId'
       ");
   }
}

此解决方案也可以,但它需要知道内部数据库结构,例如不同实体的表名,userId字段的名称等。

当然获取这些信息并不是什么大问题,但对我而言,这个解决方案似乎并不像第一个那样干净。

有没有办法从Doctrine获取必要信息,同时仍在使用简单查询/绕过ORM

或者是否有更好的解决方案来完成这项工作?

1 个答案:

答案 0 :(得分:2)

由于object hydration,您的第一种方法很慢。您并不需要加载所有记录并将其转换为对象。您只需使用QueryBuilder

即可
$qb = $em->createQueryBuilder('c');
$qb->delete('MyBundle:Contact', 'c')
   ->where('c.user = :user')
   ->setParameter('user', $user)
   ->getQuery()
   ->execute()
;

DQL

$query = $em->createQuery(
              'DELETE MyBundle:Contact c 
               WHERE c.user = :user')
            ->setParameter('user', $user);
$query->execute();