Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Очень просто о PHP, от элементарных понятий до ООП: Работа с MySQL, часть2


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

Итак, продолжим лекцию:


Играем в хирурга: имплантируем...

Вы уже знаете как выполнять запросы SELECT чтобы получать набор результатов из базы данных. Однако, вы также можете использовать API в PHP для выполнения запросов к MySQL, которые не возвращают набора результатов - например, запросов INSERT или UPDATE. Рассмотрим следующим пример, который показывает такие действия, запрашивая у пользователя ввод через форму, а затем вставляющий данные в базу данных:

<html>
<head>
<basefont face="Arial">
</head>
<body>

<?php

if (!isset($_POST['submit'])) { 
// если форма ещё не была отправлена 
?> 

    <form action="<?$_SERVER['PHP_SELF']?>" method="post"> 
    Страна: <input type="text" name="country"> 
    Национальное животное: <input type="text" name="animal"> 
    <input type="submit" name="submit" value="Записать"> 
    </form> 

<?php 
} 
else { 
// если форма была отправлена 
// устанавливаем переменные доступа к серверу БД
    $host = "localhost"; 
    $user = "test"; 
    $pass = "test"; 
    $db = "testdb"; 
     
// получаем данные ввода пользователя
    // проверим, все-ли заполнено
    // экранируем кавычки для большей безопасности
    $country = empty($_POST['country']) ?
  die ("Ошибка: введите страну") : mysql_escape_string($_POST['country']); 
    $animal = empty($_POST['animal'])
  ? die ("Ошибка: введите животное") : mysql_escape_string($_POST['animal']); 

    // открываем соединение
    $connection = mysql_connect($host, $user, $pass) or die ("Не могу подключиться!"); 
     
    // выбираем базу данных 
    mysql_select_db($db) or die ("Не могу выбрать базу данных!"); 
     
    // создаём запрос 
    $query = "INSERT INTO symbols (country, animal) VALUES ('$country', '$animal')"; 
     
    // выполняем запрос 
    $result = mysql_query($query) or die ("Ошибка в запросе: $query. ".mysql_error()); 
     
    // печатаем сообщение с идентификатором вставленной записи 
    echo "Новая запись вставлена с номером ".mysql_insert_id(); 
     
    // закрываем соединение 
    mysql_close($connection); 
}

?>

</body>
</html>

В примере пользователю сначала будет показана форма, запрашивающая страну и её национальное животное.

Страна: Национальное животное:

После того, как форма была отправлена, данные из неё используются при создании запроса INSERT, который затем отправляется базе данных методом mysql_query(). Так как mysql_query() возвращает булево значение, показывающее был запрос выполнен успешно или нет, мы можем проверить - произошла-ли вставка и выдать соответствующее сообщение:

Новая запись вставлена с номером 7

В примере мы видим две новых функции. Первая - mysql_escape_string() экранирует специальные символы (такие как кавычки) из данных пользователя для того, чтобы затем их было можно безопасно вставить в базу данных; а вторая - mysql_insert_id() - возвращает id, созданный предыдущим запросом INSERT (полезно только в случае если у таблицы есть поле со свойством AUTO_INCREMENT). Обе функции также существуют в расширении ext/mysqli.

...и ампутируем

Очевидно что вы можете делать то-же самое с другими выражениями, изменяющими данные. Следующий пример показывает как использовать выражение DELETE в PHP для выборочного удаления из таблицы. Для разнообразия на этот раз я буду использовать ext/mysqli:

<html>
<head>
<basefont face="Arial">
</head>
<body>

<?php

// переменные для доступа к серверу
$host = "localhost"; 
$user = "test"; 
$pass = "test"; 
$db = "testdb"; 

// создаём обьект mysqli
// и открываем соединение
$mysqli = new mysqli($host, $user, $pass, $db); 

// проверяемся на ошибки соединения
if (mysqli_connect_errno()) { 
    die("Не могу подключиться!"); 
} 

// если получен номер записи, удаляем запись
if (isset($_GET['id'])) { 
// создаём запрос для удаления записи 
    $query = "DELETE FROM symbols WHERE id = ".$_GET['id']; 
     
// выполняем запрос 
    if ($mysqli->query($query)) { 
    // печатаем число затронутых строк 
    echo $mysqli->affected_rows." строк удалено"; 
    } 
    else { 
    // print error message 
    echo "Ошибка в запросе: $query. ".$mysqli->error; 
    } 
} 
//запрос для выборки всех записей 
$query = "SELECT * FROM symbols"; 

