Доработанная 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 тысяч.
Третья составляющая проблемы: Откуда возьмется "0" ?
Он найдется в таблице, которая содержит связи сущности Узел и Товар:
В результате когда все условия совпали получается, что на странице просмотра Узла пытается отобразится 65 тыс. изображений, на что код не рассчитан, и PHP не хватает памяти для размещения данных.
Главный вопрос: откуда взялся "0" в записях таблицы s_related_products ? Оставим без ответа. :)