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

Очень просто о PHP, от элементарных понятий до ООП. Часть 9 - знакомство с работой в базе данных SQLite


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

Начали:


Тяжёлый выбор

Если вы читали предыдущие лекции, то вы уже знаете как использовать API в PHP для выполнения запросов и обработки полученного результата. Вы уже можете подумывать о том, как-бы переделать ваш сайт с поддержкой MySQL. Это хорошо и означает что вы уже достаточно хорошо разбираетесь в PHP, но у нас есть ещё несколько вещей, которые следовало-бы обсудить.

Как вы видели в восьмой лекции, поддержка MySQL в PHP 5.0 не так проста, как хотелось-бы. Вместо того чтобы поддерживать MySQL из коробки, PHP требует от вас выбора решений и библиотек для поддержки вашей версии MySQL. Если вы лентяй (в глубине души мы оба знаем правду), вместо MySQL можете попробовать более простой вариант: движок базы данных SQLite.

Встроенная поддержка SQLite является новинкой в PHP 5.0 и предлагает пользователям быстрый и эффективный доступ к системе баз данных. Поскольку она включена по умолчанию в PHP 5.0, то она обеспечивает жизнеспособную альтернативу MySQL, вы можете использовать её из коробки не тратя время на проверку и подгрузку версий библиотек, просто установите PHP 5 и начинайте печатать. Вот почему я посвятил целую лекцию этой теме - так вставайте-же с постели, сделайте себе кофе и давайте начнем!

Заводим новых друзей

Перед углублением в код давайте убедимся в том, что мы имеем чёткое представление о том, чем является SQLite (и не является). В отличие от MySQL, которая работает на клиент-серверной основе, SQLite - это файловая база данных и использует файловые функции ввода-вывода для хранения данных и чтения из файлов на диске. Она намного, намного меньше чем MySQL - в версии командной строки SQLite занимает менее 200 KB - и поддерживает большинство SQL-команд, которые вы привыкли использовать.

Однако небольшой размер не должен вас обмануть - в соответствии с официальным веб-сайтом SQLite, она поддерживает базы данных размером до двух терабайт и быстрее чем MySQL в определенных ситуациях. Файлы баз данных SQLite легко переносимы, SQLite-базы данных созданы и прекрасно работают на Windows и *nix-платформах.

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

Еще одно важное различие между MySQL и SQLite заключается в их политике лицензирования: в отличие от MySQL, исходный код SQLite имеет полностью открытый доступ, а это означает, что вы можете использовать и распространять его, однако вам надо выбрать между коммерческим и некоммерческим типом продукта. Подробнее читайте на http://sqlite.org/copyright.html.

Для того чтобы использовать PHP и SQLite, ваш версия PHP должна включать SQLite. Она включена по умолчанию в обоих UNIX- и Windows-версиях PHP 5. Подробнее об этом читайте на http://www.php.net/manual/en/ref.sqlite.php. Однако, если вы являетесь пользователем PHP 4.x, не отчаивайтесь - вы все еще можете использовать SQLite, вручную загрузив и установив php_sqlite.dll с сайта http://snaps.php.net (Windows) или последний архив с http://pecl.php.net/package/SQLite (UNIX). Вам не нужно скачивать ничего кроме этого; клиент SQLite 'является собственно движком.

Книжный червь возвращается

Как и в MySQL, вы используете обычные SQL-команды для работы с базой данных SQLite. Точный синтаксис SQL, используемый SQLite, описан на странице http://sqlite.org/lang.html, но большинство команд SQL стандартны.

Вот пример, создающий таблицу, которую мы будем использовать в этой лекции:

C:\WINDOWS\Desktop\sqlite>sqlite library.db 
SQLite version 2.8.15 
Enter ".help" for instructions 
sqlite> create table books ( 
   ...> id integer primary key, 
   ...> title varchar(255) not null, 
   ...> author varchar(255) not null 
   ...>); 
sqlite> insert into books (title, author) values ('Властелин колец', 'Дж. Р. Р. Толкиен'); 
sqlite> insert into books (title, author) values ('Убийство на улице Морг', 'Эдгар Алан По'); 
sqlite> insert into books (title, author) values ('Трое в лодке', 'Джером Клапка Джером'); 
sqlite> insert into books (title, author) values ('Этюд в багровых тонах', 'Артур Конан Дойл'); 
sqlite> insert into books (title, author) values ('Алиса в стране чудес', 'Льюис Кэрролл'); 
sqlite> .exit

Вы можете вводить эти команды или интерактивно, или неинтерактивно через программу командной строки SQLite, которая доступна по адресу http://sqlite.org/download.html в виде скомпилированной версии для Windows и Linux. Версия SQLite 2.* - используемая в настоящее время версия для обоих ветвей PHP, а SQLite 3.* предполагает поддержку PDO и поздних выпусков PHP 5.*.

