Опубликован: 02.10.2012 | Доступ: свободный | Студентов: 1916 / 85 | Длительность: 11:48:00
Теги: joomla, mvc, php, xhtml, xml
Лекция 2:

Работа с базой данных

< Лекция 1 || Лекция 2: 123 || Лекция 3 >
Аннотация: Подробно рассмотрена работа с базой данных средствами Joomla. Рассмотрены понятия реального и символического префиксов, этапы выполнения запроса к базе данных и класс JTable.

Цель лекции: Изучить, как происходит работа с базой данных средствами Joomla.

Префикс таблиц базы данных

Префикс таблиц базы данных - это строка, которая присоединяется к названию каждой таблицы Joomla в базе данных. Префикс задается при установке Joomla. В старых версиях по умолчанию использовался префикс "jos_", однако это создавало потенциальную уязвимость сайта, т.к. хакеры знали название таблицы с паролями пользователей - "jos_users". Теперь префикс, предлагаемый при установке, генерируется случайным образом.

Использование префикса позволяет разместить в одной базе данных несколько установок Joomla.

Различают реальный и символический префиксы. Реальный префикс - это то конкретное сочетание символов, которое используется в названиях таблиц базы данных. Символический префикс - это сочетание "#__" (решетка и два знака подчеркивания), которое используется в запросах вместо реального префикса. При обработке запроса вместо символического префикса будет автоматически подставлен реальный. Например, при реальном префиксе "jos_" строка "#__mycomponent_mytable" превратится в "jos_mycomponent_mytable".

При разработке собственных расширений в SQL-запросах всегда указывается символический префикс, а не реальный, так как в других установках Joomla почти наверняка будут использоваться другие реальные префиксы.

Выполнение запроса к базе данных

Чтобы выполнить запрос к базе данных Joomla, необходимо осуществить пять операций:

  1. Получение ссылки на объект JDatabase.
  2. Формирование запроса.
  3. Задание запроса.
  4. Выполнение запроса.
  5. При необходимости - загрузка результата.

Получение ссылки на объект JDatabase

JDatabase - абстрактный класс, предоставляющий доступ к соединению с базой данных. Это соединение создается при инициализации приложения Joomla, а в коде своего расширения мы можем получить ссылку на него с помощью метода getDbo() статического класса JFactory:

$db =& JFactory::getDbo();
        

Формирование SQL-запроса

В старых версиях Joomla запросы формулировались в виде строки:

$query = 'SELECT * FROM #__categories';
        

В Joomla 1.6 появился объект JDatabaseQuery, методы которого позволяют упростить создание сложных SQL-запросов. Названия этих методов практически совпадают с ключевыми словами языка SQL: select(), from(), where(), having(), join() и т.д. Использование объекта JDatabaseQuery иллюстрирует следующий пример:

$db =&  JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('id, name');
$query->from('#__users');
$query->order('name');
$query->where('username LIKE \'a%\'');
$db->setQuery($query);
echo $query->__toString();
        

В данном примере мы получаем из таблицы #__users отсортированный по алфавиту список id и имен пользователей, чьи логины начинаются на букву "a". Данный код выведет на экран следующий SQL-запрос:

SELECT id, name FROM #__users WHERE username LIKE 'a%' ORDER BY name
        

Как известно, употребляющиеся в запросе названия полей и таблиц рекомендуется заключать в ограничители, чтобы избежать совпадений с зарезервированными словами. Кроме того, строковые значения в запросах также берутся в кавычки. Методы nameQuote() и Quote() заключают, соответственно, названия и значения в правильные ограничители. Для MySQL это обратные апострофы (``) для названий и обычные апострофы ('') для значений.

Рассмотрим пример использования этих методов:

$query = 'SELECT * FROM '.$db->nameQuote('#__users').' WHERE '.$db->nameQuote('username').'='.$db->Quote('admin');
        

Для базы данных MySQL с префиксом таблиц jos_ переменная $query примет следующее значение:

SELECT * FROM `jos_users` WHERE `username`='admin';
        

Задание запроса

Чтобы задать SQL-запрос для последующего выполнения, используется метод:

JDatabase setQuery(string $query, string $offset=0, string $limit=0)
        

где $query - это запрос, а $offset и $limit - соответственно смещение для начала выборки и количество выбираемых строк.

Например:

$db->setQuery($query, 0, 10);
        

Обратите внимание, что метод setQuery() не выполняет запрос, а только задает его.

Выполнение запроса

Без выборки данных

Для выполнения запроса, не требующего выборки данных (например, UPDATE или INSERT), используется метод mixed query().

При успешном выполнении запроса метод возвращает указатель на его результат, в противном случае - false. Например:

$db =& JFactory::getDBO();
$query = "UPDATE #__users SET block = 0 WHERE username LIKE 'a%'";
$db->setQuery($query);
$result = $db->query();
            
С выборкой данных

В классе JDatabase существуют методы для получения форматированного результата. Их можно разделить на следующие группы:

  1. Получение одного значения: loadResult().
  2. Получение одной строки таблицы: loadRow(), loadAssoc(), loadObject().
  3. Получение одного столбца таблицы: loadResultArray().
  4. Получение нескольких строк и нескольких столбцов: loadRowList(), loadAssocList(), loadObjectList().

