Новости Joomla

Человек на GitHub ускорил Joomla в 600 раз на объёме 150к+ материалов в 1700+ категориях

Человек на GitHub ускорил Joomla в 600 раз на объёме 150к+ материалов в 1700+ категориях

👩‍💻 Человек на GitHub ускорил Joomla в 600 раз на объёме 150к+ материалов в 1700+ категориях. На старте его сайт на Joomla 3 вообще не смог обновиться на Joomla 5. Пришлось делать экспорт/импорт материалов. Проделав всё это он запустил-таки этот объём данных на Joomla 5. Тестовый скрипт грузил 200 материалов из этого объёма всего за 94 секунды ))) А главная страница с категориями грузилась 20 секунд. Добавив индекс для таблицы #__content

CREATE INDEX idx_catid_state ON #__content (catid, state);
он сократил время загрузки категорий до 1 секунды. Затем наш герой решил поковырять SQL-запрос в ArticleModel, который отвечает за выборку материалов. И решил заменить тип JOIN на STRAIGHT_JOIN для категорий.
// ->from($db->quoteName('#__content', 'a'))->from(    $db->quoteName('#__content', 'a')    . ' STRAIGHT_JOIN ' . $db->quoteName('#__categories', 'c')    . ' ON ' . $db->quoteName('c.id') . ' = ' . $db->quoteName('a.catid'))// ->join('LEFT', $db->quoteName('#__categories', 'c'), $db->quoteName('c.id') . ' = ' . $db->quoteName('a.catid'))
Что сократило загрузку 200 материалов из 150к с 94 секунд до 5. К слову сказать, боевой сайт на Joomla 3 крутится на 12CPU 64GB рамы. А все манипуляции с кодом он делает на базовом 1CPU 1GB сервере и замеры скорости даны именно для базового сервера. Но это всё в дискуссии, хотя в идеале должно вылиться в Pull Requests. Мы - Open Source сообщество, где никто никому ничего не должен. Джунгли. Но человек ищет пути оптимизации Joomla и предлагает решения. Если оказать поддержку и предложить помощь хотя бы с тестированием самых разнообразных сценариев, то возможно эти улучшения смогут войти в ядро. Пусть не быстро, пусть через несколько лет, пусть не все, но войдут. Достаточно предложить руку помощи и приложить немного усилий.
Дискуссию на GitHub можно почитать здесь.@joomlafeed#joomla #community #php

0 Пользователей и 1 Гость просматривают эту тему.
  • 18 Ответов
  • 5057 Просмотров
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Здравствуйте.

Пишу плагин обратного отсчета. Плагин должен отсчитывать время, оставшееся до окончания публикации материала.

Я работаю с датой окончания публикации, разбивая её следующим образом:

Код
$endtime = explode('.', JHTML::_('date',$this->article->publish_down, 'd.m.Y.H.i.s')); 

Далее данные подсовываю скрипту и идет отсчет. Все работает прекрасно в материале. И не работает в блоге категории.

Как я понял, при выводе блогом, плагин не может получить publish_down, т.е. код $this->article->publish_down не срабатывает. Как быть, посоветуйте пожалуйста?

Просто создать в плагине запрос к БД, выведя дату окончания публикации в отдельную переменную и далее работать уже с ней? Или есть еще варианты?
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Мозги потихоньку начинают плавиться...

Делаю стандартнейший запрос:

Код
$req = "select publish_down from #__content WHERE id='415'"; 
$db = &JFactory::getDBO();
$db->setQuery($req);
$time = $db->loadResult();

Все выводится.

Меняю код, подставляя id статьи:

Код
$req = "select publish_down from #__content WHERE id=".$this->article->id; 
$db = &JFactory::getDBO();
$db->setQuery($req);
$time = $db->loadResult();

Все завис. Ничего не выводится....

Подставляю в $result, чтобы посмотреть вывод:

Код
$result . =  "select publish_down from #__content WHERE id=".$this->article->id;

