FAQ с использованием PHP-jQuery и текстовых файлов. Часть 3 (заключительная)

FAQ с использованием PHP-jQuery

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

Итак, приступим…

План урока:

    1. Читаем содержимое файла (11:17)

    2. Выводим ссылки для удаления (09:40)

    3. Удаляем выбранную пару вопрос-ответ (11:31)

    4. Записываем в файл (08:15)

скачать исходникискачать урок

 

1. Читаем содержимое файла

Работать здесь мы будем с файлом add.php, а потому откройте его в удобном для Вас редакторе и приступим к кодированию. Но, как всегда, прежде чем приступить к написанию кода — нам необходимо понять для себя, что же мы хотим в итоге получить, т.е. построить алгоритм… ну а затем реализовать его.

Итак, нам нужно вывести в любом удобном виде первую часть каждой из строк файла base.txt, т.е. вопросы и предоставить пользователю возможность выбрать вопрос для удаления. Вывод можно реализовать, к примеру, вместе с радиокнопками или чекбоксами, или просто вывести вопросы ссылками. Мы выберем последний вариант — выведем вопросы ссылками, и при клике на конкретную ссылку будет удалена строка с выбранным вопросом и ответом к нему. Также необходимо сделать так, чтобы после удаления файл снова считывался и список вопросов выводился, соответственно, уже без удаленного на предыдущем шаге вопроса. Вот и весь алгоритм вратце.

Реализуем его теперь в коде.

Прежде всего, нужно прочитать файл в массив. Ранее мы делали это, используя функцию fgets(), и построчно считывая файл в массив. При этом перед считыванием файла его нужно было открыть функцией fopen(). Теперь мы расширим наши знания и попробуем воспользоваться другой функцией — функцией file(). Для работы этой функции не нужно уже открывать файл при помощи fopen(), и функция file() также считывает содержимое необходимого файла в массив. Проверим, получим ли мы массив:

<?php
require_once 'menu.php';
?>
<p>Здесь можно удалить пару вопрос-ответ. Для этого просто кликните по тому вопросу, который хотите удалить.</p>

<?php
$file = file('../base.txt');

echo '<pre>';
print_r($file);
echo '</pre>';
?>

Распечатав массив $file, мы увидим, что получили действительно массив, элементами которого являются строки файла base.txt.

Замечательно! Продолжим…

2. Выводим ссылки для удаления

Итак, массив у нас есть. Теперь нужно вывести его элементы ссылками. Но вся строк нам не подойдет — нас нужна только первая ее часть, т.е. вопрос. Для того, чтобы получить только вопрос мы можем сделать все также, как и в первой части урока, т.е. воспользоваться функцией explode() и в цикле пройтись по всем элементам массива, чтобы разделить вопрос и ответ… Но можно сделать и гораздо проще. Поможет нам строковая функция strtok().

Ее синтаксис:

strtok(обрабатываемая строка, разделитель);

