Xpoint
   [напомнить пароль]

Помогите разобраться с mod_random в Joostina

Метки: [без меток]
[удл]
2010-09-02 07:46:07 [обр] Case[досье]
На сайте есть блок, в нём перечислены названия фирм с ссылками и они с помощью модуля mod_random (в движке Joostina)выводятся в случайном порядке, нужно сделать так чтобы одна из фирм всегда была в этом списке (не исчезала).
file: mod_randomnews.php
<?php
/**
* @package Joostina
* @copyright Авторские права (C) 2008 Joostina team. Все права защищены.
* @license Лицензия http://www.gnu.org/licenses/gpl-2.0.htm GNU/GPL, или help/license.php
* Joostina! - свободное программное обеспечение распространяемое по условиям лицензии GNU/GPL
* Для получения информации о используемых расширениях и замечаний об авторском праве, смотрите файл help/copyright.php.
*/

// запрет прямого доступа
defined( '_VALID_MOS' ) or die();

global $mosConfig_offset, $mosConfig_live_site, $mainframe,$my,$moduleclass_sfx;

$type      = intval( $params->get( 'type', 1 ) );
$count      = intval( $params->get( 'count', 5 ) );
$catid      = trim( $params->get( 'catid' ) );
$secid      = trim( $params->get( 'secid' ) );
$noncss      = intval( $params->get( 'noncss',0 ) );
$show_front   = $params->get( 'show_front', 0 );
$def_itemid   = $params->get( 'def_itemid', false );


$now      = _CURRENT_SERVER_TIME;
$access   = !$mainframe->getCfg( 'shownoauth' );
$nullDate = $database->getNullDate();  

// Выбор между выводом содержимого объектов, статического содержимого или сразу обоих
switch ( $type ) {
   case 2: 
   //Только статическое содержимое
      $query = "SELECT a.id, a.title"
      . "\n FROM #__content AS a"
      . "\n WHERE ( a.state = 1 AND a.sectionid = 0 )"
      . "\n AND ( a.publish_up = " . $database->Quote( $nullDate ) . " OR a.publish_up <= " . $database->Quote( $now ) . " )"
      . "\n AND ( a.publish_down = " . $database->Quote( $nullDate ) . " OR a.publish_down >= " . $database->Quote( $now ) . " )"
      . ( $access ? "\n AND a.access <= " . (int) $my->gid : '' )
      . "\n ORDER BY RAND() DESC"
      ;
      $database->setQuery( $query, 0, $count );
      $rows = $database->loadObjectList();
      break;

   case 3: 
      //Оба типа
      $whereCatid = '';
      if ($catid) {
         $catids = explode( ',', $catid );
         mosArrayToInts( $catids );
         $whereCatid = "\n AND ( a.catid=" . implode( " OR a.catid=", $catids ) . " )";
      }
      $whereSecid = '';
      if ($secid) {
         $secids = explode( ',', $secid );
         mosArrayToInts( $secids );
         $whereSecid = "\n AND ( a.sectionid=" . implode( " OR a.sectionid=", $secids ) . " )";
      }
      $query = "SELECT a.id, a.title, a.sectionid, a.catid, cc.access AS cat_access, s.access AS sec_access, cc.published AS cat_state, s.published AS sec_state"
      . "\n FROM #__content AS a"
      . "\n LEFT JOIN #__content_frontpage AS f ON f.content_id = a.id"
      . "\n LEFT JOIN #__categories AS cc ON cc.id = a.catid"
      . "\n LEFT JOIN #__sections AS s ON s.id = a.sectionid"
      . "\n WHERE a.state = 1"
      . "\n AND ( a.publish_up = " . $database->Quote( $nullDate ) . " OR a.publish_up <= " . $database->Quote( $now ) . " )"
      . "\n AND ( a.publish_down = " . $database->Quote( $nullDate ) . " OR a.publish_down >= " . $database->Quote( $now ) . " )"
      . ( $access ? "\n AND a.access <= " . (int) $my->gid : '' )
      . $whereCatid
      . $whereSecid
      . ( $show_front == '0' ? "\n AND f.content_id IS NULL" : '' )
      . "\n ORDER BY RAND() DESC" 
      ;
      $database->setQuery( $query, 0, $count );
      $temp = $database->loadObjectList();

      $rows = array();
      if (count($temp)) {
         foreach ($temp as $row ) {
            if (($row->cat_state == 1 || $row->cat_state == '') &&  ($row->sec_state == 1 || $row->sec_state == '') &&  ($row->cat_access <= $my->gid || $row->cat_access == '' || !$access) &&  ($row->sec_access <= $my->gid || $row->sec_access == '' || !$access)) {
               $rows[] = $row;
            }
         }
      }
      unset($temp);
      break;

   case 1:
   default:
      //Только содержимое объектов
      $whereCatid = '';
      if ($catid) {
         $catids = explode( ',', $catid );
         mosArrayToInts( $catids );
         $whereCatid = "\n AND ( a.catid=" . implode( " OR a.catid=", $catids ) . " )";
      }
      $whereSecid = '';
      if ($secid) {
         $secids = explode( ',', $secid );
         mosArrayToInts( $secids );
         $whereSecid = "\n AND ( a.sectionid=" . implode( " OR a.sectionid=", $secids ) . " )";
      }
      $query = "SELECT a.id, a.title, a.sectionid, a.catid"
      . "\n FROM #__content AS a"
      . "\n LEFT JOIN #__content_frontpage AS f ON f.content_id = a.id"
      . "\n INNER JOIN #__categories AS cc ON cc.id = a.catid"
      . "\n INNER JOIN #__sections AS s ON s.id = a.sectionid"
      . "\n WHERE ( a.state = 1 AND a.sectionid > 0 )"
      . "\n AND ( a.publish_up = " . $database->Quote( $nullDate ) . " OR a.publish_up <= " . $database->Quote( $now ) . " )"
      . "\n AND ( a.publish_down = " . $database->Quote( $nullDate ) . " OR a.publish_down >= " . $database->Quote( $now ) . " )"
      . ( $access ? "\n AND a.access <= " . (int) $my->gid . " AND cc.access <= " . (int) $my->gid . " AND s.access <= " . (int) $my->gid : '' )
      . $whereCatid
      . $whereSecid
      . ( $show_front == '0' ? "\n AND f.content_id IS NULL" : '' )
      . "\n AND s.published = 1"
      . "\n AND cc.published = 1"
      . "\n ORDER BY RAND() DESC"
      ;
      $database->setQuery( $query, 0, $count );
      $rows = $database->loadObjectList();
      break;
}