Получаю select publish_down from #__content WHERE id=415, т.е именно то, что должно сработать в запросе к БД. Но не срабатыват, зараза.

Где я портачу?
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Блин, чтож за глюк-то такой... Ничего не понимаю.

В плагине присутствует две функции. Первая производит замену {endtime}, обнаруженного в тексте материала на вывод таймера:

Код
	public function onContentPrepare($context, &$article, &$params, $limitstart)
{
$this->article =& $article;
$this->articleParams =& $params;
$regex = '#{endtime}#';
$article->text = preg_replace_callback($regex, array($this, "Replacer"), $article->text);
return '';
}


Вторая, где собственно, формируется вывод:

Код
	public function Replacer(&$matches)
{
jimport('joomla.html.parameter');
$plugin =& JPluginHelper::getPlugin('content', 'countdown');
$pluginParams = new JParameter( $plugin->params );
$script = $pluginParams->get('script');
$debug = $pluginParams->get('debug');
$grafics = $pluginParams->get('grafics');
$text = $pluginParams->get('text');

// Подключаем скрипты и CSS.
$document = &JFactory::getDocument();
if ($script == 1) {
$document->addScript("plugins/content/countdown/files/js/jquery-1.7.2.min.js");
}
$document->addScript("plugins/content/countdown/files/js/Countdown.js");
if ($grafics == 1) {
$document->addStyleSheet("plugins/content/countdown/files/css/light.css");
} else {
$document->addStyleSheet("plugins/content/countdown/files/css/text.css");
}
if ($debug == 1) {
$result = JHTML::_('date',$this->article->publish_down, 'd.m.Y H:i:s').' - Дата окончания публикации';
$result .= '<br /><br />';
$result .= date('d.m.Y H:i:s').' - Текущее время сервера';
$result .= '<br /><br />';
$result .= JHTML::_('date','now', 'd.m.Y H:i:s').' - Текущее время согласно настроек Joomla';
$result .= '<br /><br /><br /><br />';
}

// разбиваем строку.
$endtime = explode('.', JHTML::_('date',$this->article->publish_down, 'd.m.Y.H.i.s'));

// Добавляем скрипт с настройками в head шаблона.
$document->addScriptDeclaration('
jQuery(document).ready(function() {
$(\'#countdown_dashboard\').countDown({
targetDate: {
\'day\': '.$endtime[0].',
\'month\': '.$endtime[1].',
\'year\': '.$endtime[2].',
\'hour\': '.$endtime[3].',
\'min\': '.$endtime[4].',
\'sec\': '.$endtime[5].'
}
});
});
');

// Вывод результата.

if ($endtime[2] == '-0001') {
$result .= '';
} else {
if ($grafics == 0) {
$result .= '

<div id="countdown_dashboard">
<div class="count_days_div">'.$text.'</div>

<div class="dash days_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">д.</span>
</div>

<div class="dash hours_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">ч.</span>
</div>

<div class="dash minutes_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">м.</span>
</div>

<div class="dash seconds_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">с.</span>
</div>
</div>
<br clear="all">
';
} else {
$result .= '
<div class="count_days_div">'.$text.'</div>
<div id="countdown_dashboard">
<div class="dash days_dash">
<span class="dash_title">дней</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>

<div class="dash hours_dash">
<span class="dash_title">часов</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>

<div class="dash minutes_dash">
<span class="dash_title">минут</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>

<div class="dash seconds_dash">
<span class="dash_title">секунд</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>
</div>
<br clear="all">
';
}
}
return $result;
}


Все работает на странице материала. В блоге категории не срабатывает, так как не удается получить дату окончания публикации (publish_down).

Решил сделать через запрос в БД.

Добавляю в код:

Код
		$req = "select publish_down from #__content WHERE id=".$this->article->publish_down; 
$db = &JFactory::getDBO();
$db->setQuery($req);
$end = $db->loadResult();

