Выяснилось еще одно узкое место: при выборке записей из базы для отображения на фронтальной части сайта каталог выбирает все записи заданного каталога/категории и потом делает вырезку нужного количества из массива результатов. При больших объемах PHP расходует всю доступную память и, как следствие - фатальная ошибка. Кроме того, это приводит к трениям с хостером при использовании виртуального хостинга.
Исправляется следующим образом:
в класс TableItem (файл /administrator/components/com_zoo/tables/item.php) добавляется метод getCountFromCategory
function getCountFromCategory($catalog_id, $category_id, $published = false, $access_id = false){
$date =& JFactory::getDate();
$now = $this->_db->Quote($date->toMySQL());
$null = $this->_db->Quote($this->_db->getNullDate());
$query = "SELECT count(*)"
." FROM ".$this->getTableName()." AS a"
." LEFT JOIN ".ZOO_TABLE_CATEGORY_ITEM." AS b ON a.id = b.item_id"
." WHERE b.catalog_id = ".(int) $catalog_id
." AND b.category_id ".(is_array($category_id)? " IN (".implode(",", $category_id).")" : " = ".(int) $category_id)
.($published == true ? " AND a.state = 1" : "")
.($access_id !== false ? " AND a.access <= ".(int) $access_id : "")
." AND (a.publish_up = ".$null." OR a.publish_up <= ".$now.")"
." AND (a.publish_down = ".$null." OR a.publish_down >= ".$now.")"
;
$this->_db->setQuery($query);
return $this->_db->loadResult();
}
в классе ZooModelCategory (файл /components/com_zoo/models/category.php) метод getItems должен выглядеть так:
function getItems() {
if (empty($this->items)) {
// set order
$orders = array('date' => 'a.created ASC', 'rdate' => 'a.created DESC',
'alpha' => 'a.name ASC', 'ralpha' => 'a.name DESC',
'hits' => 'a.hits DESC', 'rhits' => 'a.hits ASC',
'ordering' => 'a.ordering ASC', 'rordering' => 'a.ordering DESC');
$order = isset($orders[$this->item_order])? $orders[$this->item_order] : '';
// get items
$table =& JTable::getInstance('item', 'Table');
$table->setCache($this->cache);
$itemsCount = $table->getCountFromCategory($this->catalog_id, $this->category_id, true, $this->user->get('aid', 0));
// set pagination
$this->pagination = new YPagination('page', $itemsCount, $this->page, $this->items_per_page);
$this->pagination->setShowAll($this->items_per_page == 0);
// slice out items
if ($this->pagination->getShowAll()) {
$this->items = $table->getFromCategory($this->catalog_id, $this->category_id, true, $this->user->get('aid', 0), $order, 0, $itemsCount);
} else {
$this->items = $table->getFromCategory($this->catalog_id, $this->category_id, true, $this->user->get('aid', 0), $order, $this->pagination->limitStart(), $this->items_per_page);
}
}
return $this->items;
}