if(!$def_itemid>0){
   // требование уменьшить запросы, используемые getItemid для объектов содержимого
   if ( ( $type == 1 ) || ( $type == 3 ) ) {
      $bs   = $mainframe->getBlogSectionCount();
      $bc   = $mainframe->getBlogCategoryCount();
      $gbs   = $mainframe->getGlobalBlogSectionCount();
   }
}
// Вывод
?>
<ul class="latestnews<?php echo $moduleclass_sfx; ?>">
<?php
foreach ( $rows as $row ) {
   // get Itemid
   if(!$def_itemid>0){
      switch ( $type ) {
         case 2:
            $query = "SELECT id"
            . "\n FROM #__menu"
            . "\n WHERE type = 'content_typed'"
            . "\n AND componentid = " . (int) $row->id
            ;
            $database->setQuery( $query );
            $Itemid = $database->loadResult();
            break;

         case 3:
            if ( $row->sectionid ) {
               $Itemid = $mainframe->getItemid( $row->id, 0, 0, $bs, $bc, $gbs );
            } else {
               $query = "SELECT id"
               . "\n FROM #__menu"
               . "\n WHERE type = 'content_typed'"
               . "\n AND componentid = " . (int) $row->id
               ;
               $database->setQuery( $query );
               $Itemid = $database->loadResult();
            }
            break;

         case 1:
         default:
            $Itemid = $mainframe->getItemid( $row->id, 0, 0, $bs, $bc, $gbs );
            break;
      }
   }else{
      $Itemid=$def_itemid;
   }

   // Очистка счетчика itemid для SEF
   if ($Itemid == NULL) {
      $Itemid = '';
   } else {
      $Itemid = '&amp;Itemid='. $Itemid;
   }

   $link   = sefRelToAbs( 'index.php?option=com_content&amp;task=view&amp;id='. $row->id . $Itemid );
   $class   = ($noncss ? '':' class="latestnews'.$moduleclass_sfx.'"');
   ?>
   <li<?php echo $class ?>>
      <a href="<?php echo $link; ?>" title="<?php echo $row->title; ?>"<?php echo $class ?>><?php echo $row->title; ?></a>
   </li>
   <?php
}
?>
</ul>
file: mod_randomnews.xml
<?xml version="1.0" encoding="windows-1251"?>
<mosinstall type="module" version="1.0.0">
   <name>Случайные новости</name>
   <author>Joostina! Project</author>
   <creationDate>Июнь 2008</creationDate>
   <copyright>(C) 2008 Joostina team.</copyright>
   <license>http://www.gnu.org/licenses/gpl-2.0.htm GNU/GPL</license>
   <authorEmail>joostinacms@gmail.com</authorEmail>
   <authorUrl>www.joostina.ru</authorUrl>
   <version>1.0.0</version>
   <description> Этот модуль показывает список случайных объектов, срок действия которых не истек (срок действия некоторых возможно уже истек, не смотря на то, что они были опубликованы недавно). Объекты, которые отображены в компоненте главной странице, не включены в этот список. </description>
   <files>
      <filename module="mod_randomnews">mod_randomnews.php</filename>
   </files>
   <params>
      <param name="moduleclass_sfx" type="text" default="" label="Суффикс класса модуля" description="Суффикс, который будет использован в описании класса (table.moduletable) таблицы стилей (CSS) модуля. Это позволяет использовать индивидуальный стиль модуля." />
      <param name="@spacer" type="spacer" default="" label="" description="" />
      <param name="cache" type="radio" default="0" label="Разрешить кэширование" description="Выберите, кэшировать ли содержимое этого модуля">
         <option value="0">Нет</option>
         <option value="1">Да</option>
      </param>
      <param name="noncss" type="radio" default="1" label="Отключить дублирование стилей" description="Удалить дублирование стилей на всю ветку ul-li-a">
         <option value="0">Нет</option>
         <option value="1">Да</option>
      </param>
      <param name="@spacer" type="spacer" default="" label="" description="" />
      <param name="type" type="list" default="0" label="Режим работы модуля" description="Позволяет Вам управлять типом отображаемого в модуле контента">
         <option value="1">Только содержимое объектов</option>
         <option value="2">Только статическое содержимое</option>
         <option value="3">Оба типа</option>
      </param>
      <param name="@spacer" type="spacer" default="" label="" description="" />
      <param name="show_front" type="radio" default="1" label="Объекты главной страницы" description="Показать/скрыть объекты, предназначенные для главной страницы. Эта опция работает, если выбран режим - Только содержимое объектов">
         <option value="1">Показать</option>
         <option value="0">Скрыть</option>
      </param>
      <param name="count" type="text" default="5" label="Число объектов" description="Количество отображаемых объектов (по умолчанию -5)" />
      <param name="catid" type="text" default="" label="Идентификатор (ID) категории" description="Выбор объектов из определенных категорий, или набора категорий (для выбора более одной категории, разделяйте их запятой , )." />
      <param name="secid" type="text" default="" label="Идентификатор (ID) раздела" description="Выбор объектов определенных секций или набора секций (для выбора более одной секции, разделяйте их запятыми , )." />
      <param name="def_itemid" type="text" default="0" label="ItemId по умолчанию" description="Параметр ItemId для ссылок. 0 для ипользования автоматического рассчета." />
   </params>
