233 lines
10 KiB
PHP
233 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* @file attrbar.php
|
|
* @brief Inkludierte Datei für die Darstellung und Verarbeitung der Attribut-Filterleiste (attrbar).
|
|
*
|
|
* @details Diese Datei generiert eine dynamische Filterleiste basierend auf der aktuell
|
|
* ausgewählten Produktkategorie. Sie stellt eine Verbindung zur Datenbank her, ruft
|
|
* zugehörige Attribute ab und generiert ein HTML-Formular zur Filterung der Produkte nach spezifischen Attributen.
|
|
* Das Senden des Formulars geschieht automatisch bei einer Änderung eines Auswahlfeldes (onchange) oder über
|
|
* einen Button (falls JavaScript deaktiviert ist).
|
|
*/
|
|
|
|
// Binden der benötigten Bootstrap-Datei ein, welche grundlegende Konfigurationen und Hilfsfunktionen zur Verfügung stellt.
|
|
require_once __DIR__ . '/lib/bootstrap.php';
|
|
|
|
/**
|
|
* @var mysqli $conn
|
|
* @brief Stellt eine Verbindung zur Datenbank her.
|
|
*/
|
|
$conn = db_connect();
|
|
|
|
/**
|
|
* @var string $currentCategory
|
|
* @brief Speichert die aktuell gesetzte Kategorie aus dem GET-Parameter. Standardwert ist 'all'.
|
|
*/
|
|
$currentCategory = isset($_GET['category']) ? $_GET['category'] : 'all';
|
|
|
|
/**
|
|
* @var int|null $catId
|
|
* @brief Beinhaltet die numerische ID der aktuellen Kategorie zur Verwendung in Datenbankabfragen.
|
|
*/
|
|
$catId = null;
|
|
|
|
/**
|
|
* @var array $categoriesConfig
|
|
* @brief Ein Mapping-Array, welches Kategorie-Slugs (Strings) auf deren entsprechende Datenbank-IDs (Integer) mappt.
|
|
*/
|
|
$categoriesConfig = [
|
|
'iphone' => 20,
|
|
'ipad' => 21,
|
|
'macbook' => 22,
|
|
'airpods' => 23,
|
|
'accessories' => 24,
|
|
];
|
|
|
|
// Überprüfen, ob die gewählte Kategorie im Konfigurations-Array vorhanden ist.
|
|
if (isset($categoriesConfig[$currentCategory])) {
|
|
// Falls vorhanden, wird die entsprechende Kategorie-ID für weitere Abfragen gesetzt.
|
|
$catId = $categoriesConfig[$currentCategory];
|
|
}
|
|
|
|
/**
|
|
* @var array $attributes
|
|
* @brief Speichert die verfügbaren Attribute (z.B. Farbe, Speichergröße) für die selektierte Kategorie.
|
|
*/
|
|
$attributes = [];
|
|
|
|
// Attribute nur laden, wenn eine gültige Kategorie-ID gefunden wurde.
|
|
if ($catId) {
|
|
/**
|
|
* @details Holt alle Attribute, die mit der aktiven Kategorie verknüpft sind,
|
|
* sortiert nach ihrem Namen, um eine geordnete Filterliste anzuzeigen.
|
|
*/
|
|
$stmtAttr = $conn->prepare("
|
|
SELECT a.attributeID, a.name, a.unit, a.dataType
|
|
FROM attributes a
|
|
JOIN categoryAttributes ca ON a.attributeID = ca.attributeID
|
|
WHERE ca.categoryID = ?
|
|
ORDER BY a.name
|
|
");
|
|
$stmtAttr->bind_param("i", $catId);
|
|
$stmtAttr->execute();
|
|
$resAttr = $stmtAttr->get_result();
|
|
|
|
// Iteriere über das Result-Set und speichere jedes gefundene Attribut im $attributes-Array.
|
|
while ($row = $resAttr->fetch_assoc()) {
|
|
$attributes[] = $row;
|
|
}
|
|
// Statement schließen, um Ressourcen freizugeben.
|
|
$stmtAttr->close();
|
|
}
|
|
?>
|
|
|
|
<?php
|
|
// Wenn Attribute existieren, wird der HTML-Container für die Filterleiste gerendert.
|
|
if (!empty($attributes)): ?>
|
|
<div class="attrbar" aria-label="Attributfilter">
|
|
<div class="attrbar__inner container">
|
|
<!-- Das Formular sendet Daten per GET an die index.php für die Filterung -->
|
|
<form action="index.php" method="GET" class="attr-filter-form">
|
|
|
|
<?php
|
|
// Aktuelle Kategorie-ID im Formular versteckt mitsenden, damit man in der Kategorie bleibt.
|
|
if (isset($_GET['category'])): ?>
|
|
<input type="hidden" name="category" value="<?= htmlspecialchars($_GET['category']) ?>">
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
// Einen eventuellen Suchbegriff ebenfalls beibehalten.
|
|
if (isset($_GET['search'])): ?>
|
|
<input type="hidden" name="search" value="<?= htmlspecialchars($_GET['search']) ?>">
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
/**
|
|
* @details Iteriert durch jedes gefundene Attribut, um ein entsprechendes
|
|
* HTML-Select-Feld mit seinen eindeutigen Werten zu generieren.
|
|
*/
|
|
foreach ($attributes as $attr):
|
|
/** @var int $attrId Die Datenbank-ID des Attributs */
|
|
$attrId = $attr['attributeID'];
|
|
|
|
/** @var string $attrName Setzt sich zusammen aus dem Namen und, falls vorhanden, der Einheit (z.B. GB) */
|
|
$attrName = $attr['name'] . ($attr['unit'] ? ' (' . $attr['unit'] . ')' : '');
|
|
|
|
// SQL-Abfrage vorbereiten, um alle unterschiedlichen (DISTINCT) Werte für genau dieses Attribut abzufragen.
|
|
if ($catId) {
|
|
// Abfrage mit Kategorie-Einschränkung
|
|
$vStmt = $conn->prepare("
|
|
SELECT DISTINCT pa.valueString, pa.valueNumber, pa.valueBool
|
|
FROM productAttributes pa
|
|
JOIN products p ON pa.productID = p.productID
|
|
WHERE p.categoryID = ? AND pa.attributeID = ?
|
|
");
|
|
$vStmt->bind_param("ii", $catId, $attrId);
|
|
} else {
|
|
// Alternative Abfrage (wird in diesem Skriptteil zwar aktuell nur bei $catId aufgerufen,
|
|
// aber dient als Fallback für zukünftige globale Filter).
|
|
$vStmt = $conn->prepare("
|
|
SELECT DISTINCT valueString, valueNumber, valueBool
|
|
FROM productAttributes
|
|
WHERE attributeID = ?
|
|
");
|
|
$vStmt->bind_param("i", $attrId);
|
|
}
|
|
$vStmt->execute();
|
|
$vRes = $vStmt->get_result();
|
|
|
|
/**
|
|
* @var array $values
|
|
* @brief Speichert die extrahierten eindeutigen Werte (bereinigt und formatiert) für die Select-Box.
|
|
*/
|
|
$values = [];
|
|
|
|
// Durchlaufe alle gefundenen Attributwerte für die aktuellen Produkte
|
|
while ($vRow = $vRes->fetch_assoc()) {
|
|
// Werte je nach Datentyp (Boolean, Number, String) extrahieren
|
|
if ($attr['dataType'] === 'boolean' || $vRow['valueBool'] !== null) {
|
|
$val = $vRow['valueBool'] ? 'Ja' : 'Nein';
|
|
// Duplikate vermeiden
|
|
if (!in_array($val, $values)) $values[] = $val;
|
|
} elseif ($attr['dataType'] === 'number' || $vRow['valueNumber'] !== null) {
|
|
$val = $vRow['valueNumber'];
|
|
// Entfernt überflüssige Nullen nach dem Komma (z.B. wird 5.00 zu 5)
|
|
$val = rtrim(rtrim((string)$val, '0'), '.');
|
|
if (!in_array($val, $values)) $values[] = $val;
|
|
} elseif ($vRow['valueString'] !== null) {
|
|
$val = $vRow['valueString'];
|
|
if (!in_array($val, $values)) $values[] = $val;
|
|
}
|
|
}
|
|
$vStmt->close();
|
|
|
|
/**
|
|
* @details Sortiert die gesammelten Werte.
|
|
* Zahlen werden numerisch sortiert (damit z.B. 10 nach 2 kommt),
|
|
* Strings werden alphabetisch sortiert.
|
|
*/
|
|
if ($attr['dataType'] === 'number') {
|
|
usort($values, function($a, $b) { return (float)$a <=> (float)$b; });
|
|
} else {
|
|
sort($values);
|
|
}
|
|
|
|
// Wenn es keine Werte für das Filterfeld gibt, überspringe dieses Attribut.
|
|
if (empty($values)) continue;
|
|
|
|
/** @var string $paramName Der Name des GET-Parameters im Formular (z.B. attr_1) */
|
|
$paramName = "attr_" . $attrId;
|
|
|
|
/** @var string $selectedValue Der aktuell ausgewählte Wert aus dem GET-Parameter, falls gesetzt */
|
|
$selectedValue = isset($_GET[$paramName]) ? $_GET[$paramName] : '';
|
|
?>
|
|
<div class="attr-filter-item">
|
|
<!-- Label für das Attribut (z.B. Speichergröße (GB)) -->
|
|
<label for="attr_<?= $attrId ?>"><?= htmlspecialchars($attrName) ?>:</label>
|
|
|
|
<!-- Dropdown-Menu zur Auswahl eines Werts. onchange sumbittet das Formular sofort via JS. -->
|
|
<select name="<?= $paramName ?>" id="attr_<?= $attrId ?>" onchange="this.form.submit()">
|
|
<option value="">Alle</option>
|
|
<?php
|
|
// Liste alle aufbereiteten Optionen auf
|
|
foreach ($values as $val): ?>
|
|
<option value="<?= htmlspecialchars($val) ?>" <?= (string)$val === (string)$selectedValue ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($val) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
|
|
<!-- Fallback-Button, falls der Nutzer JavaScript in seinem Browser deaktiviert hat. -->
|
|
<noscript>
|
|
<button type="submit">Filtern</button>
|
|
</noscript>
|
|
|
|
<?php
|
|
/**
|
|
* @var bool $hasActiveFilter
|
|
* @brief Überprüft, ob mindestens ein Attributfilter aktiv in der URL vorkommt.
|
|
*/
|
|
$hasActiveFilter = false;
|
|
foreach ($_GET as $k => $v) {
|
|
// Wenn der GET-Key mit "attr_" beginnt und ein Wert gesetzt ist
|
|
if (strpos($k, 'attr_') === 0 && $v !== '') {
|
|
$hasActiveFilter = true;
|
|
break; // Sobald ein Filter gefunden ist, kann die Schleife abgebrochen werden
|
|
}
|
|
}
|
|
|
|
// Zeige den "Filter zurücksetzen"-Button nur an, wenn wirklich Filter aktiv sind.
|
|
if ($hasActiveFilter): ?>
|
|
<div class="attr-filter-action">
|
|
<!-- Ein Link auf die index.php (mit Kategorie), der alle Attribut-GET-Parameter verwirft -->
|
|
<a href="index.php<?= isset($_GET['category']) ? '?category='.urlencode($_GET['category']) : '' ?>" class="attr-filter-reset">Filter zurücksetzen</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|