// выполняем его
if ($result = $mysqli->query($query)) { 
    // если строки получены
    if ($result->num_rows > 0) { 
        // печатаем их
        echo "<table cellpadding=10 border=1>"; 
        while($row = $result->fetch_array()) { 
            echo "<tr>"; 
            echo "<td>".$row[0]."</td>"; 
            echo "<td>".$row[1]."</td>"; 
            echo "<td>".$row[2]."</td>"; 
            echo "<td><a href=".$_SERVER['PHP_SELF']."?id=".$row[0].">удалить</a></td>"; 
            echo "</tr>"; 
        } 
    } 
    // очищаем память от результата запроса
    $result->close(); 
} 
else { 
    // печатаем сообщенеи об ошибке
    echo "Ошибка в запросе: $query. ".$mysqli->error; 
} 
// закрываем соединение 
$mysqli->close();

?>

</body>
</html>

Получаем такую картину:

0 строк удалено

id страна животное  
1 Америка орёл удалить
2 Китай дракон удалить
3 Англия лев удалить
4 Индия тигр удалить
5 Австралия кенгуру удалить
6 Норвегия лось удалить

Заметьте, что мы использовали свойство affected_rows обьекта mysqli - оно возращает общее число строк, затронутых последним действием. Свойство доступно в ext/mysql, как и функция mysql_affected_rows().

Заглядываем внутрь

В PHP есть куча функций, созданных для информирования вас обо всём что вы хотели знать про клиент и сервер MySQL: их номера версий, общее число доступных баз данных, таблицах внутри каждой БД, работающих процессах... назовите что-нибудь и угадаете - оно есть! Вот пример, который использует их для показа полной картины все что происходит внутри СУБД MySQL:

<html>
<head>
<basefont face="Arial">
</head>
<body>

<?php

// переменные для доступа к серверу
$host = "localhost"; 
$user = "root"; 
$pass = "guessme"; 
$db = "testdb"; 

// открывает соединение
$connection = mysql_connect($host, $user, $pass) or die ("Не могу подключиться!"); 

// получаем список баз данных
$query = "SHOW DATABASES"; 
$result = mysql_query($query) or die ("Ошибка в запросе: $query. ".mysql_error()); 
     
echo "<ul>"; 
while ($row = mysql_fetch_array($result)) { 
    echo "<li>".$row[0]; 

    // для каждой базы получаем и печатаем список таблиц 
    $query2 = "SHOW TABLES FROM ".$row[0]; 
    $result2 = mysql_query($query2) or die ("Ошибка в запросе: $query2. ".mysql_error()); 
    echo "<ul>"; 
    while ($row2 = mysql_fetch_array($result2)) { 
        echo "<li>".$row2[0]; 
    } 
    echo "</ul>"; 
} 
echo "</ul>"; 

// получаем различную информацию
echo "Версия клиента: ".mysql_get_client_info()."<br />"; 
echo "Версия сервера: ".mysql_get_server_info()."<br />"; 
echo "Версия протокола: ".mysql_get_proto_info()."<br />"; 
echo "Хост: ".mysql_get_host_info()."<br />"; 

// получаем статус сервера
$status = mysql_stat(); 
echo $status; 

// закрываем соединение
mysql_close($connection);

?>

</body>
</html>

Если запустить этот скрипт, то мы получим вывод, подобный такому:

  • information_schema
    • CHARACTER_SETS
    • COLLATIONS
    • COLLATION_CHARACTER_SET_APPLICABILITY
    • COLUMNS
    • COLUMN_PRIVILEGES
    • KEY_COLUMN_USAGE
    • PROFILING
    • ROUTINES
    • SCHEMATA
    • SCHEMA_PRIVILEGES
    • STATISTICS
    • TABLES
    • TABLE_CONSTRAINTS
    • TABLE_PRIVILEGES
    • TRIGGERS
    • USER_PRIVILEGES
    • VIEW
  • mysql
    • columns_priv
    • db
    • func
    • help_category
    • help_keyword
    • help_relation
    • help_topic
    • host
    • proc
    • procs_priv
    • tables_priv
    • time_zone
    • time_zone_leap_second
    • time_zone_name
    • time_zone_transition
    • time_zone_transition_type
    • user
  • netams
    • events
    • oids
    • quota
    • summary
  • postfix
    • admin
    • alias
    • config
    • domain
    • domain_admins
    • fetchmail
    • log
    • mailbox
    • vacation
    • vacation_notificat
  • squidctrl
    • globalsettings
    • groups
    • ipreplace
    • log
    • passwd
    • proxyes
    • reconfig
    • redirect
    • sams
    • sconfig
    • sguard
    • shablons
    • squidusers
    • tree
    • urlreplace
    • url
  • squidlog
    • cache
    • cachesum
    • files