спустя 33 минуты [обр] Василий Свиридов(53/175)[досье]
Подход в лоб - добавить в запрос, который вытягивает компании UNION с запросом для той компании, котрая нужна всегда, и добавить WHERE ... NOT в оригинальный запрос, чтобы не выводились дубликаты.
спустя 6 часов [обр] Алексей Севрюков(162/1280)[досье]

Можно через сортировку, к таблице фирм добавить поле sort TINYINT DEFAULT 0, для фирмы, которая должна быть наверху - sort=1, а запросе меняем:

ORDER BY rand() DESC

на

ORDER BY !sort, rand() DESC

если хотим оставить несколько фирм, то делаем по принципу - чем больше значение sort, тем выше фирма в списке. Запрос:

ORDER BY sort DESC, rand() DESC

Универсально, и без всяких UNION, который каждый раз придется менять, тогда как в этом варианте достаточно поменять значения полей в базе (напрямую, или через CMS).

спустя 2 часа 58 минут [обр] Филипп Ткачев(20/112)[досье]
И не забудьте создать индекс для поля sort - благоприятно скажется на производительности.
спустя 19 дней [обр] Case[досье]
Спасибо Алексей, помогло вот такая строчка получилась
 . "\n GROUP BY a.title ORDER BY a.sort desc, RAND() DESC"
спустя 16 часов [обр] Василий Свиридов(53/175)[досье]
ORDER BY RAND() это ужасно в плане производительности, т.к. FULL SCAN. Чем больше данных в таблице - тем медленнее будет работать, и индексы не сильно помогут.
спустя 3 часа 47 минут [обр] Филипп Ткачев(20/112)[досье]
А если сначала посчитать число строк в таблице, а потом сделать запрос с LIMIT быстрый_рандом_от_числа_строк, 1
спустя 13 часов [обр] Василий Свиридов(53/175)[досье]
Это уже лучше.
Powered by POEM™ Engine Copyright © 2002-2005