Извлеките скачанные файлы в папку по выбору, перейдите в неё из окна командной строки и выполните 'sqlite'. Вы должны увидеть строку с версией SQLite и строку с приглашением выполнить команду .help:

C:\WINDOWS\Desktop\sqlite>sqlite
SQLite version 2.8.15 
Enter ".help" for instructions

Подробнее об использовании версии для командной строки написано на страничке http://sqlite.org/sqlite.html.

После того, как данные были успешно импортированы в наш файл библиотеки library.db, выполните запрос SELECT для проверки наших данных:

sqlite> select * from books;  
1|Властелин колец|Дж. Р. Р. Толкиен 2|Убийство на улице Морг|Эдгар Алан По 3|Трое в лодке|Джером Клапка Джером 4|Этюд в багровых тонах|Артур Конан Дойл 5|Алиса в стране чудес|Льюис Кэрролл

Если вы увидели такой-же вывод, как и здесь, то всё верно!

Урок анатомии

Теперь используйте PHP для общения с SQLite, получите тот-же результат и отформатируйте его в HTML-страницу. Вот код:

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

<?php

// установим путь к файлу базы данных (БД)
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 

// откроем файл БД
$handle = sqlite_open($db) or die("Не могу открыть базу данных"); 

// создадим строку запроса
$query = "SELECT * FROM books"; 

// выполним запрос
$result = sqlite_query($handle, $query)
 or die("Ошибка в запросе: ".sqlite_error_string(sqlite_last_error($handle))); 

// если есть строки 
if (sqlite_num_rows($result) > 0) { 
    // получаем каждую строку как массив
    // и печатаем данные
    echo "<table cellpadding=10 border=1>"; 
    while($row = sqlite_fetch_array($result)) { 
        echo "<tr>"; 
        echo "<td>".$row[0]."</td>"; 
        echo "<td>".$row[1]."</td>"; 
        echo "<td>".$row[2]."</td>"; 
        echo "</tr>"; 
    } 
    echo "</table>"; 
} 

// всё сделано 
// закрываем файл БД
sqlite_close($handle);

?>

</body>
</html>

Если всё прошло успешно, вы получите такой вывод:

1 Властелин колец Дж. Р. Р. Толкиен
2 Убийство на улице Морг Эдгар Алан По
3 Трое в лодке Джером Клапка Джером
4 Этюд в багровых тонах Артур Конан Дойл
5 Алиса в стране чудес Льюис Кэрролл

Если вы ещё помните что мы учили в восьмой части, то вам будет легко расшифровать код выше. Если не вышло, попробуем вместе:

  1. Начинаем с sqlite_open (), которая принимает имя файла базы данных в качестве аргумента и пытается открыть его. Если файл базы данных не может быть найден, то будет создан пустой файл базы данных с прилагаемым именем (в случае если сценарий имеет право на запись в каталоге).
    <?php
    
    // установим путь к файлу базы данных (БД)
    $db = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 
    
    // откроем файл БД
    $handle = sqlite_open($db) or die("Не могу открыть базу данных"); 
    
    // создадим строку запроса
    $query = "SELECT * FROM books"; 
    
    // выполним запрос
    $result = sqlite_query($handle, $query)
     or die("Ошибка в запросе: ".sqlite_error_string(sqlite_last_error($handle))); 
    
    ?>
    База данных library.db должна храниться в месте, недоступном через веб-браузер посетителя вашего сайта. Это означает что вам надо создать её вне вашей папки public_html, www или htdocs, но в папке, на которую у вашего скрипта есть доступ для чтения/записи. Компании - Web-хостеры обычно предоставляют такое место пользователям в родительской папке по отношению к корневой папке веб-сайта. У нас $_SERVER['DOCUMENT_ROOT']."/.." - это родительская папка для папки, доступной через web.
    В случе успеха функция sqlite_open() возвращает дескриптор файла, который сохраняется в переменной $handle и используется для последующего общения с базой данных.
  2. Следующий шаг - создать запрос и выполнить его при помощи функции sqlite_query():
    <?php
    
    $query = "SELECT * FROM books"; 
    $result = sqlite_query($handle, $query) or die("Ошибка в запросе: ".sqlite_error_string(sqlite_last_error($handle))); ?>
    Этой функции требуется два параметра: дескриптор базы данных и строка запроса. В зависимости от успешности запроса, функция возвратит истину или ложь, в случае неудачи для вывода информации об ошибке будут использованы функции sqlite_error_string() и sqlite_last_error().
  3. Если sqlite_query() была успешной, то набор результатов будет сохранён в переменной $result. Вы можете получать записи функцией sqlite_fetch_array(), которая выбирает одну строку данных из массива $row.
    Поля в этой записи представлены как элементы массива и доступны при помощи стандартной индексной нотации.
    При каждом вызове sqlite_fetch_array() будет возвращён следующий набор результатов. Это делает sqlite_fetch_array() очень удобной функцией для использования в цикле while(), так-же как и используемая нами ранее mysql_fetch_row().
    <?php
    
    if (sqlite_num_rows($result) > 0) { 
        // получаем каждую стркоу как массив
        // и печатаем данные
        echo "<table cellpadding=10 border=1>"; 
        while($row = sqlite_fetch_array($result)) { 
            echo "<tr>"; 
            echo "<td>".$row[0]."</td>"; 
            echo "<td>".$row[1]."</td>"; 
            echo "<td>".$row[2]."</td>"; 
            echo "</tr>"; 
        } 
        echo "</table>"; 
    } 
    
    ?>
    Число полученных записей может быть получено функций sqlite_num_rows(). Или, если вам интересно число полей, используйте функцию sqlite_num_fields(). Конечно, они применимы только если запрос возвращает записи; нет смысла применять их в запросах INSERT, UPDATE или DELETE.
  4. После завершения всех действий хорошим тоном считается закрыть дескриптор базы данных и вернуть занятую память системе вызовом функции sqlite_close():
    <?php
    
    sqlite_close($handle);
    
    ?>

