Описание интерфейса ipsclass для работы с БД

Один из наиболее важных инструментов, используемых при создании модулей IPB и модификаций его кода - интерфейс базы данных. Используя методы, предоставляемые объектом $ipsclass→DB, вы получаете простой и мощный способ работы с базой данных вашего форума.

Обратите внимание!

  1. Несмотря на то, что описываемый интерфейс представляет собой отличный пример абстрагирования от прямого составления SQL-запросов, разработчику необходимо как минимум общее понимание принципов языка SQL. Если эта аббревиатура ничего вам не говорит или вы чувствуете, что вам необходимо укрепить знания в этом вопросе — обратитесь к обширной и подробной документации на русском языке.
  2. При работе с интерфейсом не забывайте: указывая, из каких таблиц следует извлекать данные, следует опускать префикс таблиц базы данных — драйвер подставляет его автоматически. Исключение составляет метод query(), который не обрабатывает запрос и выполняет его в том виде, в каком он был передан методу.

В этой статье мы рассмотрим методы объекта $ipsclass→DB, с помощью которых программист может манипулировать базой данных форума. Сначала мы обратимся к простым функциям выборки — simple_select() и simple_select_with_join() и методам обработки данных, которые они возвращают. Затем будут рассмотрены методы вставки, удаления и обновления данных, а в самом конце — универсальный метод build_query, конструирующий запросы любой сложности.

Метод simple_select(): простые выборки

Допустим, вам необходимо получить данные из таблицы форума с помощью оператора SELECT. Специально для этого в объекте ipsclass предусмотрен метод simple_select(). Рассмотрим пример его использования:

$this->ipsclass->DB->simple_select( 'title,state', 'topics', 'starter_id = 1' );
$this->ipsclass->DB->exec_query();

Здесь:

  • title,state — перечень полей, которые запрашиваются из таблицы, указанной во втором параметре; допускается использование символа * для получения всех полей таблицы.
  • topics — название таблицы, из которой необходимо извлечь данные; напоминаем, что префикс таблицы (по умолчанию ibf_) указывать не нужно.
  • starter_id = 1 — условие для SQL-оператора WHERE, с помощью которого можно организовать поиск данных по определённому критерию.


Таким образом, в данном примере происходит выборка заголовков (title) и статусов (state) всех тем (topics), которые были начаты администратором (пользователем, чем ID равен единице; starter_id = 1). Обратите внимание, что после вызова метода simple_select() обязательно должен быть вызван метод exec_query(). Он-то и выполняет запрос, построенный с помощью метода simple_select(). После других методов — например, do_update() или do_insert() — метод exec_query() использовать не нужно.

Метод simple_limit(): ограничение области выборки

Этот метод добавляет к создаваемому запросу конструкцию LIMIT: она ограничивает область, в которой будет производиться выборка данных и задаёт предельное количество строк, возвращаемых в результате запроса. Рассмотрим пример использования:

$this->ipsclass->DB->simple_select( 'name,mgroup', 'members', 'allow_admin_mails = 1' );
$this->ipsclass->DB->simple_limit( 10, 5 );
$this->ipsclass->DB->exec_query();

Как мы уже знаем из предыдущих примеров, функция simple_select в данном случае создаст запрос, который извлекает значения полей name (логин пользователя) и mgroup (идентификатор его основной группы) из таблицы ibf_members. Выборка вернёт только те записи, где поле allow_admin_mails равно единице, то есть данные тех пользователей, которые разрешили приём писем от администрации форума. Вторая строка примера добавляет к сформированному запросу конструкцию LIMIT 10,5 — то есть поиск будет производиться, начиная с 11-й строки и в результате выборки будет не больше 5-и строк.

Параметр сдвига (offset) можно опускать. Например, следующий код вернёт первого в таблице пользователя, чей логин совпадает с отображаемым именем:

$this->ipsclass->DB->simple_select( '*', 'members', 'name = members_display_name' );
$this->ipsclass->DB->simple_limit( 1 );
$this->ipsclass->DB->exec_query();

Существует также модификация метода — simple_limit_with_check(). Синтаксис этой функции идентичен оригинальной, за одним исключением: преждем чем добавить к создаваемому запросу конструкцию LIMIT, она проверяет её наличие в тексте запроса и в случае положительного результата не выполняется. Таким образом исключается возможная ошибка SQL-запроса из-за задания двух конструкций LIMIT.

Метод fetch_row(): обработка результатов запроса

Итак, вы выполнили некий SQL-запрос. Что дальше? Как теперь получить данные, которые вернул сервер?

Вам нужно использовать метод fetch_row(), который вернет полученные от сервера данные в виде ассоциативного массива. Например:

$data = $this->ipsclass->DB->fetch_row();

Обратите внимание: если в результате SQL-запроса вы рассчитывали получить больше одной строки, нужно обрабатывать полученные данные, пока они не закончатся. Ваш код в этом случае будет иметь примерно такой вид:

