Skip to content

Доработанная Simpla класс Scheme

Попалось на одном из проектов Simpla с доработками, которая падает в ошибку 500 с сообщением: Allowed memory size of 67108864 bytes exhausted (tried to allocate 72 bytes) in /var/www/domain.com/api/Database.php

Причину искали, нашли, выводы:

Добавлена сущность "Узел", включающая в себя N товаров. Класс называется Scheme.

При работе с изображениями подчиненных товаров используется функция products->get_images.

Вызов выглядит так:

# SchemeView.php
# (один из примеров)
foreach($related_ids as $key=>$id_product)
            {
                //$p->position
                $p = $this->products->get_products(array('id'=>$id_product,  'visible'=>1, 'whith_related_custom'=>1));
                $p=reset($p);
                $p->position = array_shift($positions[$key]);
                $p->custom_number = array_shift($custom_numbe[$key]);

# ВОТ ОНО !!!
                $related_products_images = $this->products->get_images(array('product_id'=>array($id_product)));

#

                foreach($related_products_images as $related_product_image)
                    $p->images[] = $related_product_image;

                $related_products_variants = $this->variants->get_variants(array('product_id'=>array($id_product), 'instock'=>true));
                foreach($related_products_variants as $related_product_variant)
                {
                        $p->variants[] = $related_product_variant;
                }

                $related_products[] = $p;
            }

Реализация функции products->get_images проверяет что переданный параметр не пустой так:

if(!empty($filter['product_id'])) {
  $product_id_filter = $this->db->placehold('AND i.product_id in(?@)', (array)$filter['product_id'] );
}

Благодаря тому что Разработчики класса Scheme передают параметр как массив: array('product_id'=>array($id_product)) вышеуказанная проверка не работает, и соответственно запрос в функции get_image может быть сформирован такого вида:

SELECT i.id, i.product_id, i.name, i.filename, i.position FROM __images AS i WHERE 1 AND i.product_id in('0')  ORDER BY i.product_id, i.position;

Вроде бы ничего страшного, ведь товаров с 0-ым id не должно быть в принципе. Но тут разработчики данного класса тоже "участвовали". В таблице __images вот такая структура, и записей с product_id = 0, ровно столько сколько изображений для сущности Scheme, в данном случае более почти 65 тысяч.

image

Третья составляющая проблемы: Откуда возьмется "0" ?

Он найдется в таблице, которая содержит связи сущности Узел и Товар: image

В результате когда все условия совпали получается, что на странице просмотра Узла пытается отобразится 65 тыс. изображений, на что код не рассчитан, и PHP не хватает памяти для размещения данных.

Главный вопрос: откуда взялся "0" в записях таблицы s_related_products ? Оставим без ответа. :)