}', name: 'app_product')] public function __invoke(int $productId): Response { $product = Product::with([ 'price' => fn($query) => $query->orderBy('created_at', 'desc'), 'stock' => fn($query) => $query->orderBy('created_at', 'desc'), ])->find($productId); if (null === $product) { throw $this->createNotFoundException('Product not found'); } $priceList = $product->price()->pluck('price', 'created_at')->mapWithKeys(fn($price, $createdAt) => [explode(' ', $createdAt)[0] => $price])->toArray(); $stockList = $product->stock()->pluck('stock', 'created_at')->mapWithKeys(fn($stock, $createdAt) => [explode(' ', $createdAt)[0] => $stock])->toArray(); ksort($stockList); ksort($priceList); return $this->render('product.html.twig', [ 'product' => $product, 'price_list' => $this->prepareChartData($priceList), 'stock_list' => $this->prepareChartData($stockList), 'price_dates' => implode("','", $this->dateRange(array_key_first($priceList), array_key_last($priceList))), ]); } private function prepareChartData($set1): string { $dates = $this->dateRange(array_key_first($set1), array_key_last($set1)); $data = array_map(fn($date) => ['x' => $date, 'y' => $set1[$date] ?? null], $dates); $stringData = json_encode($data); return str_replace(['"x"', '"y"'], ['x', 'y'], $stringData); } private function dateRange($dateStart, $dateEnd): array { $from = new \DateTime($dateStart); $to = new \DateTime($dateEnd); $range = []; for ($date = clone $from; $date < $to; $date->modify('+1 day')) { $range[] = $date->format('Y-m-d'); } return $range; } }