От автора: Добро пожаловать в третью часть урока по созданию FAQ с использованием текстовых файлов в качестве БД. Данная часть будет заключительной, и здесь мы реализуем второй пункт меню административной части — удаление пары вопрос-ответ. Заодно мы познакомимся еще с несколькими новыми функциями PHP, которые и будем использовать при написании заключительной части проекта.
Итак, приступим…
План урока:
1. Читаем содержимое файла (11:17)
2. Выводим ссылки для удаления (09:40)
3. Удаляем выбранную пару вопрос-ответ (11:31)
4. Записываем в файл (08:15)
1. Читаем содержимое файла
Работать здесь мы будем с файлом add.php, а потому откройте его в удобном для Вас редакторе и приступим к кодированию. Но, как всегда, прежде чем приступить к написанию кода — нам необходимо понять для себя, что же мы хотим в итоге получить, т.е. построить алгоритм… ну а затем реализовать его.
Итак, нам нужно вывести в любом удобном виде первую часть каждой из строк файла base.txt, т.е. вопросы и предоставить пользователю возможность выбрать вопрос для удаления. Вывод можно реализовать, к примеру, вместе с радиокнопками или чекбоксами, или просто вывести вопросы ссылками. Мы выберем последний вариант — выведем вопросы ссылками, и при клике на конкретную ссылку будет удалена строка с выбранным вопросом и ответом к нему. Также необходимо сделать так, чтобы после удаления файл снова считывался и список вопросов выводился, соответственно, уже без удаленного на предыдущем шаге вопроса. Вот и весь алгоритм вратце.
Реализуем его теперь в коде.
Прежде всего, нужно прочитать файл в массив. Ранее мы делали это, используя функцию fgets(), и построчно считывая файл в массив. При этом перед считыванием файла его нужно было открыть функцией fopen(). Теперь мы расширим наши знания и попробуем воспользоваться другой функцией — функцией file(). Для работы этой функции не нужно уже открывать файл при помощи fopen(), и функция file() также считывает содержимое необходимого файла в массив. Проверим, получим ли мы массив:
1 2 3 4 5 6 7 8 9 10 11 |
<?php require_once 'menu.php'; ?> <p>Здесь можно удалить пару вопрос-ответ. Для этого просто кликните по тому вопросу, который хотите удалить.</p> <?php $file = file('../base.txt'); echo '<pre>'; print_r($file); echo ' |
’;
?>
Распечатав массив $file, мы увидим, что получили действительно массив, элементами которого являются строки файла base.txt.
Замечательно! Продолжим…
2. Выводим ссылки для удаления
Итак, массив у нас есть. Теперь нужно вывести его элементы ссылками. Но вся строк нам не подойдет — нас нужна только первая ее часть, т.е. вопрос. Для того, чтобы получить только вопрос мы можем сделать все также, как и в первой части урока, т.е. воспользоваться функцией explode() и в цикле пройтись по всем элементам массива, чтобы разделить вопрос и ответ… Но можно сделать и гораздо проще. Поможет нам строковая функция strtok().
Ее синтаксис:
1 |
strtok(обрабатываемая строка, разделитель); |
Работа функции заключается в том, что она возвращает подстроку до разделителя, т.е. именно то, что нам и нужно — вопрос (часть строки до разделителя «//»). Пройдемся по массиву в цикле:
1 2 3 4 5 6 7 8 9 |
<?php $file = file('../base.txt'); foreach($file as $item){ $question = strtok($item, '//'); echo '<a href="">' .$question. '</a><br />'; } ?> |
Замечательно!
Мы получили только вопросы. Теперь необходимо указать ссылки для каждого из них. Как мы и договаривались, по клику на вопрос будет удалена соответствующая строка из файла. Все просто… но как нам понять по какому именно вопросу произошел клик? Чтобы ответить на этот вопрос, давайте его немного перефразируем. Как нам понять по какому именно элементу массива произошел клик? Если все же кто-то еще не догадался, то все очень просто. У каждого элемента есть ключ. Вот этот вот ключ мы и будем добавлять в качестве параметра к ссылке, а по клику по ссылке он и будет передаваться дальше в скрипт. Передаваться этот параметр будет через адресную строку (он ведь присоединяется к ссылке), т.е. методом GET. А получить ключ можно немного дописав цикл foreach, в котором сейчас мы получаем только значения элементов. Укажем, что нам нужны не только значения, но и их ключи:
1 2 3 4 5 6 7 8 |
<?php $file = file('../base.txt'); foreach($file as $key => $item){ $question = strtok($item, '//'); echo '<a href="">' .$question. '</a><br />'; } ?> |
В указанной переменной $key на каждом прохождении цикла (на каждой итерации) и будет ключ текущего элемента массива. Осталось разобраться с адресом ссылки. Ссылка будет вести на эту же страницу, т.е. на del.php. Добавить к ссылке параметр можно через вопросительный знак. После адреса указываем вопросительный знак, а после него пишем нужный параметр и его значение. Параметр назовем «question», а значением его, как уже говорилось, будет текущий ключ:
1 2 3 4 5 6 7 8 |
<?php $file = file('../base.txt'); foreach($file as $key => $item){ $question = strtok($item, '//'); echo '<a href="del.php?question=' .$key. '">' .$question. '</a><br />'; } ?> |
Если теперь посмотреть на строку состояния в браузере при наведении на ссылки, то можно заметить, что у разных ссылок будет различное значение параметра question — от нуля и далее в порядке увеличения на единицу. Также можно обезопасить работу программы от случайных кликов по ссылкам, т.е. добавить подтверждение удаления — при клике на ссылке будет выведено модальное окно, где пользователь должен подтвердить желание удаления, если будет подтверждение — перейдем по ссылке, иначе — переход отменяется:
1 2 3 4 5 6 7 8 |
<?php $file = file('../base.txt'); foreach($file as $key => $item){ $question = strtok($item, '//'); echo '<a href="del.php?question=' .$key. '" onclick="return confirm(\'Удалить?\')">' .$question. '</a><br />'; } ?> |
3. Удаляем выбранную пару вопрос-ответ
Отлично!
Теперь мы можем узнать какая именно строка файла выбрана для удаления — мы получаем ключ элемента массива. А если мы знаем какой элемент массива пользователь желает удалить, то нам не составит особого труда удалить искомый элемент из массива. Для этого мы должны проверить передан ли GET-параметр (т.е. был ли клик по ссылке). Этот параметр будет, как уже говорилось, ключем элемента массива. Если такой параметр есть, то мы считаем файл в массив, а следующим шагом просто удалим элемент массива, ключ которого будет равен полученному GET-параметру. Все просто. В самом верху страницы проверяем есть ли элемент question в глобальном массиве GET:
1 2 3 4 5 6 7 |
<?php if(isset($_GET['question'])){ } require_once 'menu.php'; ?> |
Если такой элемент есть, то будем выполнять оговоренные действия в операторных скобках. Если же параметра нет, то указанный блок действий будет игнорироваться.
Итак, если параметр есть, то мы создадим переменную $question и присвоим ей значение элемента question из глобального массива GET. Далее прочитаем файл и получим массив. Ну а затем — удалим соответствующий элемент массива. Удалить элемент можно при помощи уже знакомой Вам функции unset():
1 2 3 4 5 6 7 8 9 10 |
<?php if(isset($_GET['question'])){ $question = $_GET['question']; $file = file('../base.txt'); unset($file[$question]); } require_once 'menu.php'; ?> |
Теперь если мы протестируем код и распечатаем массив после удаления элемента, то увидим, что после клика по ссылке выводится массив на экран, но уже без выбранного элемента массива.
4. Записываем в файл
Итак, массив без выбранного элемента мы уже получили. Что же нам с ним теперь делать? Все просто… осталось его только записать в файл base.txt. При этом следует учитывать, что мы должны перезаписать указанный файл — для этого его достаточно открыть в соответствующем режиме, а именно — в режиме «w». Здесь ничего нового для нас нет:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php $question = $_GET['question']; $file = file('../base.txt'); unset($file[$question]); $handle = fopen('../base.txt', 'w'); foreach($file as $item){ fwrite($handle, $item); } fclose($handle); require_once 'menu.php'; ?> |
Замечательно — все работает так, как мы и хотели. Остался последний штрих — нам нужно прописать редирект сразу после закрытия файла. Для чего это нужно? Достаточно взглянуть на адресную строку и увидеть, что там сохранился адрес вместе с GET-параметром. Это не есть хорошо, поскольку, если мы удалили элемент из середины массива, то все оставшиеся элементы сдвинутся на единицу вниз, т.е., если мы удалим, к примеру, элемент с ключем 3, то 3-им после удаления станет элементы, который до удаления имел ключ 4. Чем это плохо? Да тем, что если будет обновлена страница, то удалится еще один элемент. Чтобы этого не допустить — просто сделаем редирект на страницу del.php и теперь обновление нам не страшно:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php if(isset($_GET['question'])){ $question = $_GET['question']; $file = file('../base.txt'); unset($file[$question]); $handle = fopen('../base.txt', 'w'); foreach($file as $item){ fwrite($handle, $item); } fclose($handle); header("Location: del.php"); exit; } require_once 'menu.php'; ?> |
Вот и все.
Заключение
На протяжении 3-х уроков мы реализовали все поставленные нами цели — создали систему FAQ и в качестве хранилища информации использовали уже не БД, а текстовые файлы. Кроме того, мы написали простенькую административную часть, благодаря которой можем добавлять и удалять пары вопрос-ответ уже через нее.
На этом наш урок закончен. Ждем от Вас вопросов и новых идей!
С уважением Андрей Кудлай
Автор: Кудлай Андрей
Редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.
Комментарии (13)