''"; } if ($with_image) { $where .= " AND hero_image IS NOT NULL AND hero_image <> ''"; } if (valid_date($desde)) { $where .= " AND (updated_at IS NULL OR updated_at >= ?)"; $params[] = $desde . ' 00:00:00'; $types .= 's'; } if (valid_date($hasta)) { $where .= " AND (updated_at IS NULL OR updated_at <= ?)"; $params[] = $hasta . ' 23:59:59'; $types .= 's'; } // Orden switch ($sort) { case 'alfa': $orderSql = "titulo ASC, id DESC"; break; case 'recientes': default: $orderSql = "COALESCE(updated_at, '1970-01-01 00:00:00') DESC, id DESC"; $sort = 'recientes'; } // ---- Total para paginación ---- $sqlCount = "SELECT COUNT(*) AS total FROM landing_pages WHERE $where"; $stmt = $conn->prepare($sqlCount); if ($types) { $stmt->bind_param($types, ...$params); } $stmt->execute(); $total = (int)($stmt->get_result()->fetch_assoc()['total'] ?? 0); $stmt->close(); $total_pages = max(1, (int)ceil($total / $pageSize)); if ($page > $total_pages) { $page = $total_pages; $offset = ($page - 1) * $pageSize; } // ---- Consulta principal ---- $sql = "SELECT id, titulo, slug, hero_image, meta_desc, updated_at, game_url FROM landing_pages WHERE $where ORDER BY $orderSql LIMIT ? OFFSET ?"; $stmt = $conn->prepare($sql); // Bind evitando “positional after unpacking” $limitVal = $pageSize; $offsetVal = $offset; if ($types) { $types2 = $types . 'ii'; $bindValues = array_merge($params, [$limitVal, $offsetVal]); $stmt->bind_param($types2, ...$bindValues); } else { $stmt->bind_param('ii', $limitVal, $offsetVal); } $stmt->execute(); $rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); $stmt->close(); // Fallback de imagen $fallbackImg = 'https://picsum.photos/seed/landings/800/450'; // Helper para mantener parámetros en paginación $baseParams = $_GET; unset($baseParams['page']); $base = $_SERVER['PHP_SELF'].'?'.http_build_query($baseParams); $prev = max(1, $page-1); $next = min($total_pages, $page+1); ?>