Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Котеров Д. В., Костарев А. Ф. - PHP 5. 2-е издание (В подлиннике) - 2008

.pdf
Скачиваний:
6114
Добавлен:
29.02.2016
Размер:
11.36 Mб
Скачать

474

Часть IV. Стандартные функции PHP

ми данных таких проблем не существует, потому что разработчики предусмотрели их (проблем) решение на самом низком уровне и с максимальной эффективностью.

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

Архитектура MySQL

Одна из самых популярных СУБД, которые используются в Web-программиро- вании, — MySQL. Она предназначена для создания небольших (сравнительно, конечно — например, в районе 100 Мбайт) баз данных и поддерживает некоторое подмножество языка запросов SQL.

SQL (Structured Query Language, язык структурированных запросов) — это специально разработанный стандарт языка запросов к базам данных. В нем присутствуют такие команды, как:

создание/удаление таблицы;

создание новых записей в заданной таблице;

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

удаление записей, удовлетворяющих некоторому критерию;

обновление некоторых полей в указанных записях.

Немного подробнее с языком SQL мы будем разбираться чуть позже. А пока давайте посмотрим, что собой представляет MySQL.

MySQL — это программа-сервер, постоянно работающая на компьютере. Клиентские программы (например, сценарии) посылают ей специальные запросы через механизм сокетов (т. е. при помощи сетевых средств), она их обрабатывает и запоминает результат. Затем, также по специальному запросу клиента, весь этот результат или его часть передается обратно.

Почему всегда передается не весь результат? Очень просто: дело в том, что размер результирующего набора данных может быть слишком большим, и на его передачу по сети уйдет чересчур много времени. Да и редко когда бывает нужно получать сразу весь вывод запроса (т. е. все записи, удовлетворяющие выражению запроса). Например, нам может потребоваться лишь подсчитать, сколько записей удовлетворяет тому или иному условию, или же выбрать из данных только первые 10 записей.

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

Глава 28. Работа с СУБД MySQL

475

Как мы уже говорили, структура MySQL трехуровневая: базы данных — таблицы — записи. Один сервер MySQL способен поддерживать сразу несколько баз данных, доступ к которым может разграничиваться именем пользователя (login) и паролем (password). Зная эти регистрационные сведения, можно работать с конкретной базой данных. Например, можно создать или удалить в ней таблицу, добавить записи и т. д. Обычно имя-идентификатор и пароль назначаются хостинг-провайдерами, которые и обеспечивают поддержку MySQL для своих пользователей.

Администрирование базы данных

Для того чтобы чувствовать себя как рыба в воде при работе с СУБД, мы рекомендуем вам сразу же установить себе какую-нибудь программу для администрирования MySQL. Их существует множество. Одна из самых популярных — MySQL-Front — работает в Windows и имеет привычный графический интерфейс. Ее можно скачать с сайта http://www.mysqlfront.de. Если вы захотите подключиться к серверу хостера при помощи MySQL-Front, вас, скорее всего, будет ожидать разочарование: дело в том, что большинство хостеров ограничивают доступ к MySQL пользователями и скриптами, расположенными на их же машине (localhost). Это делается из соображений безопасности: к базе данных имеют доступ только скрипты пользователей хостинга.

Для решения подобных проблем существуют чисто серверные решения, которые позволяют администрировать и просматривать базы данных прямо в окне браузера. При этом сама система администрирования работает на сервере хостера как обычный CGIили PHP-скрипт, а потому имеет доступ к СУБД. Лидер в этой области — система phpMyAdmin, целиком написанная на PHP и устанавливаемая прямо в каталог документов сервера хостинг-провайдера. Ее можно найти по адресу http://phpmyadmin.net.

Достоинство систем администрирования в том, что с их помощью вы можете просматривать и редактировать свои базы данных и расположенные в них таблицы. Вы даже можете изменять структуру таблиц (например, добавлять в них новые поля), а также просматривать разного рода статистику. Кроме того, они позволяют в удобном виде просматривать результаты запросов, введенных вручную — это особенно полезно при отладке скриптов, когда непонятно, почему та или иная команда SQL работает не так, как ожидается.

Базовый пакет комплекса Денвер, установка которого описана в части II книги, уже включает в себя настроенный интерфейс администратора phpMyAdmin. Он доступен по адресу http://localhost/phpmyadmin.

Порядок работы с базой данных

