TL; DR: как использовать Doctrine\ORM\EntityManager::clear()
с помощью $entityName
?
Допустим, у меня есть Post
сущность с Author
и Category
, Я хочу добавить посты в свою базу данных (произвольно, из CSV-файла или чего-то еще). У меня проблемы с производительностью при добавлении данных. Использование памяти увеличивается, и это замедляет процесс, но я не знаю, как (частично) я могу очистить EntityManager.
Это цикл, где происходит волшебство:
$batchSize = 250;
foreach ($posts as $post) {
//$post['author'] is instance of Acme\BlogBundle\Author
$post = new Post($post['author'], $post['category']);
$em->persist($post);
if ($i % $batchSize == 0) {
$entity = '??';
$em->flush();
$em->clear($entityName);
gc_collect_cycles();
}
}
Это кидает Doctrine\ORM\ORMInvalidArgumentException: A new entity was found through the relationship Acme\BlogBundle\Post#author
, Это правильно, так как Author
управляется EntityManager, который был очищен.
Это понятный метод:
namespace Doctrine\ORM;
class EntityManager implements EntityManagerInterface {
/**
* Clears the EntityManager. All entities that are currently managed
* by this EntityManager become detached.
*
* @param string|null $entityName if given, only entities of this type will get detached
*
* @return void
*/
public function clear($entityName = null)
{
$this->unitOfWork->clear($entityName);
}
}
Поскольку я хочу очистить сообщения, но хочу сохранить типы сущностей Автор и Категория, я ожидал, что $entityName = 'Acme\BlogBundle\Entity\Post'
, $entityName = get_class($post);
или же $entityName = Acme\BlogBundle\Entity\Post::class
поможет, но, к сожалению, ничего не понятно.
Как правильно использовать этот параметр?
Вы можете передать имя класса как entityName в метод очистки entitymanager, но оно должно быть точно таким же, как единица работы доктрины, хранящаяся в его карте идентификации. Чтобы получить правильный, вы должны сделать что-то вроде этого:
$classMetadata = $em->getClassMetadata(get_class($post));
$entityName = $classMetadata->rootEntityName;
Других решений пока нет …