FAQ с использованием PHP-jQuery и текстовых файлов. Часть 2

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

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

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

План урока:

    1. Создаем форму добавления данных (12:28)

    2. Пишем обработчик. Часть 1 (11:12)

    3. Пишем обработчик. Часть 2 (11:36)

    4. Пишем обработчик. Часть 3 (13:23)

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

 

1. Создаем форму добавления данных

Первое, что нам понадобится — это каталог нашей админки. Создадим каталог admin и в нем создадим 5 пустых (пока что) файлов:

index.php (стартовая страница админки);

menu.php (пункты меню);

new.php (страница добавления пары вопрос-ответ);

add.php (обработчик файла new.php);

del.php (страница удаления пары вопрос-ответ);

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

<ul>
	<li><a href="index.php">Главная</a></li>
	<li><a href="new.php">Добавление вопроса-ответа</a></li>
	<li><a href="del.php">Удаление вопроса-ответа</a></li>
</ul>
<hr />

Файл меню мы будем подключать во все необходимые файлы. Сделать это можно при помощи функции require_once(). Пока что нам понадобится для работы файл new.php, в котором необходимо поместить форму для добавления пары вопрос-ответ. Добавим 2 текстовые области и кнопку отправления данных:

<?php
require_once 'menu.php';
?>
<p>Здесь можно добавить новую пару вопрос-ответ</p>

<form method="post" action="add.php">
	<table>
		<tr>
			<td>Введите вопрос: </td>
			<td><textarea rows="3" cols="40" name="question"></textarea></td>
		</tr>
		<tr>
			<td>Введите ответ: </td>
			<td><textarea rows="7" cols="40" name="answer"></textarea></td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit" name="submit" value="Добавить"></td>
		</tr>
	</table>
</form>

Здесь ничего сложного нет и все должно быть понятным. Первой текстовой области мы дали имя question (в нее вводится вопрос), второй — answer (в нее вводится ответ).

Форма создана — можно приступать к написанию обработчика для нее.

2. Пишем обработчик. Часть 1.

Обработчиком будет файл add.php — именно его мы указали в атрибуте формы action. Прежде, чем мы приступим к кодированию, поговорим немного о том, чего мы хотим, и об алгоритме работы скрипта. Прежде всего, мы должны сделать так, чтобы попасть на страницу-обработчик можно было только из формы, т.е., нажав кнопку формы. Далее, нам необходимо, чтобы были заполнены обе текстовые области формы. Если же какое-то из полей формы не заполнено, то мы должны информировать об этом пользователя, указывая какое именно поле осталось пустым. Также, в случае ошибки, уже заполненное поле должно оставаться заполненным, чтобы пользователь не заполнял его дважды.

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

Алгоритм будет прост.

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

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

Вроде алгоритм не слишком сложен — попробуем его реализовать. Первым пунктом программы является проверка нажатия кнопки формы. Сделать это можно проверив наличие элемента submit (именно такое имя мы дали кнопке формы) в глобальном массиве POST, если такой элемент есть — кнопка была нажата, иначе — делаем редирект на страницу с формой. В принципе, об этом уже неоднократно я упоминал в ряде предыдущих уроков. Пропишем в файле add.php:

if($_POST['submit']){
}else header("Location: new.php");

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

Теперь создадим 3 переменные:

if($_POST['submit']){
	$answer = trim($_POST['answer']);
	$question = trim($_POST['question']);
	$error = '';
}else header("Location: new.php");

Переменные $answer и $question принимают значения из глобального массива POST, а $error, как мы и договаривались, изначально создается с пустым значением. Заметьте, что переменным вопроса и ответа присваиваются значения из массива POST, обработанные функцией trim(). Эта функция обрезает пробелы с начала и конца строки.

Для чего мы так сделали?

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

Теперь проверим, пусты ли значения полученных переменных — сделать это нам поможет функция empty():

if($_POST['submit']){
	$answer = trim($_POST['answer']);
	$question = trim($_POST['question']);
	$error = '';
	if(empty($question)) $error .= '<p>Поле вопроса обязательно для заполнения!</p>';
	if(empty($answer)) $error .= '<p>Поле ответа обязательно для заполнения!</p>';
}else header("Location: new.php");

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