Работа с базой данных во всех скриптах происходит однотипно. Вначале надо подключиться к серверу СУБД, затем — переслать ему одну или несколько команд, обрабатывая возможные ошибки. В конце можно закрыть соединение с сервером (хотя PHP делает это автоматически при завершении сценария).

476

Часть IV. Стандартные функции PHP

Интерфейсы для работы с MySQL

В PHP версии 4 существовал лишь один набор функций для работы с MySQL. Все функции из этого набора имеют имена, начинающиеся с префикса mysql_ — например, mysql_connect(), mysql_query(), mysql_fetch_assoc() и т. д. Кроме того, поддержка MySQL была встроена в ядро PHP и работала только с версиями MySQL, не

превышающими 4.1.

Пятая версия внесла некоторые новшества: появился новый, объектно-ориентиро- ванный, интерфейс с MySQL, поддержка которого вынесена в отдельную библиотеку расширения mysqli. Он используется для доступа к серверам MySQL версии 4.1

ивыше. В момент написания этих строк (осень 2004 года) версия 4.1 все еще находилась в "экспериментальной" стадии. Старый набор функций вынесен из ядра PHP

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

Так как MySQL версии 4.1 и новее используется еще очень редко, в книге мы рассмотрим старый интерфейс — mysql. А значит, далее речь пойдет о функциях, чьи имена начинаются на префикс mysql_.

Соединение с сервером

Прежде чем работать с базой данных, необходимо установить с ней сетевое соединение, а также провести авторизацию пользователя. Для этого служит функция mysql_connect().

int mysql_connect([string $host] [,string $user] [,string $password])

Функция mysql_connect() устанавливает сетевое соединение с базой данных MySQL, расположенной на хосте $host (по умолчанию это localhost, т. е. текущий компьютер), и возвращает идентификатор открытого соединения. Вся дальнейшая работа ведется именно с этим идентификатором. При регистрации указывается имя пользователя $user и пароль $password (по умолчанию имя пользователя, от которого запущен текущий процесс, и пустой пароль). Строка $host также может включать в себя номер порта в формате: имя_хоста:порт (если сервер MySQL настроен не на стандартный, а на какой-то другой порт, что делать, вообще говоря, не рекомендуется).

Соединение с MySQL-сервером будет автоматически закрыто по завершении работы сценария, либо же при вызове функции mysql_close().

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

int mysql_select_db(string $dbname [,int $link_identifier])

До того как послать первый запрос серверу MySQL, необходимо указать, с какой базой данных мы собираемся работать. Для этого и предназначена описываемая функция. Она уведомляет PHP, что в дальнейших операциях с соединением

Глава 28. Работа с СУБД MySQL

477

$link_identifier (или с последним открытым соединением, если указанный параметр не задан) будет использоваться база данных $dbname.

Как вы, наверное, догадались, наличие данной функции свидетельствует о том, что один и тот же пользователь может иметь доступ сразу к нескольким базам данных. Так и есть. И даже более того: права доступа к разным БД для одного и того же пользователя могут различаться. Впрочем, указанные возможности задействуются редко, и обычно хостинг-провайдеры предоставляют каждому пользователю доступ лишь к одной базе данных. Ее имя совпадает с регистрационным именем пользователя (login).

Обработка ошибок

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

Важно аккуратно и своевременно использовать эти функции, потому что иначе отладка ваших сценариев может превратиться в ночной кошмар. Ниже мы рассмотрим множество примеров, как это лучше всего делать.

int mysql_errno([int $link_identifier])

Функция возвращает номер последней зарегистрированной ошибки. Идентификатор соединения $link_identifier можно не указывать, если за время работы сценария было установлено только одно соединение.

string mysql_error([int $link_identifier])

Эта функция возвращает не номер, а строку, содержащую текст сообщения об ошибке. Ее удобно применять в отладочных целях. Обычно mysql_error() используют вместе с конструкцией or die(), например:

@mysql_connect("localhost", "user", "password")

or die("Error connecting to database: ".mysql_error());

Оператор @, как обычно, служит для подавления стандартного предупреждения, которое может возникнуть в случае ошибки.

Впрочем, в последних версиях PHP предупреждения в MySQL-функциях по умолчанию не регистрируются.

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

Теперь мы подходим непосредственно к тому, как формировать и посылать запросы к базе данных. Для этого существует одна-единственная функция — mysql_query()

и возвращает она не что иное, как идентификатор результирующего набора данных

(так называемый result-set).

