In today's short note, we will see how we can remake the related product block in opencart 3 in such a way that we would automatically display products similar in attributes.

Input data - there is a product on the site - car tires, and we need to display 4 cards with the same attributes - width, diameter and profile in the block of a similar product.

I want to note right away that the solution below is a quick option that immediately came to mind and which worked. I have no doubt that it can be improved and minimized code / load, so everything is laid out as is.

First of all, open the file catalog/model/catalog/product.php, and looking for a function around line 397

public function getProductRelated($product_id) {

and after the line

$product_data = array();

get attributes for filtering the current open product

$diameter_value = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_attribute WHERE product_id = $product_id AND attribute_id = 15");

foreach($diameter_value->rows as $diameter){
    $diameter = $diameter['text'];
}

$profile_value = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_attribute WHERE product_id = $product_id AND attribute_id = 20");

foreach($profile_value->rows as $profile){
    $profile = $profile['text'];
}

$width_value = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_attribute WHERE product_id = $product_id AND attribute_id = 19");

foreach($width_value->rows as $width){
    $width = $width['text'];
}

After commenting out the standard request for similar products of the standard method

$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_related pr LEFT JOIN " . DB_PREFIX . "product p ON (pr.related_id = p.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pr.product_id = '" . (int)$product_id . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'");

foreach ($query->rows as $result) {
    $product_data[$result['related_id']] = $this->getProduct($result['related_id']);
}

and add a selection of product IDs that have the same three attributes as the open product, while excluding its ID, and making a limit of 4 items.

$related_product_id = $this->db->query("SELECT `product_id` FROM `oc_product_attribute` WHERE `text` IN ('$diameter', '$profile', '$width') GROUP BY `product_id` HAVING count(*) = 3 AND `product_id` != $product_id LIMIT 4");

foreach($related_product_id->rows as $result){
    $product_data[$result['product_id']] = $this->getProduct($result['product_id']);
}

That's actually all. Now we will display on all products 4 products similar in attributes.