В PHP 5 вы также можете использовать API SQLite в обьектно-ориентированном виде, тогда все функции станут методами обьекта SQLiteDatabase(). Посмотрите на следующий код, который эквивалентен предыдущему:

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

<?php

// установим путь к файлу БД
$file = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 

// создадим обьект БД
$db = new SQLiteDatabase($file) or die("Не могу открыть БД"); 

// создадим строку запроса
$query = "SELECT *  FROM books"; 

// выполним запрос
// получим обьект-результат
$result = $db->query($query) or die("Ошибка в запросе"); 

// если есть строки
if ($result->numRows() > 0) { 
    // получаем каждую строку как массив
    // печатаем результат
    echo "<table cellpadding=10 border=1>";
    while($row = sqlite_fetch_array($result)) { 
        echo "<tr>"; 
        echo "<td>".$row[0]."</td>"; 
        echo "<td>".$row[1]."</td>"; 
        echo "<td>".$row[2]."</td>"; 
        echo "</tr>"; 
    } 
    echo "</table>"; 
} 

// всё сделано
// уничтожим обьект БД
unset($db); ?> </body> </html>

Здесь для создания обьекта класса SQLiteDatabase() было использовано ключевое слово new с передачей имени файла базы данных. Если его не существует, то файл будет создан. Результирующий обьект, сохранённый в переменной $db, предоставляет нам методы и свойства для выполнения запросов. Каждый запрос возвращает экземпляр обьекта класса SQLiteResult(), который, в свою очередь, предоставляет нам методы для разбора и обработки записей.

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

Другой стиль

Как и API MySQL, API SQLite в PHP предоставляет больше одного способов поймать кота. Например, вы можете получить каждую строку как обьект методом sqlite_fetch_object() и получать значения полей, используя их имена как свойства обьекта. Пример:

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

<?php

// установим путь к файлу БД
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 

// откроем файл БД
$handle = sqlite_open($db) or die("Не могу открыть БД"); 

// создадим строку запроса
$query = "SELECT * FROM books"; 

// выполним запрос
$result = sqlite_query($handle, $query)
 or die("Ошибка в запросе: ".sqlite_error_string(sqlite_last_error($handle))); 

// если есть строки
if (sqlite_num_rows($result) > 0) { 
    // получим каждую строку как обьект
    // печатаем значения полей как свйоства обьекта
    echo "<table cellpadding=10 border=1>";
    while($row = sqlite_fetch_array($result)) { 
        echo "<tr>"; 
        echo "<td>".$row[0]."</td>"; 
        echo "<td>".$row[1]."</td>"; 
        echo "<td>".$row[2]."</td>"; 
        echo "</tr>"; 
    } 
    echo "</table>"; 
} 

// всё сделано
// запроем файл БД sqlite_close($handle); ?> </body> </html>

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

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

<?php

// установим путь к файлу БД
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 

// откроем файл БД
$handle = sqlite_open($db) or die("Не могу открыть БД"); 

// создадим строку запроса
$query = "SELECT * FROM books"; 

// выполним запрос
$result = sqlite_query($handle, $query)
or die("Ошибка в запросе: ".sqlite_error_string(sqlite_last_error($handle))); 

