Разработчику. Сборник рецептов PHP
Задавайте вопросы

Доступ к базам данных

Вернуться назад

Введение

Базы данных являются ключевым моментом многих веб-приложений. База данных может хранить практически любую информацию, которую может потребоваться найти или обновить, например, список пользователей, каталог изделий или последние новости. Одна из причин, по которым PHP занимает такое значительное положение среди языков веб-программирования, заключается в его широком применении для поддержки баз данных. PHP может взаимодействовать (по последним подсчетам) с 17 различными базами данных – как с реляционными, так и нет. Реляционные базы, с которыми он может работать, – это DB++, FrontBase, Informix, Interbase, Ingres II, Microsoft SQL Server, mSQL, MySQL, Oracle, Ovrimos SQL Server, PostgreSQL, SESAM и Sybase. К нереляционным базам, относящимся к сфере действия PHP, относятся dBase, filePro, HyperWave, DBM-семейство баз данных, состоящих из плоских файлов. PHP также включает поддержку ODBC, поэтому даже если ваша любимая база данных не входит в приведенный выше список, то с ней можно работать при помощи средств PHP.

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

Базы данных DBM, состоящие из плоских файлов, обсуждаемые в рецепте Работа с базами данных DBMобеспечивают большую устойчивость и эффективность, чем простые файлы, но все же ограничивают структуру данных парами ключ/значение. Они масштабируются лучше, чем обычные файлы, особенно в случае данных только для чтения (или преимущественно для чтения).

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

В данной главе во многих примерах с SQL участвует таблица с информацией о знаках Зодиака. Ниже представлена структура этой таблицы:

CREATE TABLE zodiac (
     id INT UNSIGNED NOT NULL,
     sign CHAR(11),
     symbol CHAR(13),
     planet CHAR(7),
     element CHAR(5),
     start_month TINYINT,
     start_day TINYINT,
     end_month TINYINT,
     end_day TINYINT,
     PRIMARY KEY(id)
);

А это содержимое таблицы:(*)

