Комментарии

Вспомогательный файл модуля PHP (часть 3)
( 0 Голосов )

В следующей строке кода вызывается метод setQuery () для объекта $db. Этот метод устанавливает поле в объекте базы данных, но на самом деле он не выполняет запрос. Это делается в строке

$currentArticle =  $db->loadObject();

где в качестве значения возвращается объект.

Очень важно понять, что результаты запросов могут быть получены самыми разными методами. Для этой цели обычно применяются следующие методы.

  • Метод loadObject (). Возвращает первую строку из запроса в виде объекта, где каждый столбец из строки является полем данного объекта.
  • Метод loadObjectList (). Возвращает массив всех строк из запроса, где каждый элемент массива является объектом из данной строки.
  • Метод loadResult (). Возвращает первый столбец из первой строки запроса.

Выбор конкретного метода зависит от типа запроса. В данном примере заранее известно, что в результате запроса будет возвращена максимум одна строка, поскольку выбирается строка, имеющая идентификатор (id) в качестве одного из значений. Каждый идентификатор в таблице #content не похож на остальные, а следовательно, в результате запроса нельзя получить больше одной строки. Именно поэтому и вызывается метод loadObject (), возвращающий первую строку из запроса.

Если бы нам потребовался только первый столбец из первой строки, мы могли бы вызвать метод loadResult (). А если бы нам потребовалось несколько строк из запроса, мы бы, скорее всего, вызвали метод loadObjectList (). Имеются также методы для заполнения массивов результатами запроса вместо объектов. Такие методы можно обнаружить в классе JDatabaseH3 файла libraries/ joomla/database/database.php.

Итак, мы получили три столбца для текущей статьи в переменной $currentArtide. В листинге ниже приведена третья часть вспомогательного файла РНР.

Исходный код из файла helper.php (часть 3)

// запросить базу данных с целью получить статьи текущего автора
$query->clear();
$query->select('а.*');
$query->select('с.access AS cat_access, с.published AS cat_state, c.alias AS cat_alias') ;
$query->from('#content AS  a');
// для ссылки на  статьи и проверки прав доступа к ним
//  требуются  сведения  о  категории
$query->leftJoin ('#categories AS  с ON с. id = -'a.catid') ;
//  показывать  только  опубликованные  статьи $query->where('a.state =  1'); $query->where('с.published =  1')
// показывать только место доступа к статье и категории $query->where('a.access IN (' . $levels . ')'); $query->where('с.access IN (' . $levels . ')');
// показывать только место, где статьи опубликованы в настоящий момент $query->where('(a.publish_up = '.$db->Quote($nullDate).' OR a.publish_up <= '.$db->Quote<$now) .')');
$query->where('(a.publish_down = '.$db->Quote($nullDate).' OR a.publish_down >= '.$db->Quote($now).')');
// проверить автора статьи
if ($currentArticle->created_by_alias) {
// если у текущей статьи имеется псевдоним автора, проверить на совпадение столбец created_by или created_by_alias $query->where('(a.created_by =' . (int) $currentArticle->
created_by . * OR ' . 'a.created_by_alias =' . $db- >quote($currentArticle->created_by_alias) . ')');
} else {
// если у текущей статьи отсутствует псевдоним автора, проверить
//на совпадение только столбец created_by column
$query->where('a.created_by =' . (int) $currentArticle->created_by);
}

В этой части исходного кода из вспомогательного файла РНР начинается формирование основного запроса. Сначала старый запрос очищается с помощью метода clear (), а затем составляются критерии выборки информации из базы данных. Синтаксическая конструкция "а. *" предписывает базе данных включить в запрос все столбцы из таблицы "а". Для данного модуля из таблицы # content требуется выбрать лишь несколько столбцов: название статьи, идентификатор и категорию. Не следует, однако, забывать, что всем пользователям разрешается составлять альтернативные компоновки для данного модуля, и поэтому заранее неизвестно, какие именно сведения о статьях предполагается отображать с помощью этих компоновок.

Базе данных не потребуется много времени, чтобы извлечь все нужные столбцы из таблицы #content, что дает максимум удобств для составления всех последующих компоновок. В данный запрос включены также столбцы access, published и alias из таблицы #categories. Они указываются в запросе с префиксом "с. " этой таблицы, как показано ниже.

$query->select('с.access  AS  cat_access,   с.published AS  cat_state,   с.alias AS  cat_alias');

В разных таблицах нередко используются одинаковые имена столбцов. Например, в обеих таблицах, #content и #categories, имеются столбцы access и alias. Ре
зультаты данного запроса будут возвращены в виде объекта, где имя столбца совпадает с именем поля. Следовательно, когда имена столбцов дублируются, их нужно изменить в запросе. И это делается с помощью псевдонима столбца AS таким же образом, как и для псевдонимов таблиц. Например, выражение с.access AS cat_access означает, что в результате запроса будет возвращено значение из столбца access для таблицы #categories со столбцом cataccess. Подобным образом можно отличить столбец access для доступа к статье от столбца cataccess для доступа к категории.

В следующей строке кода таблица #content обозначается как первая таблица в запросе с помощью псевдонима "а". Как правило, первой в запросе обозначается основная таблица, но в данном случае нас больше всего интересует информация из таблицы #content.

Далее следует строка кода

$query->leftJoin('#categories  AS  с  ON  с.id = a.catid');

где применяется соединение — способ ввода информации из другой таблицы в запрос. В данном случае три столбца из таблицы # categories вводятся в каждую строку запроса. Как же тогда узнать, какую именно строку из таблицы #categories следует использовать? На это указывает оператор ON. Выражение ON с. id = а. cat id' предписывает базе данных найти строку в таблице # categories, где столбец id совпадает со столбцом catidn3 таблицы #content.

Для этой цели вызывается метод left Join (). Таблицы из базы данных могут быть соединены в запросе разными способами. Чаще всего используются левое и внутреннее соединения. Как правило, они делают одно и то же, а отличаются лишь тем, что именно происходит, если во второй таблице отсутствует строка, совпадающая со значением в операторе ON. При левом соединении в любых столбцах, выбираемых из второй таблицы, устанавливается пустое значение NULL. А при внутреннем соединении вся строка из первой таблицы исключается из запроса.

Для рассматриваемого здесь запроса это не имеет никакого значения. Если база данных не испорчена, то можно ожидать получение вполне достоверной категории для каждой статьи. Но если по какой-нибудь причине категория статьи удалена, эта статья все равно останется в запросе. А если бы нам понадобилось исключить из запроса статьи, для которых отсутствует категория, мы бы тогда вызвали метод inner Join () вместо метода leftJoin().

Далее следует целый ряд вызовов метода where () для задания критериев выборки информации по данному запросу. В первых двух вызовах метода where () указывается требование, чтобы статья и ее категория были опубликованы. Следует заметить, что в таблице статей для отметки состояния "опубликовано" используется столбец state, тогда как в таблице категорий — столбец published. Единичное значение в обоих столбцах обозначает одно и то же: состояние "опубликовано".

А зачем вообще знать, опубликована ли категория? Дело в том, что в Joomla категории служат своего рода вместилищами для статей и других видов содержимого, подобно папкам для файлов на жестком диске компьютера. Если категория установлена в состояние "не опубликовано" значит, и все стати этой категории должны быть установлены в состояние "не опубликовано". Именно это правило и соблюдается в первых двух вызовах метода where ().

Аналогичная логика применяется и к уровням доступа. Так, если доступ к категории ограничен, то ограничение накладывается и на все статьи данной категории. Напомним, что переменной $ levels присвоен разделяемый запятыми список уровней доступа пользователя к статьям для их просмотра. В операторе IN запроса SQL проверяется наличие значения в разделяемом запятыми списке. Так, в операторе

a.access   IN   (1,2,3)

проверяется, равно ли 1, 2 или 3 значение, извлекаемое из столбца a.access таблицы. Поэтому в рассматриваемом здесь коде в запрос вводятся два оператора IN: один — для доступа к статьям, другой — для доступа к категориям.

При построении символьной строки в методе where () следует проявлять особую аккуратность, употребляя открывающие и закрывающие круглые скобки. Вероятно, при дальнейшем усовершенствовании класса JDatabaseQuery в него будут добавлены методы, поддерживающие различные типы операторов сравнения, в том числе IN, BETWEEN, LIKE, = и т.д. И тогда можно будет воспользоваться выражением