Client version: 5.0.85
Server version: 5.0.85-log
Protocol version: 10
Host: Localhost via UNIX socket
Uptime: 151795 Threads: 3 Questions: 1523045 Slow queries: 2 Opens: 107 Flush tables: 1 Open tables: 95 Queries per second avg: 10.034

Первая часть скрипта очень проста: она выполняет запрос SHOW DATABASES для получения списка баз данных, затем проходит по списку и выполняет запрос SHOW TABLES для каждой из них. Далее выполняются функции mysql_get_*_info() для получения версии клиента, версии MySQL, версии протокола клиент-сервер MySQL для общения между ними, текущее имя хоста и как он подключён к серверу MySQL. И, наконец, новая с PHP версии 4.3.0, функция mysql_stat() возвращает строку с информацией о сервере MySQL (время работы, открытые таблицы, число запросов в секунду и прочую статистику).

Ну всё уже?!

Нет, ещё не всё. Прежде чем вы отправитесь создавать круты сайты с базами данных, вам следует узнать что оба расширения MySQL имеют мощные функции отслеживания ошибок, которые могут уменьшить время разработки. Рассмотрите следующий пример, содержащий преднамеренную ошибку в строке запроса SELECT:

<?php

// подключаемся 
$connection = mysql_connect("localhost", "test", "test")
    or die("Неверно указан сервер или пользователь"); 
mysql_select_db("testdb", $connection) or die("Не могу выбрать базу данных"); 

// запрос 
$query = "SELECT FROM symbols"; 

// результат 
$result = mysql_query($query,$connection); 

// проверяемся на предмет ошибки и печатаем 
if(!$result) { 
    $error_number = mysql_errno(); 
    $error_msg = mysql_error(); 
    echo "Ошибка MySQL №$error_number: $error_msg";     
} 

// отключаемся 
mysql_close($connection);

?>

Этот пример выдаст следующее сообщение:

Ошибка MySQL №1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM t_tovars' at line 1

Функция mysql_errno() показывает код ошибки, возвращённый MySQL если она произошла в вашем SQL-запросе, а mysql_error() - возвращает само сообщение об ошибке. Используйте эти функции и вы заметно уменьшите время на поиск ошибок в коде.

Код расширения ext/mysqli имеет две дополнительных функции для ошибок подключения - mysqli_connect_errno() и mysqli_connect_error(), содержащие информацию только об ошибках соединения с сервером. Используйте их для проверки подключенией MySQL, как в примере ниже:

<?php

// создаём обьект mysqli
// открывает соединение
$mysqli = new mysqli("localhost", "test", "test", "testdb"); 

// проверяем ошибку соединения 
if (mysqli_connect_errno()) { 
    die("Не могу подключиться: ".mysqli_connect_error()); 
} 

// запрос 
$query = "SELECT FROM symbols"; 

// execute query 
$result = $mysqli->query($query); 

// ищем ошибки и печатаем 
if(!$result) { 
    $error_number = $mysqli->errno; 
    $error_msg = $mysqli->error; 
    echo "Ошибка MySQL №$error_number: $error_msg";     
} 

// отключается 
$mysqli->close();

?>

Если вам интересно почему я не использовал обьектный синтаксис для этих функций, отвечу: я не могу. Видите-ли, если есть ошибки подключения к серверу, то обьект mysqli не будет создан и поэтому его методы и свойства не будут существовать. По этой причине для отладки в ext/mysqli вам всегда надо использовать процедурный код, а не обьектный.

Вот и подошла к концу наша лекция. В девятой части я расскажу вам о встроенной в PHP альтернативе СУБД - очень крутом движке баз данных SQLite. Не вздумайте пропустить!

оригинал: http://www.figli-migli.org.ua/books/1082-php101-8b


В избранное