Рассмотрим каждый из этих методов на примере таблицы #__categories, использующейся Joomla ( таблица 2.1).

Таблица 2.1. Таблица #__categories
id asset_id parent_id lft rgt level path extension language
1 0 0 0 11 0 system *
2 27 1 1 2 1 uncategorised com_content *
3 28 1 3 4 1 uncategorised com_banners *
4 29 1 5 6 1 uncategorised com_contact *
5 30 1 7 8 1 uncategorised com_newsfeeds *
6 31 1 9 10 1 uncategorised com_weblinks *
mixed loadResult()

Метод загружает значение первого столбца первой строки результирующей выборки. Используется для получения из базы данных какого-либо одного значения. При ошибке выполнения запроса метод вернет null, как и все рассмотренные ниже методы выборки данных.

Например, получим значение поля extension в записи под номером 2:

$db =& JFactory::getDbo();
$query = 'SELECT '.$db->nameQuote('extension').
      ' FROM '.$db->nameQuote('#__categories').
      ' WHERE '.$db->nameQuote('id').'='.$db->Quote('2');
$db->setQuery($query);
echo $db->loadResult();
                

Результатом выполнения данного запроса будет значение "com_content".

array loadRow()

Загружает первую строку результирующей выборки в виде массива. Если запрос возвращает больше одной строки, то метод вернет первую из них.

$db =& JFactory::getDbo();
$query = 'SELECT * FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadRow());
                

Результатом запроса будет следующий список (будем называть списком массив, индексами которого являются числа 0, 1, 2 и т.д.):

Array([0]=>1 [1]=>0 [2]=>0 [3]=>0 [4]=>11 [5]=>0 [6]=> [7]=>system [8]=>ROOT
 [9]=>root [10]=> [11]=> [12]=>1 [13]=>0 [14]=>0000-00-00 00:00:00 
[15]=>1 [16]=>{} [17]=> [18]=> [19]=> [20]=>0 [21]=>2009-10-18 16:07:09
 [22]=>0 [23]=>0000-00-00 00:00:00 [24]=>0 [25]=>*)
                
array loadAssoc()

Метод загружает первую строку результирующей выборки в виде ассоциативного массива, ключами которого становятся названия полей таблицы. Если запрос возвращает больше одной строки, то метод вернет первую из них.

$db =& JFactory::getDbo();
$query = 'SELECT * FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadAssoc());
                

Результат запроса:

Array([id]=>1 [asset_id]=>0 [parent_id]=>0 [lft]=>0 [rgt]=>11 [level]=>0 [path]=> [extension]=
>system [title]=>ROOT [alias]=>root [note]=> [description]=> 
[published]=>1 [checked_out]=>0 [checked_out_time]=>0000-00-00 00:00:00 [access]=
>1 [params]=>{} [metadesc]=> [metakey]=> [metadata]=> [created_user_id]=>0 
[created_time]=>2009-10-18 16:07:09 [modified_user_id]=
>0 [modified_time]=>0000-00-00 00:00:00 [hits]=>0 [language]=>*)
                
object loadObject()

Метод загружает первую строку результирующей выборки в виде объекта класса stdClass, причем его полями становятся названия полей таблицы. Если запрос возвращает больше одной строки, то метод вернет первую из них.

$db =& JFactory::getDbo();
$query = 'SELECT * FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadObject());
                

Результат запроса:

stdClass Object([id]=>1 [asset_id]=>0 [parent_id]=>0 [lft]=>0 [rgt]=>11 [level]=
>0 [path]=> [extension]=>system [title]=>ROOT [alias]=>root [note]=> 
[description]=> [published]=>1 [checked_out]=>0 [checked_out_time]=>0000-00-00 00:00:00 [access]=
>1 [params]=>{} [metadesc]=> [metakey]=> [metadata]=> 
[created_user_id]=>0 [created_time]=>2009-10-18 16:07:09 [modified_user_id]=>0 [modified_time]=
>0000-00-00 00:00:00 [hits]=>0 [language]=>*)
                
array loadResultArray(int numinarray=0)

Метод загружает массив значений из результирующей выборки, полученных из одного столбца. Параметр numinarray используется для указания того, какой столбец нужно вернуть.

$db =& JFactory::getDbo();
$query = 'SELECT '.$db->nameQuote('extension').
      ' FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadResultArray()); 
                

Результатом будет следующий список:

Array([0]=>com_banners [1]=>com_contact [2]=>com_content [3]=>com_newsfeeds [4]=>com_weblinks [5]=>system)
                

Данный метод позволяет перебирать в цикле столбцы таблицы:

$db =& JFactory::getDbo();
$query = 'SELECT '.$db->nameQuote('path').','.$db->nameQuote('extension').','.$db->nameQuote('language').
' FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
for ($i = 0; $i <= 2; $i++)
{
  $column = $db->loadResultArray($i);
  print_r($column);
  echo "<br>";
}
                

В результате на экран будет выведено:

