@yooooooman

Как исправить фильтр-тормоз yii?

Доброго времени суток!

Есть сайт (интернет-магазин), который был написан сторонним разработчиком на yii. Сам не соображаю в yii, да и в программировании в общем туго. Но страницы каталога ужасно долго грузятся. Я уже устал видеть в webmaster.yandex.ru критичные ошибки "Долгий ответ сервера". Каталог выглядит стандартно: вывод слева фильтра по товарам и справа сами товары. Я не буду приводить здесь таблицу mysql, как устроены характеристики, атрибуты товаров (хотя полагаю, что надо бы конечно).

Вопрос такой. Фильтр подключается как я понимаю как виджет $this->widget('widget.filters.AFilters');

Сам виджет выглядит так:

class AFilters extends CWidget {

	private function _publishAssets()
	{
		$assets = dirname(__FILE__).'/assets';
		$baseUrl = Yii::app()->assetManager->publish($assets);
	
		$cs=Yii::app()->getClientScript();

        $cs->registerScriptFile("{$baseUrl}/js/attr_filter.js", CClientScript::POS_HEAD);
        $cs->registerScriptFile("{$baseUrl}/js/jquery-ui.min.js", CClientScript::POS_HEAD);
        $cs->registerCssFile("{$baseUrl}/css/jquery-ui.css");
       # $cs->registerCssFile("http://code.jquery.com/ui/1.10.3/themes/south-street/jquery-ui.css");

	}

    public function run(){
    	$this->_publishAssets();
        $attributes = $attributeValues = [];
        $categoryID = Yii::app()->request->getParam('id');

        if (Yii::app()->controller->action->id == 'category'){
            if (Yii::app()->controller->id == 'shop') {
                $max_price = Category::model()->getMaxPrice();
                $min_price = Category::model()->getMinPrice();

                /** @var $category Category */
                $category = Category::model()->findByPk($categoryID);

                $criteria = $category->getProductsCriteria();
            } else {
                $sql = 'SELECT MAX(price) FROM product WHERE 1';
                $connection = Yii::app()->db;
                $command = $connection->createCommand($sql);
                $max_price = $command->queryScalar();;
                $min_price = 0;

                $model = AdviceCategory::model()->findByPk($categoryID);

                $newCriteria = new CDbCriteria();
                $newCriteria->select = 't.id';
                $newCriteria->index = 'id';
                $criteria = $model->getProductsCriteriaByCondition($newCriteria, false);
            }

            $criteria->index = 'id';

            foreach ($_GET as $paramName => $paramValue) {
                if (strpos($paramName, 'attr_') === 0) {
                    $paramParts = explode('_', $paramName);

                    $counter = 1;
                    $paramCriteria = new CDbCriteria();

                    $conditions[] = '(productAttributes.value = "' . $paramValue . '" AND productAttributes.id_attrs = "' . intval(end($paramParts)) . '")';
                    $paramCriteria->addCondition(implode(' OR ', $conditions), 'OR');
                    $paramCriteria->group = 'id_product';
                    $paramCriteria->having = 'count(id_product)=' . $counter;
                    $paramCriteria->with = array('productAttributes');
                    $paramCriteria->index = 'id';
                    $paramCriteria->select = 't.id';
                    $paramCriteria->together = true;

                    $criteria->mergeWith($paramCriteria);
                }
            }

            $products = Product::model()->cache(CACHE_TIME)->findAll($criteria);
            $productIDs = array_keys($products);

            if ($productIDs) {
                $criteria = new CDbCriteria();
                $criteria->index = 'id_attrs';
                $criteria->group = 'id_attrs';
                $criteria->addInCondition('id_product', $productIDs);
                $criteria->addCondition('value <> ""');

                $attributeValues = EavValue::model()->findAll($criteria);


                if ($attributeValues) {
                    $criteria = new CDbCriteria();
                    $criteria->addInCondition('id', array_keys($attributeValues));
                    $criteria->addCondition('use_filter = 1');
                    $criteria->index = 'id';

                    $attributes = EavAttribute::model()->findAll($criteria);
                }

            }

            $values = [];

            foreach ($attributes as $attribute) {
                $criteria = new CDbCriteria();
                $criteria->group = 't.id_attrs, t.value';
                $criteria->addInCondition('id_product', $productIDs);
                $criteria->addCondition('t.id_attrs = :id_attrs');
                $criteria->params[':id_attrs'] = $attribute->id;
                $criteria->addCondition('t.value <> ""');
                $criteria->order = 't.enum, t.value';

                $values[$attribute->id]['type'] = $attribute->type;
                $values[$attribute->id]['name'] = $attribute->name;

                // $values[$attribute->id]['values'] = EavValue::model()->findAll($criteria);

                if ($attribute->type != 2) {
                    $values[$attribute->id]['values'] = EavValue::model()->cache(CACHE_TIME)->findAll($criteria);
                } else {
                    $criteria->limit = 1;
                    $criteria->order = 't.enum DESC, t.value';

                    $values[$attribute->id]['values'] = EavValue::model()->cache(CACHE_TIME)->findAll($criteria);
                }
            }

            $this->render('attr_list', compact('values', 'max_price', 'min_price'));
    	}
    }

}


Если виджет (фильтр) отключить, ну попросту убрать $this->widget('widget.filters.AFilters');, то скорость загрузки вырастает в разы. Я понимаю, что из-за множества атрибутов товаров, там неимоверное количество записей в базе и он по этим записям делает поиск. Как можно решить проблему скорости, может с кодом виджета косяк и можно сделать гораздо лучше? Может, что-то в mysql можно сделать волшебное? Если здесь есть разработчики на yii и готовы сделать это за какое-то денежное вознаграждение, то пишите предложения тоже! А вопрос в первую очередь задал, чтобы понимать в какую сторону акцентировать свое внимание.
  • Вопрос задан
  • 48 просмотров
Пригласить эксперта
Ответы на вопрос 1
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
Как можно решить проблему скорости

Закешировать все что можно.
Вообще крайне не верно из виджета слать запросы, я бы сделал айяйяй разработчику.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы