Y
Y
yooooooman2018-03-16 21:30:56
Yii
yooooooman, 2018-03-16 21:30:56

How to fix yii filter-brake?

Good day!
There is a site (online store) that was written by a third-party developer in yii. I myself do not understand in yii, and programming in general is tight. But the catalog pages take an awfully long time to load. I'm already tired of seeing critical errors "Long server response" in webmaster.yandex.ru. The catalog looks standard: the output of the filter by products on the left and the products themselves on the right. I will not give a mysql table here, how the characteristics and attributes of goods are arranged (although I believe that it would be necessary, of course).
The question is. The filter is connected, as I understand it, as a widget $this->widget('widget.filters.AFilters');
The widget itself looks like this:

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'));
    	}
    }

}

If the widget (filter) is disabled, well, simply remove $this->widget('widget.filters.AFilters');, then the download speed will increase significantly. I understand that due to the many attributes of goods, there is an incredible number of records in the database and he searches for these records. How can I solve the speed problem, can there be a jamb with the widget code and can be done much better? Maybe something magical can be done in mysql? If there are yii developers here and are willing to do it for some kind of monetary reward, then write suggestions too! And first of all, I asked the question in order to understand in which direction to focus my attention.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Maxim Timofeev, 2018-04-09
@webinar

How to solve the speed problem

Cache everything you can.
In general, it is extremely wrong to send requests from the widget, I would make ayayay to the developer.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question