478

Часть IV. Стандартные функции PHP

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

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

Любой запрос к MySQL-серверу представляет собой обычную строку, записанную на языке SQL. В этой строке указывается имя команды, а также данные (в апострофах), которые необходимо использовать для модификации записей или поиска

втаблицах. Например, следующий SQL-запрос осуществляет поиск всех записей

втаблице Music, для которых название композиции равно "Going Under":

SELECT * FROM Music WHERE title='Going Under'

Язык SQL мы рассмотрим чуть позже (см. разд. "Язык запросов СУБД MySQL" далее

в этой главе).

int mysql_query(string $query [,int $link_identifier])

Эта функция в своем роде универсальна: она посылает MySQL-серверу запрос $query и возвращает идентификатор ответа, или результата. Параметр $query представляет собой строку, составленную по правилам языка SQL. Используется установленное ранее соединение $link_identifier, а в случае его отсутствия — последнее открытое соединение.

Есть несколько команд SQL, которые возвращают только признак, успешно они выполнились или нет (например, команды UPDATE, INSERT и т. д.). В таком случае этот признак и будет возвращен функцией. Вообще, возвращается не просто признак "есть ошибка/нет ошибки", а целое число, которое говорит, сколько записей было затронуто данным запросом. Если оно равно нулю, значит, ни одна запись не была задействована в запросе.

Наоборот, для запроса SELECT возвращается как раз идентификатор результирующего набора, нулевое значение которого свидетельствует о произошедшей ошибке.

За один вызов mysql_query() можно выполнить только одну команду MySQL. В некоторых других языках программирования, а также в интерфейсе командной строки сервера MySQL (mysql.exe в Windows, mysql — в Unix) разрешено выполнение сразу нескольких команд, разделенных точкой с запятой, однако в PHP данный способ не работает. Позже мы увидим, что это сильно повышает безопасность работы скриптов.

Автоматизация подключения к СУБД

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

Глава 28. Работа с СУБД MySQL

479

и т. д. Соответственно, код, ответственный за подключение к СУБД, лучше всего выделить в отдельный файл, который потом будет подключаться ко всем программам.

В листинге 28.1 приведен PHP-файл, осуществляющий подключение к базе данных. Мы будем далее включать его во всех скриптах при помощи команды:

require_once "mysql_connect.php";

Листинг 28.1. Файл mysql_connect.php

<?php ## Подключение к СУБД MySQL. $user = "root";

$pass = "";

$db = "spoon";

// Подключаемся к СУБД MySQL. mysql_connect("localhost", $user, $pass)

or die("Could not connect: ".mysql_error());

//Создаем БД $db — это может делать только суперпользователь!

//Если БД уже существует, будет ошибка, но это не страшно. @mysql_query("CREATE DATABASE $db");

//Выбираем БД $db (только что созданную или уже существующую). mysql_select_db($db)

or die("Could not select database: ".mysql_error()); ?>

Старайтесь везде, где только можно, использовать апострофы в качестве ограничителей строк, содержащих SQL-команды. Этим вы сможете гарантировать, что никакая $-переменная случайно не будет интерполирована (т. е. не заменится на свое значение), и увеличите безопасность скриптов. Ближе к концу главы мы рассмотрим этот аспект подробнее (см. разд. "MySQL и проблемы безопасности" далее в этой главе).

Прежде чем продолжить, давайте внимательно взглянем на параметры подключения к серверу. Ну, хост localhost — это стандартный вариант для большинства хостингов. В то же время, имя пользователя root (суперпользователь) и пустой пароль назвать "стандартными" нельзя никак. Ни один хостинг-провайдер на реальном сервере в Интернете не позволит вам подключиться с указанными параметрами. Однако если вы отлаживаете скрипт на локальной машине под Windows, как рекомендуется делать в части II этой книги, то по умолчанию для доступа к MySQL как раз используется имя пользователя root и отсутствующий пароль. При этом сервер MySQL "не виден" извне по сети, а доступен только с текущей машины по адресу localhost, так что безопасность не страдает.

Пользователю root разрешено выполнять любые действия с MySQL-сервером. В частности, он может заводить на нем новые базы данных, чем мы и пользуемся в данном скрипте. Мы создаем базу "на всякий случай" при каждом запуске сценария, но, конечно, реальные действия произойдут только при первом запуске — последующие же попытки породят ошибку, которую мы попросту игнорируем (оператор @).

480