Не срабатывает. Не выводятся данные. Причем если указать id явно (select publish_down from #__content WHERE id=415"), то все работает.

Если вывести просто $result .= $this->article->publish_down; ,  то выводится id материала корректно - 415

Почему же он, собака, не срабатывает в запросе к БД?
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Тихо-мирно сам с собою....

На странице материала код

Код
		$req = "select publish_down from #__content WHERE id=".$this->article->publish_down; 
$db = &JFactory::getDBO();
$db->setQuery($req);
$end = $db->loadResult();

отрабатывает как положено... Осталось понять, почему не срабатывает в категории.
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Так... При использовании события onContentBeforeDisplay я могу получить все требуемые мне параметры материала.

Но при использовании
Код
public function onContentPrepare($context, &$article, &$params, $limitstart)
у меня ломается preg_replace_callback.
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Мда.. Перекопал все что только можно. Насколько я понимаю, я не смогу получить id конкретного материала в блоге категории?
*

prometheus

  • Захожу иногда
  • 84
  • 7 / 0
как минимум попробуй задавать через $db->quote() так
$req = "select publish_down from #__content WHERE id=".$db->quote($this->article->id);
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Ругнулся: Fatal error: Call to a member function quote() on a non-object in Z:\home\kamensk.ru\www\plugins\content\countdown\countdown.php on line 57

57 строка это и есть: $req = "select publish_down from #__content WHERE id=".$db->quote($this->article->id);

Блин, одного не могу понять...

Почему при добавлении в $result, который потом выведется в return - все срабатывает. ID присутствует.

При попытке использовать в эту переменную в запросе в БД результат нулевой
*

prometheus

  • Захожу иногда
  • 84
  • 7 / 0
Строчка
$db = &JFactory::getDBO();
должна быть первее чем
$req = "select publish_down from #__content WHERE id=".$db->quote($this->article->id);

Причем я заметил ты иногда используешь $this->article->publish_down вместо $this->article->id почему? Опечатка?
И еще нужно убедиться что объект $this->article действительно создан и содержит нужные данные
например var_dump($this->article);
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
$db = &JFactory::getDBO(); вынес вперед - не помогло, что и неудивительно, поскольку var_dump($this->article); не выводит id материала.
В общем аллес... Не нашел ни одного намека на то, как вывести id материала в блоге категории. Хоть бери и JS'ом выдергивай из кнопки "подробнее". Мрак. Или просто я настолько торможу. 

Цитировать
Причем я заметил ты иногда используешь $this->article->publish_down вместо $this->article->id почему? Опечатка?

В запросе - да, ошибка. Неправильно написал, когда вставлял на форум.
*

prometheus

  • Захожу иногда
  • 84
  • 7 / 0
$db = &JFactory::getDBO(); вынес вперед - не помогло, что и неудивительно, поскольку var_dump($this->article); не выводит id материала.
В общем аллес... Не нашел ни одного намека на то, как вывести id материала в блоге категории. Хоть бери и JS'ом выдергивай из кнопки "подробнее". Мрак. Или просто я настолько торможу. 

В запросе - да, ошибка. Неправильно написал, когда вставлял на форум.

$db = &JFactory::getDBO(); впереди нужен чтобы н ебыло ошибки Fatal error: Call to a member function quote() on a non-object
var_dump($this->article); выводит не id а весь объект  и если он выводит false или null значит объект не создается.

Короче говоря расскажи что за файл ты редактируешь? Стандартный Joomla или свой? И в каком месте формируется $this->article
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Редактирую свой файл. Пишу плагин для вывода таймера отсчета времени до окончания публикации.

Код плагина:

Код
<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
jimport( 'joomla.plugin.plugin' );

class plgContentCountDown extends JPlugin
{
public function plgContentCountDown( &$subject, $params )
{
parent::__construct( $subject, $params );

}
public function onContentPrepare($context, &$article, &$params, $limitstart)
{
$this->article =& $article;
$this->articleParams =& $params;
$regex = '#{endtime}#';
$article->text = preg_replace_callback($regex, array($this, "Replacer"), $article->text);
return '';
}
public function Replacer(&$matches)
{
jimport('joomla.html.parameter');
$plugin =& JPluginHelper::getPlugin('content', 'countdown');
$pluginParams = new JParameter( $plugin->params );
$script = $pluginParams->get('script');
$debug = $pluginParams->get('debug');
$grafics = $pluginParams->get('grafics');
$text = $pluginParams->get('text');

// Подключаем скрипты и CSS.
$document = &JFactory::getDocument();
if ($script == 1) {
$document->addScript("plugins/content/countdown/files/js/jquery-1.7.2.min.js");
}
$document->addScript("plugins/content/countdown/files/js/Countdown.js");
if ($grafics == 1) {
$document->addStyleSheet("plugins/content/countdown/files/css/light.css");
} else {
$document->addStyleSheet("plugins/content/countdown/files/css/text.css");
}
if ($debug == 1) {
$result = JHTML::_('date',$this->article->publish_down, 'd.m.Y H:i:s').' - Дата окончания публикации';
$result .= '<br /><br />';
$result .= date('d.m.Y H:i:s').' - Текущее время сервера';
$result .= '<br /><br />';
$result .= JHTML::_('date','now', 'd.m.Y H:i:s').' - Текущее время согласно настроек Joomla';
$result .= '<br /><br /><br /><br />';
}

// разбиваем строку.
$endtime = explode('.', JHTML::_('date',$this->article->publish_down, 'd.m.Y.H.i.s'));

// Добавляем скрипт с настройками в head шаблона.
$document->addScriptDeclaration('
jQuery(document).ready(function() {
$(\'#countdown_dashboard\').countDown({
targetDate: {
\'day\': '.$endtime[0].',
\'month\': '.$endtime[1].',
\'year\': '.$endtime[2].',
\'hour\': '.$endtime[3].',
\'min\': '.$endtime[4].',
\'sec\': '.$endtime[5].'
}
});
});
');

// Вывод результата.

if ($endtime[2] == '-0001') {
$result .= '';
} else {
if ($grafics == 0) {
$result .= '

<div id="countdown_dashboard">
<div class="count_days_div">'.$text.'</div>

<div class="dash days_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">д.</span>
</div>

<div class="dash hours_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">ч.</span>
</div>

<div class="dash minutes_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">м.</span>
</div>

<div class="dash seconds_dash">
<div class="digit">0</div>
<div class="digit">0</div>
<span class="dash_title">с.</span>
</div>
</div>
<br clear="all">
';
} else {
$result .= '
<div class="count_days_div">'.$text.'</div>
<div id="countdown_dashboard">
<div class="dash days_dash">
<span class="dash_title">дней</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>

<div class="dash hours_dash">
<span class="dash_title">часов</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>

<div class="dash minutes_dash">
<span class="dash_title">минут</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>

<div class="dash seconds_dash">
<span class="dash_title">секунд</span>
<div class="digit">0</div>
<div class="digit">0</div>
</div>
</div>
<br clear="all">
';
}
}
return $result;
}
}

Уперся в то, что плагин не работает в блоге категории, так как не могу получить $this->article->publish_down
Хотел сделать стандартным запросом в БД, но не могу выцепить id материала...
« Последнее редактирование: 18.07.2012, 07:58:03 от dkraev »
*

prometheus

  • Захожу иногда
  • 84
  • 7 / 0
Событие onContentPrepare вызывается только внутри материала. В другом месте нужно другое событие
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Да, я пробрвал использовать событие onContentBeforeDisplay.
Рушится функционал, ломается preg_replace_callback. Но спасибо, буду копать дальше.
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
Допер! Закончу - распишу, мало ли кто будет также тупить, как и я.
*

dkraev

  • Захожу иногда
  • 148
  • 7 / 0
В общем, как и сказал prometheus, событие onContentPrepare вызывается только внутри материала, соответственно, в блоге категории подобный метод не сработает, с чем я и столкнулся.

Поэтому я использовал событие onContentBeforeDisplay. Этот метод вызывается ПЕРЕД отображением контента, но самое главное - здесь доступны все свойства материала в блоге категории, в отличии от onContentPrepare. Но опять уперся своими рогами (не от жены, а так - просто тупой, наверное) в стену. В материале все отрабатывало корректно, однако в блоге не выводилось ничего, отображалась только моя заглушка - {endtime}, которая по идее должна бы замениться на таймер.

Тут опять помог prometheus:

Цитировать
И еще нужно убедиться что объект $this->article действительно создан и содержит нужные данные
например var_dump($this->article);

Ну я, как умный человек, смотрю, только не вижу нифига. И вместо того, чтобы внимательно проанализировать то, что мне показывают на экране, мол: "Человече, глазы свои разуй наконец", я в панике бегаю по форуму, размахивая руками и крича "SOS" доставая все того же prometheus.

Сегодня, решив во что бы то ни стало добить этот многострадальный плагин, я начал смотреть более внимательно, что мне показывает var_dump($this->article). А она показывает мне, что в полном материале есть данные ["introtext"] и ["fulltext"], а в блоге только ["introtext"].

Я же в коде использовал:

Код
$article->text = preg_replace_callback($regex, array($this, "Replacer"), $article->text);

что производило замену {endtime} на код таймера только в полном тексте материала. А для блога надо было использовать

Код
$article->introtext = preg_replace_callback($regex, array($this, "Replacer"), $article->introtext);

Добавил проверку:

Код
		if (empty($article->text) && !empty($article->introtext)) {
$article->introtext = preg_replace_callback($regex, array($this, "Replacer"), $article->introtext);
} else {
$article->text = preg_replace_callback($regex, array($this, "Replacer"), $article->text);
}


Все, проблема решена.

Огромное спасибо prometheus, который не прошел мимо, а навел, так сказать, на путь истинный!
*

Captain

  • Осваиваюсь на форуме
  • 48
  • 1 / 0
Да, тоже столкнулся с этой проблемой. В твоем случае все решилось, а в моем случае действия зависят от id статьи ) Так что все не так просто...
*