А теперь нам достаточно проверить осталось ли пустым значение $error. Если это так — значит все ок, иначе — пользователь что-то не заполнил:

if($_POST['submit']){
	$answer = trim($_POST['answer']);
	$question = trim($_POST['question']);
	$error = '';
	if(empty($question)) $error .= '<p>Поле вопроса обязательно для заполнения!</p>';
	if(empty($answer)) $error .= '<p>Поле ответа обязательно для заполнения!</p>';

	if(empty($error)){
		// заполнены оба поля
	}else{

	}
}else header("Location: new.php");

3. Пишем обработчик. Часть 2.

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

Также в обработчике создадим сессионную переменную $_SESSION['res'], в которую поместим значение $error. После создания сессионной переменной сделаем редирект и завершим работу программы:

session_start();
if($_POST['submit']){
	$answer = trim($_POST['answer']);
	$question = trim($_POST['question']);
	$error = '';
	if(empty($question)) $error .= '<p>Поле вопроса обязательно для заполнения!</p>';
	if(empty($answer)) $error .= '<p>Поле ответа обязательно для заполнения!</p>';

	if(empty($error)){
		// заполнены оба поля
	}else{
		$_SESSION['res'] = $error;
		header("Location: new.php");
		exit;
	}
}else header("Location: new.php");

Теперь мы можем вывести значение переменной $_SESSION['res'] в нужном месте на странице формы. Также после вывода переменной разрегистрируем все сессионные переменные (у нас еще будет парочка таких) и закроем сессию. Делаем мы это для того, чтобы все сообщения сессии выводились только один раз — больше нам не нужно:

<?php
session_start();
require_once 'menu.php';
?>
<p>Здесь можно добавить новую пару вопрос-ответ</p>

<form method="post" action="add.php">
	<table>
		<tr>
			<td>Введите вопрос: </td>
			<td><textarea rows="3" cols="40" name="question"></textarea></td>
		</tr>
		<tr>
			<td>Введите ответ: </td>
			<td><textarea rows="7" cols="40" name="answer"></textarea></td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit" name="submit" value="Добавить"></td>
		</tr>
	</table>
</form>
<?php
echo $_SESSION['res'];
session_unset();
session_destroy();
?>

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

Сделать это просто.

Достаточно в обработчике зарегистрировать еще 2 сессионные переменные и присвоить им значение соответствующих переменных $answer и $question. Ну а в форме вывести эти переменные в качестве значений текстовых областей. Код файла add.php:

session_start();
if($_POST['submit']){
	$answer = trim($_POST['answer']);
	$question = trim($_POST['question']);
	$error = '';
	if(empty($question)) $error .= '<p>Поле вопроса обязательно для заполнения!</p>';
	if(empty($answer)) $error .= '<p>Поле ответа обязательно для заполнения!</p>';

	if(empty($error)){
		// заполнены оба поля
	}else{
		$_SESSION['res'] = $error;
		$_SESSION['question'] = $question;
		$_SESSION['answer'] = $answer;
		header("Location: new.php");
		exit;
	}
}else header("Location: new.php");

Код файла new.php:

<?php
session_start();
require_once 'menu.php';
?>
<p>Здесь можно добавить новую пару вопрос-ответ</p>

<form method="post" action="add.php">
	<table>
		<tr>
			<td>Введите вопрос: </td>
			<td><textarea rows="3" cols="40" name="question"><?php echo $_SESSION['question']; ?></textarea></td>
		</tr>
		<tr>
			<td>Введите ответ: </td>
			<td><textarea rows="7" cols="40" name="answer"><?php echo $_SESSION['answer']; ?></textarea></td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit" name="submit" value="Добавить"></td>
		</tr>
	</table>
</form>
<?php
echo $_SESSION['res'];
session_unset();
session_destroy();
?>

А теперь можно переходить к добавлению значений полей формы в файл base.txt.

4. Пишем обработчик. Часть 3.

Поскольку данные о каждой паре вопрос-ответ в текстовом файле мы храним построчно — нам необходимо перед записью объединить значения переменных $question и $answer в одну строку, не забыв при этом добавить разделитель. Также перед записью новой строки мы должны открыть файл в соответствующем режиме — в режиме записи, а точнее — в режиме ДОзаписи (режим «а»). Код теперь будет таким:

session_start();
if($_POST['submit']){
	$answer = trim($_POST['answer']);
	$question = trim($_POST['question']);
	$error = '';
	if(empty($question)) $error .= '<p>Поле вопроса обязательно для заполнения!</p>';
	if(empty($answer)) $error .= '<p>Поле ответа обязательно для заполнения!</p>';

	if(empty($error)){
		// заполнены оба поля
		$handle = fopen('../base.txt', 'a');
		$string = $question. '//' .$answer. "\r\n";
	}else{
		$_SESSION['res'] = $error;
		$_SESSION['question'] = $question;
		$_SESSION['answer'] = $answer;
		header("Location: new.php");
		exit;
	}
}else header("Location: new.php");

Заметим, что в конце строки мы также добавили следующие символы — «\r\n». Это символы переноса строки.

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

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

Чтобы исключить его вывод на странице сайта, достаточно немного изменить код страницы faq.php и в блоке foreach() добавить проверку. В условии проверки мы будем выводить на экран только те элементы массива, которые не пусты. Новый код соответствующего блока страницы faq.php будет таким:

foreach($read as $item){
	if(!empty($item)){
		$data[] = explode('//', $item);
		echo '<div class="question">' .$data[$i][0]. '</div>';
		echo '<div class="answer">' .$data[$i][1]. '</div>';
		$i++;
	}
}

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

Остался последний шаг — записать полученную строку в файл:

<?php
session_start();
if($_POST['submit']){
	$answer = trim($_POST['answer']);
	$question = trim($_POST['question']);
	$error = '';
	if(empty($question)) $error .= '<p>Поле вопроса обязательно для заполнения!</p>';
	if(empty($answer)) $error .= '<p>Поле ответа обязательно для заполнения!</p>';

	if(empty($error)){
		// заполнены оба поля
		$handle = fopen('../base.txt', 'a');
		$string = $question. '//' .$answer. "\r\n";
		if(fwrite($handle, $string)){
			$_SESSION['res'] = '<p>Добавлено!</p>';
			fclose($handle);
			header("Location: new.php");
			exit;
		}else{
			$_SESSION['res'] = '<p>Ошибка записи! Попробуйте еще раз.</p>';
			fclose($handle);
			header("Location: new.php");
			exit;
		}
	}else{
		$_SESSION['res'] = $error;
		$_SESSION['question'] = $question;
		$_SESSION['answer'] = $answer;
		header("Location: new.php");
		exit;
	}
}else header("Location: new.php");
?>

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

Отлично!

Теперь можно добавлять вопрос-ответ через форму административной части. Остался последний незначительный момент. Если Вы работаете на локальной машине, то все должно работать без проблем. Если же Вы перенесете файлы на сервер хостера, то получите ошибку при попытке добавления новой пары вопрос-ответ. Эта ошибка связана с отсутствием прав на запись в файл. Для того чтобы скрипт работал без проблем в сети — просто установите нужные для записи в файл права.

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

Кликаем правой кнопкой мыши по файлу и выбираем пункт «Права доступа к файлу…».

права доступа

Выставляем права, отмечая необходимые чекбоксы или введя числовое значение нужных прав доступа.

атрибуты файла

Заключение

На этом данный урок закончен.

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

В следующем (заключительном) уроке мы напишем второй пункт — удаление пары вопрос-ответ.

Ваши вопросы и отзывы жду в комментариях

С уважением Андрей Кудлай

Автор: Кудлай Андрей

Редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.

Фреймворк YII2: теория и первая практика

Овладейте азами фреймворка Yii2 за 5 дней!

Получить

Метки: , ,

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

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

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

  1. Игорь

    Интересно было прочитать урок. Мне понравилось!

  2. Владимир

    Замечательный урок. Все ясно и понятно пока, попробую сделать на своем сайте.

  3. Владимир

    С учетом 1-ой и 2-ой частей, выяснил для себя, что FAQ еще можно довести до соответствующего уровня по сегодняшним меркам. Спасибо.

  4. Александр

    Попробую сделать также!посмотри что получится

  5. Любовь

    Получается, но всё как хотелось, и интересно становится, если даже где-то и сбой получается.

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

Ваш 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