Часть IV. Стандартные функции PHP

Впрочем, в последних версиях PHP сообщения об ошибках подавляются и без оператора @. Однако мы будем на всякий случай использовать его здесь и далее в случаях, когда ошибки обрабатываются явно или не влияют на работу.

При переносе скрипта на хостинг вы должны будете заменить параметры подключения на те, которые выдаст вам хостер. Но как же сохранить совместимость с локальной версией сайта под Windows? Тут есть два способа.

Создание нового пользователя

Первый способ — завести на локальной машине пользователя и базу данных, чьи параметры в точности совпадают с выданными хостером. Этот способ, вероятно, наилучший, но он подразумевает, что вы умеете создавать новые базы данных и регистрировать пользователей в MySQL.

В архиве с исходными кодами на сайте книги имеется скрипт addmuser.php, предназначенный для формирования новой базы данных и пользователя, а также ограничения прав созданного пользователя теми значениями, которые обычно применяют хостинг-провай- деры.

Подключение с правами администратора

Второй способ — применить различный код при работе в Unix и Windows:

$db = "spoon"; // имя БД общее if (getenv("COMSPEC")) {

//Мы работаем в Windows. $user = "root"; $password = "";

}else {

//Работаем в Unix.

$user = "выданный хостером"; $password = "выданный хостером";

}

Переменная окружения COMSPEC специфична для всех версий Windows и содержит путь до командного интерпретатора (cmd.exe или command.com). В Unix же она не установлена, поэтому таким нехитрым способом вы сможете определить, где запускается скрипт.

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

Язык запросов СУБД MySQL

Разумеется, весь язык запросов SQL в рамках одной главы описать просто невозможно. О нем сочиняют (и будут сочинять) "объемистые" книги. Однако самые ос-

Глава 28. Работа с СУБД MySQL

481

новные команды мы в этой главе приведем. Более подробно о них вы можете прочитать в любой книге по языку SQL.

Все запросы к базе данных посылаются при помощи одной-единственной функции — mysql_query(). Они должны передаваться ей в виде строкового параметра. Этот параметр, впрочем, может быть и многострочным, т. е. содержать символы перевода строки. MySQL допускает включение любого количества пробелов, символов табуляции или перевода строки везде, где разрешено использование одного пробела (в этом смысле он похож на PHP и большинство других языков программирования).

Возможности языка SQL по-настоящему впечатляют, и он позволяет нам создавать довольно сложные запросы. Подчас разобраться в каком-нибудь особенно сложном запросе, затрагивающем сразу несколько таблиц, может только специалист. Составление SQL-запросов — это в некотором роде искусство, и от того, насколько опытен разработчик, часто зависит скорость выполнения запроса.

Ниже мы перечислим лишь наиболее употребительные команды MySQL, да и то — не в их полном формате, а только в наиболее употребимом. За деталями обращайтесь к документации MySQL.

CREATE DATABASE: создание базы данных

Одну из команд — создание базы данных, мы уже применяли выше. Она доступна только суперпуперпользователю, и на большинстве хостингов вы не сможете ее выполнять.

CREATE DATABASE ИмяБазыДанных

Создает новую базу данных с именем ИмяБазыДанных. Эта команда доступна только администратору сервера.

CREATE TABLE: создание таблицы

CREATE [IF NOT EXISTS] TABLE ИмяТаблицы(ИмяПоля тип, ИмяПоля тип, ...)

Этой командой в базе данных создается новая таблица с колонками (полями), определяемыми своими именами (ИмяПоля) и указанными типами. После создания таблицы в нее можно будет добавлять записи, состоящие из перечисленных в данной команде полей.

Пример программы, создающей новую таблицу, приведен в листинге 28.2.

Листинг 28.2. Файл create.php

<?php ## Создание новой таблицы в БД.

include_once "mysql_connect.php";

mysql_query('CREATE TABLE people(id INT, name TEXT)')

or die("MySQL error: ".mysql_error());

?>

Язык SQL нечувствителен к регистру символов. Вы можете написать CREATE, create или даже CrEaTe, и это будет работать одинаково. Тем не менее в литературе принято

482

Часть IV. Стандартные функции PHP

команды и операторы SQL (да и вообще — все ключевые слова) писать большими буквами, а имена полей и таблиц — маленькими.

Данный сценарий создает новую таблицу с двумя полями. Первое поле имеет тип INT (целое) и имя id. Второе — тип TEXT (текстовая строка) и имя name. Если таблица существует, сработает уже набившая оскомину конструкция or die().

