Блог на G-Drive

Решила собрать блог на G-Drive (этот сайт) и по горячим следам описать основные используемые при этом приемы. И вот что у меня получилось...

Блог обычно имеет структуру, при которой основной список статей размещается непосредственно на главной странице сайта. Кроме того, в блоге также присутствуют дополнительные списки статей, сгруппированных по какому-либо признаку (категория статьи, временной период публикации статьи и т.п.). Было бы вполне логично сделать так, чтобы за формирование и вывод всех списков статей отвечал один и тот же модуль. Т.к. списки статей размещаются не в одной категории (в терминах G-Drive каждая запись таблицы site_categories представляет собой отдельную категорию), в таблице site_categories необходимо определить поле module и поместить в него имя модуля, отвечающего за формирование и вывод всех списков статей. Категории статей можно разместить непосредственно в таблице site_categories, но лучше это сделать в отдельной таблице, чтобы не смешивать их с другими страницами блога, особенно с учетом того, что статьи блога также могут быть размещены в таблице site_categories, чтобы упростить их адресацию. В итоге получается следующее:

Таблица site_categories
artidname...categorybitsmodule
0Блог разработчиков...052category
1categoryКатегории статей...059category
10g-drive-dbe-3Знакомьтесь: G-Drive DBE 3...252article
11g-drive-blogБлог на G-Drive...252article
Таблица site_category
categoryidname...
1gencyGency...
2g-driveG-Drive...

Для формирования списка статей определенной категории на соответствующей странице может быть использован следующий запрос:

SELECT * FROM `site_categories` WHERE `category`={$page['category']}

Для формирования основного списка статей на главной странице сайта может быть использован следующий запрос:

SELECT * FROM `site_categories` WHERE `category`!=0

Сравнение "!=0" в условии отбора можно опустить.

В G-Drive признаком обращения к главной странице сайта является наличие пустой строки в $px (а также в $p0 и в $r0['id']). Выполнение соответствующей проверки с объединением двух описанных выше запросов в один и базовый код для осуществления постраничной навигации представлены ниже:

// можно использовать просто $page['category'],
// т.к. для главной страницы $page['category'] содержит 0
$category = strlen($px) ? $page['category'] : 0;

$pp = 5;

$pc = articles\pagecount($pp, $category);

rotate01();
if ($pn == 0 || $pn > $pc)
{
  error(404);
  return;
}

$result = articles\page($pn, $pp, $category, ['date' => ORDER_DESC]);

Функции page и pagecount:

namespace articles;

function page($pn = 0, $pp = 10, $category = 0, $order = [])
{
  $query = 'SELECT * FROM `site_categories` WHERE `category`';

  if ($category)
  {
    $query .= '='.$category;
  }

  $query .= ' ORDER BY '.\order($order);

  if ($pn)
  {
    $query .= ' LIMIT '.(($pn - 1) * $pp).','.$pp;
  }

  return \query($query);
}

function pagecount($pp = 10, $category = 0)
{
  $query = 'SELECT COUNT(*) FROM `site_categories` WHERE `category`';

  if ($category)
  {
    $query .= '='.$category;
  }

  $result = \query($query);
  list($count) = $result->fetch_row();
  $result->free();

  return (int)(($count + $pp - 1) / $pp);
}

Условие `category`!=0 (или просто `category`) позволяет исключить из основного списка статей не требующие публикации статьи, т.е. статьи все-таки будут опубликованы, но они не будут отображаться в основном списке статей. Чтобы исключить статьи с нулевым идентификатором категории и из дополнительных списков, необходимо отказаться от использования категории с нулевым идентификатором. Также можно использовать более универсальное условие `category`!=0 AND `category`={$page['category']}, которое за счет изменения второй части позволяет группировать статьи по разным признакам и при этом исключить из списков не требующие публикации статьи (с нулевым идентификатором категории).

Как показано в первой таблице, нулевой идентификатор категории имеют не только не требующие публикации статьи, но и другие страницы или служебные записи. Чтобы отделить статьи от всех прочих записей таблицы site_categories, у этих записей в поле category можно установить значение/признак NULL. Такой способ часто более предпочтителен, чем, например, использование для данной цели поля module. Отделять статьи нужно, например, для создания коллекции статей, чтобы их можно было редактировать в Gency.

Вот и все, что я хотела написать в данной статье. Жду ваших вопросов и комментариев.

Комментарии: 2

  1. Юлия

    По просьбам коллег решила добавить разделение статей по авторам. Развивая изложенную в конце статьи идею, для главной страницы сайта можно использовать запрос с условием отбора `category`!=0, а для страниц со списками статей определенного автора или определенной категории – соответственно `category`!=0 AND `author`={$page['author']} или `category`!=0 AND `category`={$page['category']} (предполагается, что в таблице site_author по аналогии с таблицей site_category используется поле author для хранения идентификаторов авторов статей). Как видно, два последних запроса будут отличаться друг от друга только именем поля во второй части условия отбора. Имя этого поля совпадает со значением поля id таблицы site_categories (доступно в $p0 и в $r0['id']). Т.е. можно использовать универсальное условие `category`!=0 AND `{$p0}`={$page[$p0]}.

  2. Юлия

    После добавления авторов мне понадобилось выводить в списках статей метаданные авторов (имена для адреса и текста ссылок, например june и Юлия). Конечно, можно было просто добавить в основной запрос из кода, приведенного в статье, фрагмент LEFT JOIN `site_author` USING(`author`) и т.п., но у меня был более универсальный код articles, который можно использовать следующим образом:

    $filter = [];
    
    $meta = ['author' => []];
    
    // это аналог условия strlen($px) из статьи
    if (isset($r1))
    {
      $filter[$r0['id']] = $page[$r0['id']];
    
      if (array_key_exists($r0['id'], $meta))
      {
        $meta[$r0['id']] = [$page['id'], $page['name']];
      }
    }
    
    $pp = 5;
    
    $pc = articles\pagecount($pp, $filter);
    
    rotate01();
    if ($pn == 0 || $pn > $pc)
    {
      error(404);
      return;
    }
    
    $result = articles\page($pn, $pp, $filter, $meta, ['date' => ORDER_DESC]);
    

    Содержимое $meta можно было не менять после инициализации, но функция page позволяет использовать метаданные, которые выбираются движком автоматически, вместо показанного выше LEFT JOIN. Например, на странице списка моих статей по адресу /author/june имена june и Юлия доступны соответственно в переменных $page['id'] и $page['name']. При получении этих данных функция подставит их в запрос, чтобы результат выборки не менялся по сравнению с запросом, в котором используется LEFT JOIN.

    Метаданные также нужны и на странице статьи, причем не только данные автора, но и данные категории (обратите внимание на ссылку сразу после текста статьи), однако эти данные непосредственно не связаны со списком комментариев, расположенным на странице статьи. Иными словами, для страниц статей можно использовать тот же самый универсальный код, но в нем нужно иметь отдельный массив признаков для выборки метаданных, связанных с собственным содержимым страницы, а не списком объектов страницы. Код обработки этого массива должен отличаться от показанного выше, т.к. основной запрос для страницы статьи выполняется движком автоматически и не предусматривает присоединения каких-то дополнительных данных. Эти данные можно выбирать отдельными запросами.

Отправить комментарий

Ваш адрес E-mail не будет опубликован.