If you're doing a batch-processing job such as batch-update, batch-delete, list then make sure you're using Query#iterate() in your QueryBuilder to avoid loading the whole result into memory at once. For more info, click here. Example below does batch-update.


Repository


use Doctrine\ORM\Internal\Hydration\IterableResult;

class UserProductRepository extends EntityRepository
{
/**
* @return IterableResult
**/
public function findProductsByUserIdAndProductNames($userId, array $productNames = [])
{
$dql = "SELECT up
FROM Application\ProductBundle\Entity\UserProduct up
WHERE up.user = :userId AND up.productName IN (:productNames)";

return $this->getEntityManager()
->createQuery($dql)
->setParameters(['userId' => $userId, 'productNames' => $productNames])
->iterate();
}
}

Service


use Doctrine\ORM\Internal\Hydration\IterableResult;

class UserProductService
{
...
...

public function getUserProducts()
{
$userId = 123;
$productNames = ['sony', 'samsung', 'htc'];

$userProducts = $this->userProductRepository->findProductsByUserIdAndProductNames(
$userId,
productNames
);

if (count($userProducts)) {
$batchSize = 20;
foreach ($userProducts as $userProduct) {
$userProduct[0]->setSell(new DateTime());

--$batchSize;
if ($batchSize === 0) {
$this->em->flush();
$this->em->clear();
$batchSize = 20;
}
}

$this->em->flush();
$this->em->clear();
}
}
}