$query->whereln('a.access',   $levels);

чтобы упростить операции сравнения типа IN и не вводить круглые скобки вручную. Но такие методы пока что отсутствуют. Впрочем, программное обеспечение постоянно совершенствуется, в особенности такой открытый проект, как Joomla. С другой стороны, можно и самостоятельно создать подкласс, производный от класса JDatabaseQuery, добавив в него нужные методы.

В следующем фрагменте кода проверяются даты начала и окончания публикации статьи (publish_up и publishdown), чтобы выяснить, опубликована ли статья на текущий момент. Для этой цели используются созданные ранее переменные $now и $ null Date. Необходимо проверить одно из двух:

  • начальная или конечная дата не введена или,
  • текущая дата находится в пределах между начальной и конечной датами.

Поэтому в данном фрагменте кода вводятся два оператора WHERE: один — для проверки начальной даты, другой — для проверки конечной даты, причем в каждом из них используется оператор OR. Обратите внимание на то, что все проверяемое значение заключается в круглые скобки. Например, результат вызова первого метода, реализующего оператор WHERE, может выглядеть следующим образом:

(a.published_up =   '0000-00-00  00:00:00'   OR a.publish_up <=   '2012-  12-  31  23:30:00')

Очень важно понять, что по умолчанию операторы WHERE, формируемые методом where (), связаны с оператором AND запроса SQL. Это означает, что все условия в операторах WHERE должны быть истинны для строки, извлекаемой по запросу. Но если поместить оба проверяемых условия в сигнатуре одного оператора where (), объединив их оператором OR и заключив в круглые скобки, то условие в операторах WHERE окажется истинным, если истинно любое из исходных условий, что, собственно, нам и требуется.

Кроме того, метод $db->quote () вызывается с целью заключить переменные $nullDate и $now в кавычки. И хотя заранее известно, что их значения действительны, кавычки все же нужны, поскольку эти значения могут содержать пробелы. Проверка конечной даты публикации организуется аналогичным образом. Но в данном случае проверяется, является ли текущая дата меньше конечной даты публикации.

В следующем фрагменте кода проверяется авторство статьи для текущего автора. Ранее было принято решение составить список всех статей, авторство которых совпадает со значениями в столбцах created by или created by alias. Но что если в столбце created_by_alias ничего не указано для текущей статьи. В таком случае проверка на совпадение со значением в столбце createdbyalias не должна производиться, поскольку нет никакого смысла показывать все остальные статьи с пустым значением в этом столбце. Поэтому сначала нужно проверить содержимое столбца created_by_alias для текущей статьи, а затем сформировать оператор WHERE в зависимости от того, что будет обнаружено в этом столбце. Если в столбце created_by_alias имеется какое-нибудь значение, оно используется в операторе WHERE следующим образом:

$query->where('(a.created_by ='. (int) $currentArticle->created__by'OR * . 'a.created_by_alias  = *V . $db->quote($currentArticle->created_by_alias) .')');

И в этом случае весь оператор WHERE заключается в круглые скобки.

Вторая часть условного оператора i f выполняется при условии, что столбец created_ by_alias пуст. В таком случае проверяется только значение в столбце created_by, как показано ниже.

$query->where('a.created_by =' . (int) $currentArticle->created_by);

Обратите внимание на то, что тип значения в столбце created_by специально приводится к целочисленному типу. Это значение и так должно быть целым, но во избежание программных ошибок значения, извлекаемые из столбцов таблицы, все-таки лучше специально приводить к нужному типу. А значение, извлекаемое из столбца created_by_alias, очень важно заключить в кавычки, вызвав метод $db->quote (). Ведь оно вводится пользователем в соответствующем поле при создании статьи, а следовательно, может оказаться каким угодно, в том числе и злонамеренным кодом. Если же заключить его в кавычки с помощью метода $db->quote (), то тем самым можно исключить внесение в запрос любого злонамеренного кода.


Понравился материал? Пригодилась информация? Плюсани в социалки!


 
Похожие новости
Добавить комментарий


Защитный код