баги с превью
This commit is contained in:
@@ -13,6 +13,9 @@ final class CatalogController
|
||||
{
|
||||
$categoryRepository = new CategoryRepository();
|
||||
$productRepository = new ProductRepository();
|
||||
$pagination = $this->paginationInput();
|
||||
$totalProducts = $productRepository->catalogTotal(true);
|
||||
$products = $productRepository->catalogPreview($pagination['limit'], $pagination['offset'], true);
|
||||
|
||||
view('catalog/index', [
|
||||
'title' => 'Каталог Рыбсток - рыба, морепродукты, мясо, сыры и продукты',
|
||||
@@ -24,7 +27,8 @@ final class CatalogController
|
||||
],
|
||||
'categories' => $categoryRepository->tree(),
|
||||
'currentCategory' => null,
|
||||
'products' => $productRepository->catalogPreview(48),
|
||||
'products' => $products,
|
||||
'pagination' => $this->paginationData('/catalog', $totalProducts, count($products), $pagination),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -48,6 +52,9 @@ final class CatalogController
|
||||
}
|
||||
|
||||
$categoryName = (string) $category['name'];
|
||||
$pagination = $this->paginationInput();
|
||||
$totalProducts = $productRepository->categoryTotal((int) $category['id'], true);
|
||||
$products = $productRepository->forCategory((int) $category['id'], $pagination['limit'], $pagination['offset'], true);
|
||||
|
||||
view('catalog/index', [
|
||||
'title' => $category['seo_title'] ?: $categoryName . ' - купить в Рыбсток с доставкой по Москве',
|
||||
@@ -56,7 +63,8 @@ final class CatalogController
|
||||
'breadcrumbs' => $categoryRepository->breadcrumbs((int) $category['id']),
|
||||
'categories' => $categoryRepository->tree(),
|
||||
'currentCategory' => $category,
|
||||
'products' => $productRepository->forCategory((int) $category['id'], 48),
|
||||
'products' => $products,
|
||||
'pagination' => $this->paginationData('/catalog/' . (string) $category['slug'], $totalProducts, count($products), $pagination),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -100,4 +108,58 @@ final class CatalogController
|
||||
'images' => $productRepository->imagesForProduct((int) $product['id']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{page:int, limit:int, offset:int, per_page:int, cumulative:bool}
|
||||
*/
|
||||
private function paginationInput(): array
|
||||
{
|
||||
$perPage = 48;
|
||||
$cumulativeLimit = isset($_GET['limit']) ? (int) $_GET['limit'] : 0;
|
||||
|
||||
if ($cumulativeLimit > 0) {
|
||||
$limit = max($perPage, min($cumulativeLimit, 5000));
|
||||
|
||||
return [
|
||||
'page' => 1,
|
||||
'limit' => $limit,
|
||||
'offset' => 0,
|
||||
'per_page' => $perPage,
|
||||
'cumulative' => true,
|
||||
];
|
||||
}
|
||||
|
||||
$page = max(1, (int) ($_GET['page'] ?? 1));
|
||||
|
||||
return [
|
||||
'page' => $page,
|
||||
'limit' => $perPage,
|
||||
'offset' => ($page - 1) * $perPage,
|
||||
'per_page' => $perPage,
|
||||
'cumulative' => false,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{page:int, limit:int, offset:int, per_page:int, cumulative:bool} $input
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function paginationData(string $basePath, int $total, int $currentCount, array $input): array
|
||||
{
|
||||
$shown = min($total, $input['offset'] + $currentCount);
|
||||
$nextLimit = min($total, max($shown, $input['limit']) + $input['per_page']);
|
||||
|
||||
return [
|
||||
'base_path' => $basePath,
|
||||
'total' => $total,
|
||||
'shown' => $shown,
|
||||
'page' => $input['page'],
|
||||
'pages' => max(1, (int) ceil($total / $input['per_page'])),
|
||||
'per_page' => $input['per_page'],
|
||||
'limit' => $input['limit'],
|
||||
'has_more' => $shown < $total,
|
||||
'next_limit' => $nextLimit,
|
||||
'cumulative' => $input['cumulative'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,15 @@ final class ProductRepository extends BaseRepository
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function catalogPreview(int $limit = 24): array
|
||||
public function catalogPreview(int $limit = 24, int $offset = 0, bool $includeHidden = false): array
|
||||
{
|
||||
$limit = max(1, min($limit, 60));
|
||||
$limit = max(1, min($limit, 5000));
|
||||
$offset = max(0, $offset);
|
||||
$sql = $this->previewSelectSql(
|
||||
'ORDER BY p.sort_order, p.name',
|
||||
$limit
|
||||
'ORDER BY (p.is_published = 0 OR p.is_available = 0), p.sort_order, p.name',
|
||||
$limit,
|
||||
$offset,
|
||||
$includeHidden
|
||||
);
|
||||
|
||||
$statement = $this->pdo()->query($sql);
|
||||
@@ -40,12 +43,21 @@ final class ProductRepository extends BaseRepository
|
||||
return $this->preparePreviewProducts($statement->fetchAll());
|
||||
}
|
||||
|
||||
public function catalogTotal(bool $includeHidden = false): int
|
||||
{
|
||||
$statusSql = $includeHidden ? '' : ' AND p.is_published = 1 AND p.is_available = 1';
|
||||
$statement = $this->pdo()->query('SELECT COUNT(*) FROM products p WHERE 1=1' . $statusSql);
|
||||
|
||||
return (int) $statement->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function forCategory(int $categoryId, int $limit = 48): array
|
||||
public function forCategory(int $categoryId, int $limit = 48, int $offset = 0, bool $includeHidden = false): array
|
||||
{
|
||||
$limit = max(1, min($limit, 96));
|
||||
$limit = max(1, min($limit, 5000));
|
||||
$offset = max(0, $offset);
|
||||
$categoryIds = (new CategoryRepository())->descendantIds($categoryId);
|
||||
$categoryParents = $this->categoryParentMap();
|
||||
$requestedRootId = $this->rootCategoryId($categoryId, $categoryParents);
|
||||
@@ -69,8 +81,10 @@ final class ProductRepository extends BaseRepository
|
||||
)
|
||||
)
|
||||
)
|
||||
ORDER BY p.sort_order, p.name',
|
||||
5000
|
||||
ORDER BY (p.is_published = 0 OR p.is_available = 0), p.sort_order, p.name',
|
||||
5000,
|
||||
0,
|
||||
$includeHidden
|
||||
);
|
||||
|
||||
$statement = $this->pdo()->prepare($sql);
|
||||
@@ -94,13 +108,22 @@ final class ProductRepository extends BaseRepository
|
||||
) {
|
||||
$filtered[] = $product;
|
||||
}
|
||||
|
||||
if (count($filtered) >= $limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
usort($filtered, static function (array $left, array $right): int {
|
||||
$leftUnavailable = ((int) ($left['is_published'] ?? 1) === 0 || (int) ($left['is_available'] ?? 1) === 0) ? 1 : 0;
|
||||
$rightUnavailable = ((int) ($right['is_published'] ?? 1) === 0 || (int) ($right['is_available'] ?? 1) === 0) ? 1 : 0;
|
||||
|
||||
return [$leftUnavailable, (int) ($left['sort_order'] ?? 0), (string) ($left['name'] ?? '')]
|
||||
<=> [$rightUnavailable, (int) ($right['sort_order'] ?? 0), (string) ($right['name'] ?? '')];
|
||||
});
|
||||
|
||||
return array_slice($filtered, $offset, $limit);
|
||||
}
|
||||
|
||||
public function categoryTotal(int $categoryId, bool $includeHidden = false): int
|
||||
{
|
||||
return count($this->forCategory($categoryId, 5000, 0, $includeHidden));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,7 +275,7 @@ final class ProductRepository extends BaseRepository
|
||||
}
|
||||
}
|
||||
|
||||
private function previewSelectSql(string $tailSql, int $limit): string
|
||||
private function previewSelectSql(string $tailSql, int $limit, int $offset = 0, bool $includeHidden = false): string
|
||||
{
|
||||
return 'SELECT
|
||||
p.id,
|
||||
@@ -264,12 +287,15 @@ final class ProductRepository extends BaseRepository
|
||||
p.seo_description,
|
||||
p.seo_keywords,
|
||||
p.category_id,
|
||||
p.is_published,
|
||||
p.is_available,
|
||||
c.name AS category_name,
|
||||
c.slug AS category_slug,
|
||||
p.main_image_path,
|
||||
p.base_unit,
|
||||
p.package_display_mode,
|
||||
p.sales_count,
|
||||
p.sort_order,
|
||||
v.id AS variant_id,
|
||||
v.name AS variant_name,
|
||||
v.unit,
|
||||
@@ -291,10 +317,10 @@ final class ProductRepository extends BaseRepository
|
||||
ORDER BY pv.is_default DESC, pv.sort_order, pv.id
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE p.is_published = 1
|
||||
AND p.is_available = 1
|
||||
WHERE 1=1
|
||||
' . ($includeHidden ? '' : 'AND p.is_published = 1 AND p.is_available = 1') . '
|
||||
' . $tailSql . '
|
||||
LIMIT ' . $limit;
|
||||
LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user