INSERT INTO zodiac VALUES (1,'Aries','Ram','Mars','fire',3,21,4,19);
INSERT INTO zodiac VALUES (2,'Taurus','Bull','Venus','earth',4,20,5,20);
INSERT INTO zodiac VALUES (3,'Gemini','Twins','Mercury','air',5,21,6,21);
INSERT INTO zodiac VALUES (4,'Cancer','Crab','Moon','water',6,22,7,22);
INSERT INTO zodiac VALUES (5,'Leo','Lion','Sun','fire',7,23,8,22);
INSERT INTO zodiac VALUES (6,'Virgo','Virgin','Mercury','earth',8,23,9,22);
INSERT INTO zodiac VALUES (7,'Libra','Scales','Venus','air',9,23,10,23);
INSERT INTO zodiac VALUES
(8,'Scorpio','Scorpion','Mars','water',20,24,11,21);
INSERT INTO zodiac VALUES
(9,'Sagittarius','Archer','Jupiter','fire',11,22,12,21);
INSERT INTO zodiac VALUES
(10,'Capricorn','Goat','Saturn','earth',12,22,1,19);
INSERT INTO zodiac VALUES (11,'Aquarius','Water
Carrier','Uranus','air',1,20,2,18);
INSERT INTO zodiac VALUES
(12,'Pisces','Fishes','Neptune','water',2,19,3,20);

*********************************************************************************

Структура таблицы: номер, знак (sign), символ (symbol), планета (planet) и ее расшифровка. Для первой строки: INSERT INTO zodiac VALUES (1,'Овен', 'баран','Марс','огонь',3,21,4,19);.

*********************************************************************************

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

Приведенный ниже пример извлекает строки из таблицы zodiac базы данных Oracle с помощью интерфейса OCI8:

if (! $dbh = OCILogon('david', 'foo!bar','ORAINST')) {
     die("Can't connect: ".OCIError());

}

if (! $sth = OCIParse($dbh,'SELECT * FROM zodiac')) {
     die("Can't parse query: ".OCIError());

}

if (! OCIExecute($sth)) {
     die("Can't execute query: ".OCIError());

}

$cols = OCINumCols($sth);
while (OCIFetch($sth)) {
     for ($i = 1; $i <= $cols; $i++) {
          print OCIResult($sth,$i);
          print " ";

}

print "\n";

}

Функция OCILogin() соединяется с данным экземпляром Oracle с помощью имени пользователя и пароля. Можно опустить третий аргумент (экземпляр), если переменная окружения ORACLE_SID установлена в соответствии с требуемым экземпляром Oracle. Функция OCIParse() возвращает дескриптор оператора, а функция OCIExecute() выполняет запрос. При каждом вызове функции OCIFetch() очередная строка результата направляется в результирующий буфер. Значение в определенной колонке текущей строки доставляется в результирующий буфер функцией OCIResult().

Ниже приведен тот же самый пример для PostgreSQL:

if (! $dbh = pg_connect('dbname=test user=david password=foo!bar')) {
     die("Can't connect: ".pg_errormessage());

}

if (! $sth = pg_exec($dbh,'SELECT * FROM zodiac')) {
     die("Can't execute query: ".pg_errormessage());

}

for ($i = 0, $j = pg_numrows($sth); $i < $j; $i++) {
     $ar = pg_fetch_row($sth,$i);
     foreach ($ar as $col){
          print "$col ";
     }
     print "\n";

}

В данном случае функция pg_connect(), которой в качестве параметров передаются имя базы данных, имя пользователя и пароль, соединяется с PostgreSQL. Запрос выполняется функцией pg_exec(). Здесь нет необходимости в разделении этапов анализа и выполнения, как в случае с Oracle. Поскольку функция pg_fetch_row() размещает отдельные строки из результирующего множества в массиве, то выполняется цикл по всем строкам (при этом функция pg_numrows() вызывается для получения общего количества строк) и каждый элемент этого массива выводится на печать.

Приведем тот же самый пример, но для MySQL:

if (! $dbh = mysql_connect('localhost','david','foo!bar')) {
     die("Can't connect: ".mysql_error());

}

mysql_select_db('test');

if (! $sth = mysql_query('SELECT * FROM zodiac')) {
     die("Can't execute query: ".mysql_error());

}

while ($ar = mysql_fetch_row($sth)) {
     foreach ($ar as $col) {
           print "$col ";

     }

     print "\n";
}

Сначала функция mysql_connect(), в качестве параметров которой выступают имя хоста, имя пользователя и пароль, возвращает дескриптор базы данных. Затем вызывается функция mysql_select_db(), чтобы показать, какая база данных используется. Запрос выполняется функцией mysql_query(). Функция mysql_fetch_row() извлекает очередную строку, помещая ее в результирующее множество, и NULL, если строк больше нет; извлечение всех строк выполняется с помощью цикла while.

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

Aries Ram Mars fire 3 21 4 19
Taurus Bull Venus earth 4 20 5 20
Gemini Twins Mercury air 5 21 6 21
Cancer Crab Moon water 6 22 7 22
Leo Lion Sun fire 7 23 8 22
Virgo Virgin Mercury earth 8 23 9 22
Libra Scales Venus air 9 23 10 23
Scorpio Scorpion Mars water 20 24 11 21
Sagittarius Archer Jupiter fire 11 22 12 21
Capricorn Goat Saturn earth 12 22 1 19
Aquarius Water Carrier Uranus air 1 20 2 18
Pisces Fishes Neptune water 2 19 3 20

Рецепты с Выполнение запросов к базе данных SQL поОпределение количества строк, возвращенных запросом посвящены посылке запросов в базу данных и получению результатов в ответ, а также использованию запросов, изменяющих данные в базе.

PHP поддерживает множество параметров настройки и оптимизации для каждой базы данных. Большинство интерфейсов баз данных поддерживают постоянные соединения с помощью специальных функций. В предыдущих трех примерах можно было использовать функции OCIPLogon(), pg_pconnect() и mysql_pconnect() для создания постоянного соединения вместо однократного соединения для каждого обращения к сценарию.

Если требуется набор функций для определенной базы данных, то обратитесь к онлайновому руководству по PHP, соответствующие разделы которого содержат массу полезных советов по правильному конфигурированию и использованию для каждой базы данных. Начиная с рецепта Соединение с базой данных SQL все SQL-примеры основаны на уровне абстракции базы данных PEAR DB, минимизирующем объем кода, который должен быть изменен для того, чтобы примеры работали с различными базами данных. Ниже приведен фрагмент программы, который может показать все строки из таблицы zodiac, используя DB и MySQL:

require 'DB.php';
$dbh = DB::connect('mysql://david:foo!bar@localhost/test');
$sth = $dbh->query('SELECT * FROM zodiac');
while ($row = $sth->fetchRow()) {

     print join(' ',$row)."\n";

}

Единственное, что надо изменить, чтобы заставить этот код работать с другой базой данных, – это аргумент, переданный функции DB::connect() и определяющий, с какой базой данных нужно соединяться. Однако уровень абстракции базы данных не делает SQL полностью переносимым. Как правило, каждый производитель базы данных реализует свои индивидуальные расширения SQL, предоставляющие полезные возможности для одной базы данных и совершенно не работающие с другими базами.

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

С какой бы базой данных вы ни работали, скорее всего вы будете брать информацию из полей HTML-формы и сохранять эту информацию в базе данных. Некоторые символы, такие как апостроф и обратная косая черта, имеют особое назначение в SQL, поэтому следует соблюдать осторожность, если форма содержит такие символы. В PHP есть возможность, называемая «волшебные кавычки» (magic quotes), облегчающая работу с такими символами. Если параметр конфигурации magic_quotes_gpc установлен в on, то переменные, доставляемые запросами GET, запросами POST и cookies и содержащие одинарные кавычки, двойные кавычки, символы обратной косой черты и NULL, преобразовываются в escape-последовательности с помощью обратной косой черты. Можно также включить параметр magic_quotes_runtime, чтобы автоматически превращать в escape-последовательности символы кавычек, обратной косой черты и нуля, полученные из внешних источников, таких как запросы к базе данных или текстовые файлы. Так, если опция magic_quotes_runtime установлена в on, и вы читаете файл в массив с помощью функции file(), то специальные символы в этом массиве уже будут преобразованы в escape-последовательности.

Например, если элемент $_REQUEST['excuse'] содержит «Ferris wasn’t sick», а параметр magic_quotes_gpc установлен в on, то следующий запрос выполнится успешно:

$dbh->query("INSERT INTO excuses (truth) VALUES ('" . $_REQUESTS['excuse'] .
')');

Без волшебных кавычек апостроф в слове «wasn’t» будет сигнализировать базе данных о конце строки, и запрос породит синтаксическую ошибку. Чтобы параметры magic_quotes_gpc и magic_quotes_runtime выделяли одинарные кавычки с помощью другой одинарной кавычки вместо символа обратной косой черты, установите параметр magic_quotes_sybase в on. Преобразование специальных символов в запросах в escape-последовательности обсуждается в рецепте Преобразование кавычек в еscapе-последовательности Основные приемы отладки, которые можно использовать для обработки ошибок, явившихся результатом выполнения запросов в базы данных, рассматриваются в рецепте Регистрация отладочной информации и ошибок

Остальные рецепты посвящены задачам более сложным, чем простые запросы. В рецепте Автоматическое присваивание уникальных значений идентификаторов показано, как автоматически сгенерировать уникальное значение идентификатора, которое можно использовать в качестве идентификатора записи. Конструирование запросов из списка полей во время исполнения объясняется в рецепте Программное создание запросов Это позволяет легче справляться с запросами INSERT и UPDATE, затрагивающими много столбцов. В рецепте Постраничный вывод большого количества записей продемонстрировано, как показывать ссылки, позволяющие путешествовать по результирующему множеству, отображая небольшое количество записей на каждой странице. В рецепте Кэширование запросов и результатов объясняется, как ускорить доступ к базе данных с помощью кэширования запросов и их результатов.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования


Рейтинг Сайтов ДОСКИ.РУ