Array([0]=> [1]=>uncategorised [2]=>uncategorised [3]=
>uncategorised [4]=>uncategorised [5]=>uncategorised)
Array([0]=>system [1]=>com_content [2]=>com_banners [3]=
>com_contact [4]=>com_newsfeeds [5]=>com_weblinks)
Array([0]=>* [1]=>* [2]=>* [3]=>* [4]=>* [5]=>*)
                
array loadRowList(int key)

Метод загружает список массивов или ассоциативный массив массивов. Если задан параметр key, то ключами возвращаемого массива будут значения поля, идущего в таблице под номером key, начиная с нуля.

$db =& JFactory::getDbo();
$query = 'SELECT * FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadRowList(7));
                

В данном примере из таблицы #__categories ядра Joomla извлекаются все записи, причем ключами полученного массива будут значения столбца №7, т.е. поля extension:

Array
(
  [system]=>Array([0]=>1   … [25]=>*)
  [com_content]=>Array([0]=>2   … [25]=>*) 
  [com_banners]=>Array([0]=>3   … [25]=>*) 
  [com_contact]=>Array([0]=>4   … [25]=>*) 
  [com_newsfeeds]=>Array([0]=>5 … [25]=>*) 
  [com_weblinks]=>Array([0]=>6 … [25]=>*)
)
                

Если не указать параметр key, то вместо ассоциативного массива мы получим список:

Array
(
  [0]=>Array([0]=>1 … [25]=>*)
  [1]=>Array([0]=>2 … [25]=>*) 
  [2]=>Array([0]=>3 … [25]=>*) 
  [3]=>Array([0]=>4 … [25]=>*) 
  [4]=>Array([0]=>5 … [25]=>*) 
  [5]=>Array([0]=>6 … [25]=>*)
)
                
array loadAssocList(string key='', string column='')

Метод загружает список ассоциативных массивов или ассоциативный массив ассоциативных массивов. Если задан параметр key, то ключами полученного массива будут значения столбца под названием key. Если задан параметр column, то в полученном массиве будет всего один столбец column.

$db =& JFactory::getDbo();
$query = 'SELECT * FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadAssocList('extension'));
                

Результат запроса:

Array
(
  [system]=>Array([id]=>1 [asset_id]=>0 ... [language]=>*)
  [com_content]=>Array([id]=>2 [asset_id]=>27 ... [language]=>*) 
  [com_banners]=>Array([id]=>3 [asset_id]=>28 ... [language]=>*) 
  [com_contact]=>Array([id]=>4 [asset_id]=>29 ... [language]=>*) 
  [com_newsfeeds]=>Array([id]=>5 [asset_id]=>30 ... [language]=>*) 
  [com_weblinks]=>Array([id]=>6 [asset_id]=>31 ... [language]=>*)
)
                

Как видим, ключи полученного массива - это значения поля extension, заданного параметром в метод loadAssocList().

Зададим значение второго параметра, чтобы получить только значение id для каждой строки таблицы:

$db =& JFactory::getDbo();
$query = 'SELECT * FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadAssocList('extension','id'));
                

Результат запроса:

Array([system]=>1 [com_content]=>2 [com_banners]=>3 [com_contact]=>4 [com_newsfeeds]=>5 [com_weblinks]=>6)
                
array loadObjectList(string key='')

Метод загружает список объектов stdClass или ассоциативный массив объектов stdClass. Если задан параметр key, то ключами полученного массива будут значения поля под названием key:

$db =& JFactory::getDbo();
$query = 'SELECT * FROM '.$db->nameQuote('#__categories');
$db->setQuery($query);
print_r($db->loadObjectList('extension'));
                

Результат запроса:

Array
(
  [system]=>stdClass Object([id]=>1 [asset_id]=>0 ... [language]=>*)
  [com_content]=>stdClass Object([id]=>2 [asset_id]=>27 ... [language]=>*)
  [com_banners]=>stdClass Object([id]=>3 [asset_id]=>28 ... [language]=>*)
  [com_contact]=>stdClass Object([id]=>4 [asset_id]=>29 ... [language]=>*)
  [com_newsfeeds]=>stdClass Object([id]=>5 [asset_id]=>30 ... [language]=>*)
  [com_weblinks]=>stdClass Object([id]=>6 [asset_id]=>31 .. [language]=>*)
)
                
< Лекция 1 || Лекция 2: 123 || Лекция 3 >
Кирилл Гусаров
Кирилл Гусаров

В разделе "Первые папки и файлы. Добавление пунктов меню"

предлагается создать две файла:

- myquestions.php;

- admin.myquestions.php

с соответствуюшими адресами:

/components/com_myquestions/myquestions.php;

- /administrator/components/com_myquestions/admin.myquestions.php;

Так вот, при создании файла "admin.myquestions.php" В админке выдает ошибку - "Компонент не найден", а при переименовании его на  "myquestions.php" в последующем шаге, в админке не выводятся кнопки редактирования. 
Проверил кодировку, проверил правильность пути к файлам, пересохранил указанный код. Скажите что я делаю не так или в чем может быть причина?