203 lines
6.7 KiB
PHP
203 lines
6.7 KiB
PHP
<?php
|
|
/**
|
|
* Copyright seit 2024 Webshop System
|
|
*
|
|
* Frontend-Such-Controller für das Webshop-System
|
|
*
|
|
* @author Webshop System
|
|
* @license GPL v3
|
|
*/
|
|
|
|
namespace App\Front\Controllers;
|
|
|
|
use Doctrine\DBAL\DriverManager;
|
|
use Doctrine\DBAL\Exception;
|
|
|
|
class SearchController
|
|
{
|
|
public function index()
|
|
{
|
|
$query = $_GET['q'] ?? '';
|
|
$category = $_GET['category'] ?? '';
|
|
$sort = $_GET['sort'] ?? 'name';
|
|
$order = $_GET['order'] ?? 'asc';
|
|
$minPrice = $_GET['min_price'] ?? '';
|
|
$maxPrice = $_GET['max_price'] ?? '';
|
|
$page = max(1, intval($_GET['page'] ?? 1));
|
|
$perPage = 12;
|
|
|
|
// DB-Verbindung herstellen
|
|
$connectionParams = [
|
|
'dbname' => getenv('DB_DATABASE') ?: 'freeshop',
|
|
'user' => getenv('DB_USERNAME') ?: 'freeshop_user',
|
|
'password' => getenv('DB_PASSWORD') ?: 'freeshop_password',
|
|
'host' => getenv('DB_HOST') ?: 'db',
|
|
'driver' => 'pdo_mysql',
|
|
'port' => getenv('DB_PORT') ?: 3306,
|
|
'charset' => 'utf8mb4',
|
|
];
|
|
|
|
try {
|
|
$conn = DriverManager::getConnection($connectionParams);
|
|
|
|
// Suchbedingungen aufbauen
|
|
$whereConditions = ['p.active = 1'];
|
|
$params = [];
|
|
|
|
if (!empty($query)) {
|
|
$whereConditions[] = '(p.name LIKE ? OR p.description LIKE ?)';
|
|
$params[] = '%' . $query . '%';
|
|
$params[] = '%' . $query . '%';
|
|
}
|
|
|
|
if (!empty($category)) {
|
|
$whereConditions[] = 'p.category_id = ?';
|
|
$params[] = $category;
|
|
}
|
|
|
|
if (!empty($minPrice)) {
|
|
$whereConditions[] = 'p.price >= ?';
|
|
$params[] = $minPrice;
|
|
}
|
|
|
|
if (!empty($maxPrice)) {
|
|
$whereConditions[] = 'p.price <= ?';
|
|
$params[] = $maxPrice;
|
|
}
|
|
|
|
$whereClause = implode(' AND ', $whereConditions);
|
|
|
|
// Gesamtanzahl für Pagination
|
|
$countSql = "
|
|
SELECT COUNT(*) as total
|
|
FROM ws_product p
|
|
LEFT JOIN ws_category c ON p.category_id = c.id
|
|
WHERE $whereClause
|
|
";
|
|
|
|
$stmt = $conn->prepare($countSql);
|
|
$stmt->execute($params);
|
|
$totalCount = $stmt->fetchAssociative()['total'];
|
|
|
|
// Produkte laden
|
|
$offset = ($page - 1) * $perPage;
|
|
$sql = "
|
|
SELECT p.*, c.name as category_name
|
|
FROM ws_product p
|
|
LEFT JOIN ws_category c ON p.category_id = c.id
|
|
WHERE $whereClause
|
|
ORDER BY p.$sort $order
|
|
LIMIT $perPage OFFSET $offset
|
|
";
|
|
|
|
$stmt = $conn->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
$products = [];
|
|
while ($row = $stmt->fetchAssociative()) {
|
|
$products[] = $row;
|
|
}
|
|
|
|
// Kategorien für Filter laden
|
|
$stmt = $conn->prepare('SELECT id, name FROM ws_category WHERE active = 1 ORDER BY name');
|
|
$stmt->execute();
|
|
|
|
$categories = [];
|
|
while ($row = $stmt->fetchAssociative()) {
|
|
$categories[] = $row;
|
|
}
|
|
|
|
// Pagination berechnen
|
|
$totalPages = ceil($totalCount / $perPage);
|
|
$pagination = [
|
|
'current' => $page,
|
|
'total' => $totalPages,
|
|
'per_page' => $perPage,
|
|
'total_count' => $totalCount
|
|
];
|
|
|
|
$this->render('front/search/index.html.twig', [
|
|
'title' => 'Webshop - Suche',
|
|
'query' => $query,
|
|
'products' => $products,
|
|
'categories' => $categories,
|
|
'pagination' => $pagination,
|
|
'filters' => [
|
|
'category' => $category,
|
|
'sort' => $sort,
|
|
'order' => $order,
|
|
'min_price' => $minPrice,
|
|
'max_price' => $maxPrice
|
|
]
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
$this->render('front/search/index.html.twig', [
|
|
'title' => 'Webshop - Suche',
|
|
'query' => $query,
|
|
'products' => [],
|
|
'categories' => [],
|
|
'pagination' => ['current' => 1, 'total' => 1, 'per_page' => 12, 'total_count' => 0],
|
|
'filters' => [],
|
|
'error' => 'Datenbankfehler: ' . $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function ajax()
|
|
{
|
|
// AJAX-Suche für Live-Suggestions
|
|
$query = $_GET['q'] ?? '';
|
|
|
|
if (empty($query) || strlen($query) < 2) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['products' => []]);
|
|
return;
|
|
}
|
|
|
|
$connectionParams = [
|
|
'dbname' => getenv('DB_DATABASE') ?: 'freeshop',
|
|
'user' => getenv('DB_USERNAME') ?: 'freeshop_user',
|
|
'password' => getenv('DB_PASSWORD') ?: 'freeshop_password',
|
|
'host' => getenv('DB_HOST') ?: 'db',
|
|
'driver' => 'pdo_mysql',
|
|
'port' => getenv('DB_PORT') ?: 3306,
|
|
'charset' => 'utf8mb4',
|
|
];
|
|
|
|
try {
|
|
$conn = DriverManager::getConnection($connectionParams);
|
|
|
|
$sql = "
|
|
SELECT p.id, p.name, p.price, p.image, c.name as category_name
|
|
FROM ws_product p
|
|
LEFT JOIN ws_category c ON p.category_id = c.id
|
|
WHERE p.active = 1 AND (p.name LIKE ? OR p.description LIKE ?)
|
|
ORDER BY p.name ASC
|
|
LIMIT 5
|
|
";
|
|
|
|
$stmt = $conn->prepare($sql);
|
|
$stmt->execute(['%' . $query . '%', '%' . $query . '%']);
|
|
|
|
$products = [];
|
|
while ($row = $stmt->fetchAssociative()) {
|
|
$products[] = $row;
|
|
}
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['products' => $products]);
|
|
|
|
} catch (Exception $e) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['products' => [], 'error' => $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
protected function render($template, $data = [])
|
|
{
|
|
// Einfache Template-Engine (später durch Twig ersetzen)
|
|
extract($data);
|
|
include __DIR__ . '/../../templates/' . $template;
|
|
}
|
|
}
|