Kapcsolódó Termékek
Egyirányú Kapcsolat Fix
OpenCart alapból kétirányúan menti a kapcsolódó termékeket: ha A-hoz hozzárendeled B-t, B is automatikusan megkapja A-t kapcsolódóként. Ez a javítás megszünteti ezt a viselkedést.
🔍 A probléma
Ha az admin felületen egy terméknél kapcsolódó terméket adsz hozzá, az OpenCart automatikusan visszafelé is bejegyzi a kapcsolatot – mindkét irányban. Ez sok esetben nem kívánatos.
Kívánatos viselkedés
A-nál megjelenik B mint kapcsolódó termék. B-nél nem jelenik meg A.
Jelenlegi (OC alap) viselkedés
A-nál B kapcsolódó → automatikusan B-nél is A kapcsolódó lesz. Mindkét irányban.
Adatbázisban
Két sor keletkezik a product_related táblában termékpáronként a mentés során.
⚙️ Miért történik – a kód logikája
A kapcsolódó termékek mentése az
admin/model/catalog/product.php fájlban,
az editProduct() és addProduct() metódusokban történik.
Az OpenCart két SQL műveletet végez minden egyes kapcsolódó termékhez:
egyet az eredeti irányba, egyet visszafelé.
Az érintett kódrészlet (eredeti)
// Előbb törli a meglévő kapcsolatokat – MINDKÉT irányból: $this->db->query("DELETE FROM " . DB_PREFIX . "product_related WHERE product_id = '" . (int)$product_id . "'"); $this->db->query("DELETE FROM " . DB_PREFIX . "product_related WHERE related_id = '" . (int)$product_id . "'"); foreach ($data['product_related'] as $related_id) { // Előre irány – ez kell: $this->db->query("INSERT INTO " . DB_PREFIX . "product_related SET product_id = '" . (int)$product_id . "', related_id = '" . (int)$related_id . "'"); // Visszafelé irány – ezt kell törölni: $this->db->query("INSERT INTO " . DB_PREFIX . "product_related SET product_id = '" . (int)$related_id . "', related_id = '" . (int)$product_id . "'"); }
🔧 A megoldás
Az admin/model/catalog/product.php fájlban két metódus érintett.
Az alábbiakban a helyes, végleges kód látható mindkét helyen.
product.php.bak) mielőtt felülírod.
addProduct() – helyes product_related blokk
if (isset($data['product_related'])) { foreach ($data['product_related'] as $related_id) { $this->db->query("DELETE FROM " . DB_PREFIX . "product_related WHERE product_id = '" . (int)$product_id . "' AND related_id = '" . (int)$related_id . "'"); $this->db->query("INSERT INTO " . DB_PREFIX . "product_related SET product_id = '" . (int)$product_id . "', related_id = '" . (int)$related_id . "'"); } }
editProduct() – helyes product_related blokk
$this->db->query("DELETE FROM " . DB_PREFIX . "product_related WHERE product_id = '" . (int)$product_id . "'"); if (isset($data['product_related'])) { foreach ($data['product_related'] as $related_id) { $this->db->query("DELETE FROM " . DB_PREFIX . "product_related WHERE product_id = '" . (int)$product_id . "' AND related_id = '" . (int)$related_id . "'"); $this->db->query("INSERT INTO " . DB_PREFIX . "product_related SET product_id = '" . (int)$product_id . "', related_id = '" . (int)$related_id . "'"); } }
🗄️ Adatbázis cleanup – meglévő duplikációk
A kódfájl módosítása csak az ezután mentett termékekre hat. A korábban felvitt kétirányú bejegyzések az adatbázisban maradnak. Ezeket kézzel kell kitakarítani.
A visszafelé irányú sorok azonosítása
Azok a sorok "feleslegesek", amelyeknél az ellentétes párjuk is megvan (product_id és related_id felcserélve):
SELECT a.product_id, a.related_id FROM oc_product_related a JOIN oc_product_related b ON b.product_id = a.related_id AND b.related_id = a.product_id WHERE a.product_id > a.related_id; -- A WHERE feltétel biztosítja, hogy minden pár csak egyszer szerepeljen
A felesleges sorok törlése
DELETE a FROM oc_product_related a JOIN oc_product_related b ON b.product_id = a.related_id AND b.related_id = a.product_id WHERE a.product_id > a.related_id;
Alternatíva: újramentés
Ha kevés az érintett termék, a legegyszerűbb megoldás: a kódfájl módosítása után az admin felületen nyisd meg és mentsd újra az érintett termékeket. A mentéskor a régi kapcsolatok törlődnek, és az újak már csak egyirányban kerülnek be.
✅ Ellenőrzés
A javítás után ellenőrizd, hogy minden rendben működik:
Admin: kapcsolódó termék hozzáadása
Nyisd meg az A terméket, adj hozzá B-t kapcsolódóként, mentsd el.
Admin: B termék ellenőrzése
Nyisd meg a B terméket – az A nem kell, hogy megjelenjen ott kapcsolódóként.
Adatbázis ellenőrzés (opcionális)
Ellenőrizd, hogy csak egy sor keletkezett-e a mentés után:
SELECT * FROM oc_product_related WHERE product_id IN (A_ID, B_ID) OR related_id IN (A_ID, B_ID);
Ha a fix működött, az eredménynek egy sort kell mutatnia:
product_id = A, related_id = B.
📋 Tudnivalók
| Szempont | Részlet |
|---|---|
| Érintett fájl | admin/model/catalog/product.php |
| Érintett metódusok | editProduct() és addProduct() |
| Adatbázis tábla | oc_product_related |
| Frontend hatás | Nincs – csak az admin mentési logika változik |
| Journal 3 konfliktus | Nincs – a Journal theme nem módosítja ezt a modell fájlt |
| OC frissítésnél | A product.php felülíródhat – frissítés után újra el kell végezni a módosítást |
| Visszaállítás | A .bak fájl visszamásolásával azonnal visszaállítható az eredeti viselkedés |