while( $row = $this->ipsclass->DB->fetch_row() )
{
	// Манипулируем данными строки. Например, заносим в массив. Вот так:
	$all_rows[] = $row;
}

После выполнения этой конструкции в массив $all_rows будут занесены все строки, которые вернул вам сервер баз данных после обработки запроса.

Метод simple_delete(): удаление данных

Синтаксис метода, удаляющего строки из таблицы, очень прост и выглядит примерно так:

$this->ipsclass->DB->simple_delete( 'spider_logs', 'bot=MyBot' );
$this->ipsclass->DB->exec_query();

Здесь первый оператор — это название таблицы, из которой следует удалять данные, а второй — условие их удаления (аналог SQL-оператора WHERE). В этом примере из таблицы ibf_spider_logs будут удалены все строки, в которых поле bot имеет значение «MyBot» (то есть, будут удалены все данные посещений форума ботом, определённым как MyBot).

Обратите внимание, что если вы опустите второй параметр и укажите только название таблицы, из неё будут удалены все данные, а счётчик автоинкрементных полей будет обнулён (то есть, выполнится SQL-запрос TRUNCATE). Будьте осторожны!

Методы get_num_rows() и get_affected_rows(): определение результатов запроса

In the case that you need to check for the rows returned, or the affected rows, you have two functions at your disposal: [code]$num_rows = $this→ipsclass→DB→get_num_rows();[/code] get_num_rows() does exactly what it says, it will return the number of rows returned by the query just executed. It returns 0 for 0, so you can do a true/false check on the returned value. [code]$affect_rows = $this→ipsclass→DB→get_affected_rows();[/code] get_affected_rows() will return the number of rows changed in an update query, delete query, or insert query.

Усложнённые и составные запросы

FIXME Дописать про методы семейства simple_* и вообще про build_query, тут и трети нет.

Если вам необходимо выполнить более сложную выборку (и не только выборку, запрос может быть любого типа и ниже мы это рассмотрим) - используйте метод build_query(). Метод использует очень гибкие параметры. Расммотрим пример обработки двух таблиц через привычный LEFT JOIN:

$join_array = array( 'select' => 'b.*',
                     'from'   => array( 'table_b' => 'b' ),
                     'where'  => 'a.this_thing = b.this_other',
                     'type'   => 'left'
                     );
 
$this->ipsclass->DB->build_query( array( 'select'   => 'a.*',
                                         'from'     => array( 'table_name' => 'a' ),
                                         'where'    => 'a.this = 4',
                                         'add_join' => $join_array,
                                         'limit'    => array( 0,15 )
                                         )
                                  );
 
$this->ipsclass->DB->exec_query();

В целях удобочитаемости кода IBResource.ru рекомендует вам формировать запрос из фрагментов: так, в этом примере массив $join_array сначала задан, а потом использован в методе build_query(). Рассмотрим части этого массива:

  • $join_array['select'] - перечисление полей таблиц, которые вы хотите получить в результате запроса. Не забывайте указывать алиас таблицы из поля from, если он там задан.
  • $join_array['from'] - простой массив вида 'имя_таблицы' ⇒ 'алиас_таблицы', сообщающий методу build_query(), в каких таблицах следует производить выборку.
  • $join_array['where'] - аналог оператора WHERE языка SQL. Например, для получения данных о пользователе из ibf_members и ibf_member_extra этот фрагмент будет иметь вид m.id = mex.id.
  • $join_array['type'] - тип присоединения данных. Допустимые значения: left, inner и straight.

Вы можете использовать метод build_query для обновления, вставки данных и многих других операций.

The parameters are nearly identical to the [i]$join_array[/i], except for the key 'add_join'. This is where you would pass the [i]$join_array[/i] to the function so that the proper join SQL can be generated.

Обновление и вставка данных: простой путь

By using the do_update() and do_insert() functions, you can process an update or insert query in just one function call. [code]$this→ipsclass→DB→do_update( 'some_table', array( 'fieldname' ⇒ 0, 'fieldtwo' ⇒ 'new_value' ), 'this_field = 5' );[/code] The first parameter is the table you wish to update. Second parameter is an array of each field that you need to update, and their new values. Third, and very important, is the WHERE clause. Leave this out and you'll get a nice table of the exact same values :P

The do_insert() syntax is identical, except for the missing WHERE clause: [code]$this→ipsclass→DB→do_insert( 'some_table', array( 'field_to_insert' ⇒ 'the_value' ) );[/code] If your DB schema has default values in certain fields, and you don't want to change them on insert, you don't have to specify the field name in the array.

В заключении...

There are more methods and tricks to using the DB layer, however these are the most commonly used in most modifications, and in the products themselves. If anyone would like to expand on the other functions, feel free :)

 

sources/api/ipsclassdb.txt · Последние изменения: 2007/08/14 12:01 (внешнее изменение)

Работает на DokuWiki
© 2002—2006 ibresource
e-mail: wikiteam@iblink.ru