Необязательная фраза IF NOT EXISTS, если она задана, говорит серверу MySQL, что он не должен генерировать сообщение об ошибке, если таблица с указанным именем уже существует в базе данных.

Типы полей

Далее мы перечислим большинство типов полей, которые могут применяться в MySQL. Их довольно много. Квадратными скобками, по традиции, мы будем помечать необязательные элементы — не набирайте их в своих программах!

Целые числа

Существует несколько разных типов целых чисел, различающихся количеством байтов данных, которые отводятся в базе данных для их хранения. Все эти типы рознятся только названиями и записываются (с некоторыми сокращениями) так:

префиксINT [UNSIGNED]

Необязательный флаг UNSIGNED задает, что будет создано поле для хранения беззнаковых чисел (больших или равных 0). Имена типов, в общем виде обозначенные здесь как префиксINT, приводятся в табл. 28.1.

Таблица 28.1. Типы целочисленных данных MySQL

Òèï

Описание

 

 

 

 

 

TINYINT

Может хранить числа от –128 до +127

SMALLINT

Диапазон от –32 768 до 32

767

MEDIUMINT

Диапазон от –8 388 608

äî

8 388 607

INT

Диапазон от –2 147 483

648

äî 2 147 483 647

BIGINT

Диапазон от –9 223 372

036

854 775 808 äî 9 223 372 036 854 775 807

 

 

 

 

 

Вещественные числа

Точно так же, как целые числа подразделяются в MySQL на несколько разновидностей, эта СУБД поддерживает и несколько типов дробных чисел. В общем виде они записываются так:

ИмяТипа[(length,decimals)] [UNSIGNED]

Здесь length — количество знакомест (ширина поля), в которых будет размещено дробное число при его передаче в PHP, а decimals — количество знаков после десятичной точки, которые будут учитываться. Как обычно, UNSIGNED задает беззнаковые числа. Строка ИмяТипа замещается на предопределенные значения, соответствующие возможным вариантам представления вещественных чисел (табл. 28.2).

 

Глава 28. Работа с СУБД MySQL

483

 

 

 

Таблица 28.2. Типы рациональных чисел в MySQL

 

 

 

 

 

Òèï

Описание

 

 

 

 

 

 

 

 

FLOAT

Число с плавающей точкой небольшой точности

 

 

 

DOUBLE

Число с плавающей точкой двойной точности

 

 

 

REAL

Синоним для DOUBLE

 

 

 

DECIMAL

Дробное число, хранящееся в виде строки

 

 

 

NUMERIC

Синоним для DECIMAL

 

 

 

 

 

 

 

Строки

Строки представляют собой массивы символов. Обычно при поиске по текстовым полям по запросу SELECT не берется в рассмотрение регистр символов, т. е. строки "Вася" и "ВАСЯ" считаются одинаковыми. Кроме того, если база данных настроена на автоматическую перекодировку текста при его помещении и извлечении (см. ниже), эти поля будут храниться в указанной вами кодировке.

Для начала давайте познакомимся с типом строки, которая может хранить не более length символов, где length принадлежит диапазону от 1 до 255.

VARCHAR(length) [BINARY]

При занесении некоторого значения в поле такого типа из него автоматически вырезаются концевые пробелы (как будто по вызову функции rtrim()). Если указан флаг BINARY, то при запросе SELECT строка будет сравниваться с учетом регистра. Тип VARCHAR неудобен тем, что способен хранить не более 255 символов. Если строка может быть длиннее, вместо него следует использовать другие текстовые типы, перечисленные в табл. 28.3.

 

Таблица 28.3. Строковые типы данных таблиц MySQL

 

 

Òèï

Описание

 

 

TINYTEXT

Может хранить максимум 255 символов

TEXT

Может хранить не более 65 535 символов

MEDIUMTEXT

Может хранить максимум 16 777 215 символов

LONGTEXT

Может хранить 4 294 967 295 символов

 

 

Чаще всего применяется тип TEXT, но если вы не уверены, что данные будут всегда короче 65 536 байтов, используйте LONGTEXT.

Слухи о том, что TEXT-типы занимают намного больше места на диске, чем аналогичные VARCHAR-поля, сильно преувеличены.

Тут вы можете оставить комментарий к выбранному абзацу или сообщить об ошибке.

Оставленные комментарии видны всем.