In my symfony application, I am generating a form in order to parameter some ingredients. I now face the situation where users start managing thousands of ingredients.
With only 200 ingredients, the php memory usage goes above the max 120Mo.
The following shows that the action stats with a usage of 50Mo and that creating the form alone takes 40Mo. It crashes if I try to render the view.
What can I do to avoid forms to take so much memory ?
My controller action :
/**
* @Route("/set_ingredient_stock", name="set_ingredient_stock")
* @Method({"PUT","GET"})
* @Template(":FoodAnalytics/UserIngredient:set_ingredient_stock.html.twig")
* @param Request $request
* @Security("is_granted('organizer')")
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function setIngredientStockAction(Request $request)
{
r('init : ' . ceil(memory_get_usage() / 1000000));
$userIngredientManager = $this->get('user_ingredient_manager');
r('manager : ' . ceil(memory_get_usage() / 1000000));
/** @var User $user */
$user = $this->getDoctrine()->getRepository('AppBundle:User\User')->findUserWithUserIngredients($this->getPortfolioUser());
r('user : ' . ceil(memory_get_usage() / 1000000));
$setStockIngredientForm = $userIngredientManager->getSetIngredientStockForm($user);
r('form : ' . ceil(memory_get_usage() / 1000000));
if ($request->getMethod()=='PUT')
{
$formManager = $this->get('form_manager');
if ($formManager->handleRequestAndFlush($setStockIngredientForm, $user))
{
$this->addSuccess("Le stock d'ingrédients à été mis à jour");
return $this->redirectToRoute('set_ingredient_stock');
}
$this->addInvalidFormMessage();
}
$nonExecutedTasks = $this->getDoctrine()->getRepository('AppBundle:FoodAnalytics\Task')->getNonExecutedTasksQueryBuilder($this->getPortfolioUser())->select('COUNT(t)')->getQuery()->getSingleScalarResult();
$nonReceivedOrders = $this->getDoctrine()->getRepository('AppBundle:MarketPlace\Order')->getNonReceivedOrdersQueryBuilder($this->getPortfolioUser())->select('COUNT(o)')->getQuery()->getSingleScalarResult();;
$horizon = $user->getParameter(User::STOCK_HORIZON) ?: 7;
r('small_variables : ' . ceil(memory_get_usage() / 1000000));
$userIngredients = $this->getDoctrine()->getRepository('AppBundle:FoodAnalytics\UserIngredient')->getUserIngredientsWithJoinsIndexedByProductIds($this->getPortfolioUser());
r('user_ingredients : ' . ceil(memory_get_usage() / 1000000));
$stocks = $userIngredientManager->getUserIngredientStocks($userIngredients, $horizon);
~r('stocks : ' . ceil(memory_get_usage() / 1000000));
return array(
'set_stock_ingredient_form' => $setStockIngredientForm->createView(),
'non_executed_tasks' => $nonExecutedTasks,
'non_received_orders' => $nonReceivedOrders,
'stocks' => $stocks,
'horizon' => $horizon
);
}
The dumps:
init : 50
manager : 51
user : 61
form : 100
small_variables : 100
user_ingredients : 101
stocks : 105
EDIT : The methods that generates the form just created a regular symfony form attached to the user who owns a collection of userIngredients generated by another type. There are 3 fields per userIngredients.