// получим полный набор результатов
// как последовательность вложенных массивов
$data = sqlite_fetch_all($result); 

// всё сделано
// закроем файл БД
sqlite_close($handle); 

// проверим, содержит-ли массив хотя-бы одну запись
if (sizeof($data) > 0) { 
    echo "<table cellpadding=10 border=1>"; 
    // проходим по внешнему массиву (по строкам результата) 
    // печатаем значения каждого элемента внутреннего массива (колонки результата) 
    foreach ($data as $row) { 
        echo "<tr>"; 
        echo "<td>".$row[0]."</td>"; 
        echo "<td>".$row[1]."</td>"; 
        echo "<td>".$row[2]."</td>"; 
        echo "</tr>"; 
    } 
    echo "</table>"; 
}

?>

</body>
</html>

Во всех предыдущих примерах база данных оставалась открытой во время обработки набор результатов, так как записи получались одна за другой функциями sqlite_fetch_array() или sqlite_fetch_object(). В последней примере особенность в том, что база данных может быть закрыта перед обработкой набора результатов. Это возможно благодаря тому, что весь набор результатов был получен единовременно и сохранён в массив $data array, так что больше нет необходимости держать БД открытой.

Если ваш набор результатов содержит только одно поле, используйте функцию sqlite_fetch_single(), которая получает значение первого поля в строке. Руководство по PHP поясняет эту функцию лучше всего: "Это самый оптимальный путь для получения данных, когда вы заинтересованы только в значениях одного столбца данных." Посмотрите:

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

<?php

// устанавливаем буть к БД
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 

// открываем файл БД
$handle = sqlite_open($db) or die("Не могу открыть БД"); 

// создаём стркоу запроса
// этот запрос вернёть только одну запись с одним полем
$query = "SELECT author FROM books WHERE title = 'Этюд в багровых тонах'"; 

// выполним запрос
$result = sqlite_query($handle, $query)
 or die("Ошибка в запросе: ".sqlite_error_string(sqlite_last_error($handle))); 

// если строка получена
if (sqlite_num_rows($result) > 0) { 
    // получим значение первого поля первой строки
    echo sqlite_fetch_single($result); 
} 

// всё сделано 
// закроываем файл БД
sqlite_close($handle);

?>

</body>
</html>

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

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

<?php

// устанвоим путь к файлу БД
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 

// откроем файл БД
$handle = sqlite_open($db) or die("Не могу открыть БД"); 

// создадим строку запроса 
$query = "SELECT DISTINCT author FROM books"; 

// выполним запрос 
$result = sqlite_query($handle, $query)
 or die("Ошибка в запросе: ".sqlite_error_string(sqlite_last_error($handle))); 

// если строка существует
if (sqlite_num_rows($result) > 0) { 
    echo "<table cellpadding=10 border=1>"; 
    // проверим, есть-ли ещё строки 
    while (sqlite_has_more($result)) { 
        // получим первое поле каждой строки
        // напечатаем значение
        $row = sqlite_fetch_single($result); 
        echo "<tr>"; 
        echo "<td>".$row."</td>"; 
        echo "</tr>"; 
    } 
    echo "</table>"; 
} 

// всё сделано
// закроем файл БД
sqlite_close($handle);

?>

</body>
</html>

Конечно, вы можете использовать обьектную нотацию в PHP 5. Однако, вам надо знать, что sqlite_has_more() - функция, которая не транслируется в имя метода обьекта; в ООП-скрипте вам надо использовать метод $result->valid();.
ООП-скрипт, эквивалентный предыдущему:

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

<?php

// установим путь к БД
$file = $_SERVER['DOCUMENT_ROOT']."/../library.db"; 

// создадим обьект БД
$db = new SQLiteDatabase($file) or die("Не могу открыть БД"); 

// создадим строку запроса
$query = "SELECT DISTINCT author FROM books"; 

// выполним запрос
$result = $db->query($query) or die("Ошибка в запросе"); 

// если строка существует 
if ($result->numRows() > 0) { 
    echo "<table cellpadding=10 border=1>"; 
    // проверим, есть-ли ещё строки 
    while ($result->valid()) { 
        // получим первое поле каждой строки
        // напечатаем значение
        $row = $result->fetchSingle(); 
        echo "<tr>"; 
        echo "<td>".$row."</td>";     
        echo "</tr>"; 
    } 
    echo "</table>"; 
} 

// всё сделано
// уничтожим обьект БД
unset($db);

?>

</body>
</html>

Продолжение читайте во второй части лекции.

Оригинал статьи: http://www.figli-migli.org.ua/books/1377-php101-9a


В избранное