Captain

  • Осваиваюсь на форуме
  • 48
  • 1 / 0
В принципе, в плагине нужно создать переменную для хранения id и в onContentBeforeDisplay ее устанавливать, а в onContentPrepare проверять, есть ли id  во входном параметре, и если нет, то брать его из переменной.
*

Captain

  • Осваиваюсь на форуме
  • 48
  • 1 / 0
Чорт, так тоже не работает. onContentBeforeDisplay вызывается после onContentPrepare и в блоге все "съезжает" на обработку следующей статьи.
Чтобы оставить сообщение,
Вам необходимо Войти или Зарегистрироваться
 

Как и чем можно обращаться с запросами из Joomla к GraphQL?

Автор bmf1982

Ответов: 0
Просмотров: 947
Последний ответ 03.10.2019, 15:46:00
от bmf1982
Joomla как система авторизации

Автор kav

Ответов: 23
Просмотров: 2807
Последний ответ 29.04.2018, 11:10:30
от Aleks.Denezh
Нужна помощь в доработке модуля под Joomla 3

Автор kik84

Ответов: 5
Просмотров: 2795
Последний ответ 30.01.2018, 22:40:30
от Елeна
Как отучить Joomla стартовать session для гостей?

Автор commeta

Ответов: 8
Просмотров: 3495
Последний ответ 20.08.2015, 14:06:38
от acyp
Модуль отправки сообщений для Joomla 1.5 и 2.5 (ajax)

Автор gaalferov

Ответов: 7
Просмотров: 6137
Последний ответ 02.06.2015, 18:05:52
от gaalferov