Работа функции заключается в том, что она возвращает подстроку до разделителя, т.е. именно то, что нам и нужно — вопрос (часть строки до разделителя «//»). Пройдемся по массиву в цикле:

<?php
$file = file('../base.txt');

foreach($file as $item){
	$question = strtok($item, '//');
	echo '<a href="">' .$question. '</a><br />';
}

?>

Замечательно!

Мы получили только вопросы. Теперь необходимо указать ссылки для каждого из них. Как мы и договаривались, по клику на вопрос будет удалена соответствующая строка из файла. Все просто… но как нам понять по какому именно вопросу произошел клик? Чтобы ответить на этот вопрос, давайте его немного перефразируем. Как нам понять по какому именно элементу массива произошел клик? Если все же кто-то еще не догадался, то все очень просто. У каждого элемента есть ключ. Вот этот вот ключ мы и будем добавлять в качестве параметра к ссылке, а по клику по ссылке он и будет передаваться дальше в скрипт. Передаваться этот параметр будет через адресную строку (он ведь присоединяется к ссылке), т.е. методом GET. А получить ключ можно немного дописав цикл foreach, в котором сейчас мы получаем только значения элементов. Укажем, что нам нужны не только значения, но и их ключи:

<?php
$file = file('../base.txt');

foreach($file as $key => $item){
	$question = strtok($item, '//');
	echo '<a href="">' .$question. '</a><br />';
}
?>

В указанной переменной $key на каждом прохождении цикла (на каждой итерации) и будет ключ текущего элемента массива. Осталось разобраться с адресом ссылки. Ссылка будет вести на эту же страницу, т.е. на del.php. Добавить к ссылке параметр можно через вопросительный знак. После адреса указываем вопросительный знак, а после него пишем нужный параметр и его значение. Параметр назовем «question», а значением его, как уже говорилось, будет текущий ключ:

<?php
$file = file('../base.txt');

foreach($file as $key => $item){
	$question = strtok($item, '//');
	echo '<a href="del.php?question=' .$key. '">' .$question. '</a><br />';
}
?>

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

<?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:

<?php
if(isset($_GET['question'])){
	
}

require_once 'menu.php';
?>

Если такой элемент есть, то будем выполнять оговоренные действия в операторных скобках. Если же параметра нет, то указанный блок действий будет игнорироваться.
Итак, если параметр есть, то мы создадим переменную $question и присвоим ей значение элемента question из глобального массива GET. Далее прочитаем файл и получим массив. Ну а затем — удалим соответствующий элемент массива. Удалить элемент можно при помощи уже знакомой Вам функции unset():

<?php
if(isset($_GET['question'])){
	$question = $_GET['question'];
	$file = file('../base.txt');
	
	unset($file[$question]);
}

require_once 'menu.php';
?>

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

4. Записываем в файл

Итак, массив без выбранного элемента мы уже получили. Что же нам с ним теперь делать? Все просто… осталось его только записать в файл base.txt. При этом следует учитывать, что мы должны перезаписать указанный файл — для этого его достаточно открыть в соответствующем режиме, а именно — в режиме «w». Здесь ничего нового для нас нет:

<?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 и теперь обновление нам не страшно:

<?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.

Курс по программированию на языке PHP

Изучите PHP с нуля до результата!

Смотреть курс

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (13)

  1. Kevin

    А причем тут jQuery?

    • Андрей Кудлай

      При том, что FAQ реализован в том числе и посредством использования jQuery. Это заключительная часть цикла по созданию системы ответов на частые вопросы. В первых уроках цикла как раз рассматривался вопрос использования jQuery.

      • Kevin

        ну так не лучше было бы уже и реализовать удаление через аякс без перезагрузки страницы, а обновление только блока с вопросами? тогда это было бы лучшее представление связки PHP-jQuery. Имхо

        • Андрей Кудлай

          Вы правы — лучше. Можно и добавление, и удаление реализовать посредством асинхронных запросов. Но это отнюдь не входило в задачи урока. Вчитайтесь в комменты на сайте — отдельным пользователям сложновато понять даже то, что есть в уроке на данный момент.
          Хотя отличная идея записать еще один урок, где обновление будем осуществлять при помощи AJAX… спасибо за идею — поставим в план :)
          Кстати, если Вы запишите такой урок — будем только рады.

          • Koko

            Хотя отличная идея записать еще один урок, где обновление будем осуществлять при помощи $_COOKIE! А то закрыл браузер вдруг и все сначало.
            Спасибо за видео. Андрей PHP-молодец.

  2. Юрий

    Интересные решения, но я в РНР слабоват, трудновато воспринимается.

  3. Артур

    Система настолько сложна, что описание, как сделать её ушло аж на 3 статьи!

    • Андрей Кудлай

      Ну, не сказал бы, что она настолько сложна… хотя, если для кого-то это может быть сложным, то никто не возбраняет начинать с чего-нибудь попроще. В первом уроке для вывода данных имеем 10 строк кода, во второй части — 30 строк и в третьей — 10 строк.
      Итого — около 50 строк кода для полноценной системы… это совсем немного. Все это можно было бы вместить и в 1 урок, но тогда пострадало бы качество подачи материала.

  4. Игорь

    Андрей Кудлай, всн нормально. Не слушай. Только уроки пытайся сделать мобильней, чтобы не на несколько частей ) Спасибо.

  5. alt

    Андрей, а как вывести (программно в рнр) определенное кол-во FAQ (от 1 до 3-х) на странице?

    • Андрей Кудлай

      То, что Вы имеете в виду — это так называемая постраничная навигация. Как раз один из следующих уроков, которые планируется записать, будет посвящен этой теме… так что дождитесь :)
      Если рассмотреть алгоритм, то он будет примерно таким:
      1. Выбираем все пары вопрос-ответ в массив.
      2. Считаем количество элементов массива (к примеру их 10).
      3. Считаем сколько у нас будет страниц (если по 3 пары на страницу, то получим 4 страницы: 10/3=4(здесь округление в бОльшую сторону)).
      4. В цикле выводим указатели на страницы (1|2|3|4), при этом указатель передает соответствующий GET-параметр (кроме того, на котором мы сейчас находимся).
      5. При клике на указатель (к примеру, 3) получаем GET-параметр и по формуле ((3-1)*(кол-во на страницу)) отдаем записи с 6 по 9…
      Это вкратце. Несколько вариантов постраничной навигации рассмотрим, как говорилось выше, далее… Дождитесь ;)

  6. masik

    Андрей, а в чем смысл этой админки?
    Я же могу, как админ сайта, через FTP открыть base.txt и не только добавить запись или удалить ее, но и отредактировать нужную информацию?
    А за познавательный урок держи лайк!
    С уважением…

    • Андрей Кудлай

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree