Всем привет. Кто пользуется сильно тегами Zoo - просьба протестировать данных хак Zoo.
Предыстория: теги Zoo просто дико сделаны, если коротко - чем больше айтемов/тегов - тем больше памяти будет сжирать сайт. У меня начались проблемы с 7-10к айтемов на тег (съедало > 256 мб), решалось повышением памяти - но это заплатка, а не решение проблемы. Проанализировал проблему и вроде сделал верное решение:
До оптимизации (7к айтемов на 1 тег) - Zoo теги: 225 MB
После оптимизации: 19.23 MB
В файле: item.php мы изменяем функцию: getByTag и добавляем также еще новую: getByTagCountAll
/administrator/components/com_zoo/tables/item.php
public function getByTag($application_id, $tag, $published = false, $user = null, $orderby = "", $offset = 0, $limit = 0, $ignore_order_priority = false, $limitStart, $items_per_page) { // var_dump($limitStart); // var_dump($items_per_page); // get database $db = $this->database; // get dates $date = $this->app->date->create(); $now = $db->Quote($date->toSQL()); $null = $db->Quote($db->getNullDate()); // get item ordering list($join, $order) = $this->_getItemOrder($orderby, $ignore_order_priority); $query = "SELECT a.id" ." FROM ".$this->name." AS a " ." LEFT JOIN ".ZOO_TABLE_TAG." AS b ON a.id = b.item_id" .($join ? $join : "") ." WHERE a.application_id = ".(int) $application_id ." AND b.name = '".$db->escape($tag)."'" ." AND a.".$this->app->user->getDBAccessString($user) .($published == true ? " AND a.state = 1" ." AND (a.publish_up = ".$null." OR a.publish_up <= ".$now.")" ." AND (a.publish_down = ".$null." OR a.publish_down >= ".$now.")": "") ." GROUP BY a.id" ." ORDER BY a.id DESC"; // perfomance huge hack // ." LIMIT ".$items_per_page; // perfomance huge hack // .($order ? " ORDER BY " . $order : "") // .($limit ? " LIMIT ".(int) $offset.",".(int) $limit : ""); $list = $this->app->database->queryAssocList($query); $itemOrig = array_reduce($list, function($acc, $item){ $acc[] = $item['id']; return $acc; }, []); $itemOrig = array_slice($itemOrig, $limitStart, $items_per_page); // $list = JBModelItem::model()->getZooItemsByIds($itemOrigOpt); // $list = $this->app->jbarray->sortByArray($list, $itemOrigOpt); $list = JBModelItem::model()->getZooItemsByIds($itemOrig); $list = $this->app->jbarray->sortByArray($list, $itemOrig); return $list; }
public function getByTagCountAll($application_id, $tag, $published = false, $user = null, $orderby = "", $offset = 0, $limit = 0, $ignore_order_priority = false) { // get database $db = $this->database; // get dates $date = $this->app->date->create(); $now = $db->Quote($date->toSQL()); $null = $db->Quote($db->getNullDate()); // get item ordering list($join, $order) = $this->_getItemOrder($orderby, $ignore_order_priority); $query = "SELECT a.id" ." FROM ".$this->name." AS a " ." LEFT JOIN ".ZOO_TABLE_TAG." AS b ON a.id = b.item_id" .($join ? $join : "") ." WHERE a.application_id = ".(int) $application_id ." AND b.name = '".$db->escape($tag)."'" ." AND a.".$this->app->user->getDBAccessString($user) .($published == true ? " AND a.state = 1" ." AND (a.publish_up = ".$null." OR a.publish_up <= ".$now.")" ." AND (a.publish_down = ".$null." OR a.publish_down >= ".$now.")": "") ." GROUP BY a.id" ." ORDER BY a.id DESC" // perfomance huge hack // .($order ? " ORDER BY " . $order : "") .($limit ? " LIMIT ".(int) $offset.",".(int) $limit : ""); $list = count($this->app->database->queryAssocList($query)); // $itemOrig = array_reduce($list, function($acc, $item){ // $acc[] = $item['id']; // return $acc; // }, []); return $list; }
В файле default.php мы правим глобальную функцию tag
/components/com_zoo/controllers/default.php
public function tag() { // get request vars $page = $this->app->request->getInt('page', 1); $this->tag = $this->app->request->getString('tag', ''); // raise 404 if tag does not exist if (!$this->app->table->tag->getAll($this->application->id, $this->tag)) { return $this->app->error->raiseError(404, JText::_('Tag not found')); } // get params $params = $this->application->getParams('site'); $items_per_page = $params->get('config.items_per_page', 15); $this->item_order = $params->get('config.item_order'); $ignore_priority = $params->get('config.ignore_item_priority', false); // get categories and items $this->categories = $this->application->getCategoryTree(true); // $this->items = $this->app->table->item->getByTag($this->application->id, $this->tag, true, null, $this->item_order, 0, 0, $ignore_priority); $this->itemsCountAll = $this->app->table->item->getByTagCountAll($this->application->id, $this->tag, true, null, $this->item_order, 0, 0, $ignore_priority); // get item pagination $this->pagination = $this->app->pagination->create($this->itemsCountAll, $page, $items_per_page, 'page', 'app'); $this->pagination->setShowAll($items_per_page == 0); $this->pagination_link = $this->app->route->tag($this->application->id, $this->tag); // slice out items if (!$this->pagination->getShowAll()) { $this->items = $this->app->table->item->getByTag($this->application->id, $this->tag, true, null, $this->item_order, 0, 0, $ignore_priority, $this->pagination->limitStart(), $items_per_page); } else { $this->items = $this->app->table->item->getByTag($this->application->id, $this->tag, true, null, $this->item_order, 0, 0, $ignore_priority, null, null); } // set alphaindex if ($params->get('template.show_alpha_index')) { $this->alpha_index = $this->_getAlphaindex(); } // set metadata $this->app->document->setTitle($this->app->zoo->buildPageTitle($this->tag)); // create pathway $this->pathway->addItem(JText::_('Tags').': '.$this->tag, JRoute::_($this->app->route->tag($this->application->id, $this->tag))); // get template and params if (!$this->template = $this->application->getTemplate()) { return $this->app->error->raiseError(500, JText::_('No template selected')); } $this->params = $params; // set renderer $this->renderer = $this->app->renderer->create('item')->addPath(array($this->app->path->path('component.site:'), $this->template->getPath())); // display view $this->getView('tag')->addTemplatePath($this->template->getPath())->setLayout('tag')->display(); }
Если объяснить по простому:
Вначале получаем просто кол-во, а далее уже прокидываем (!!!) offset и кол-во айтемов Можно и переписать решение немного по другому, но не суть.
Прикрепляю файлы, но кроме этих правок там могут быть и другие.
item.php 26.94KB 204 downloads
default.php 22.55KB 200 downloads