我正在开展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
?
或者是否有更好的解决方案来完成这项工作?
答案 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();