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

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

От автора: Данный урок является логическим продолжением урока "Как сделать FAQ на сайте с использованием PHP-MySQL-jQuery". В комментариях к указанному уроку поступила просьба показать, как можно реализовать аналогичную "штуку", но без использования БД, а с использованием в качестве хранилища данных текстовые файлы. Также в комментариях содержалась просьба показать, как создать административную часть, при помощи которой можно было бы управлять указанным хранилищем данных.

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

Время ролика: 47:22

Сложность: средняя

План урока:

    1. Подготовительный этап. Формирование задач (10:24)

    2. Читаем файл (13:32)

    3. Формирование массива вывода данных (11:14)

    4. Выводим данные (11:21)

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

 

1. Подготовительный этап. Формирование задач

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

Теперь относительно минусов… Здесь они лучше просматриваются на фоне плюсов при использовании БД. Базы данных позволяют хранить информацию с очень сложной структурой, с разграничением по типам данных. При этом использование БД позволяет существенно упростить поиск, извлечение и редактирование требуемой информации. Чего не скажешь о текстовых файлах — там разработать сложную структуру хранения данных гораздо проблематичнее, а для выполнения операций с требуемой информацией нужно приложить гораздо больше усилий.

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

Это, на мой взгляд, основные плюсы/минусы использования текстовых файлов. Если Вы больше заинтересуетесь этим теоретическим вопросом, то в сети Вы можете найти целые «баталии» между сторонниками использования файлов и БД.

Ну что ж, продолжим. Для начала возьмем все файлы из предыдущего урока («Как сделать FAQ на сайте с использованием PHP-MySQL-jQuery»), создадим на сервере каталог под наш проект — я назову его «faq_txt» — и скопируем в него файлы предыдущего урока. Теперь откроем в редакторе файл faq.php и внесем в него необходимые правки. Нам не понадобится БД — поэтому код соединения с ней удаляем. Также удаляем код, которым осуществляется вывод информации из БД.

Теперь создадим текстовый файл, который и будет хранилищем информации, т.е. в нем будут храниться пары вопрос-ответ. Файл назовем base.txt и в него поместим 3 пары вопрос-ответ в 3 строки:

Шаг 1//Прежде всего необходимо подключиться к серверу БД. Конечно же, у Вас уже должна быть создана БД. Также необходим шаблон, на котором мы и будем проделывать все наши эксперименты.
Шаг 2//Здесь Вы должны вытащить из БД все вопросы и необходимые к ним ответы. Также желательно подать их в приемлемом виде, чтобы было понятно, что это именно вопрос-ответ.
Шаг 3//На этом этапе необходимо подключить библиотеку jQuery и написать скрипт, которым мы возьмем в набор jQuery все элементы с классом 'question'. Затем при помощи события 'toggle()' мы установим своеобразный переключатель из 2-х функций: по первому клику - показывается ответ на соответствующий вопрос, по второму - ответ скрывается.

Заметьте, что 1 пара должна занимать ровно 1 строку — эта особенность важна и далее Вы узнаете почему. Кроме того, вопрос и ответ я разделил двумя слешами («//»). На самом деле разделитель может быть и другим, главное, чтобы он не встречался больше в строке, чтобы создаваемая нами программа понимала, что до разделителя идет вопрос, а после него — ответ… ну а с новой строки вновь идет вопрос-ответ и т.д.

Теперь немного о работе с файлами в PHP. Работу с файлами здесь можно разбить на 3 этапа:

открытие файла;

считывание информации или редактирование файла;

закрытие открытого файла.

Перейдем к первому этапу — открытие файла. Сделать это можно при помощи функции fopen(). Ее синтаксис:

fopen("имя файла", "режим");

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

"r" — чтение файла;

"w" — запись в файл, при этом, если в файле уже были какие-то данные, — они будут затерты, т.е. файл будет перезаписан;

"a" — файл открывается для дозаписи, т.е. указатель (курсор) устанавливается в конец файла и новая информация в него дописывается.

Теперь перейдем к написанию кода.

2. Читаем файл

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

Итак, откроем файл в режиме чтения:

$handle = fopen('base.txt', 'r');

Результат выполнения функции мы поместили в переменную $handle. Теперь эта переменная является дескриптором открытого файла или, говоря простым языком, — она указывает на открытый файл и именно с ней происходит дальнейшая работа.

Информацию из открытого файла мы будем считывать построчно — именно для этого мы и помещали пару вопрос-ответ в отдельную строку. Считать строку из файла нам поможет функция fgets(). Ее синтаксис:

fgets(дескриптор файла);

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

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

Теперь еще раз вернемся к условию. Как можно узнать достигнут ли конец файла? Здесь нам поможет функция feof(), которая проверяет достигнут ли конец файла. Ее синтаксис:

feof(дескриптор файла);

Данная функция возвращает значение TRUE (ИСТИНА) если достигнут конец файла или FALSE (ЛОЖЬ) в любом другом случае. Таким образом, в условии мы будем проверять возвращает ли функция ЛОЖЬ, если возвращает — значит конец файла не достигнут и будем считывать строку, если вернет ИСТИНУ, т.е. условие не выполнится — прекратим считвать файл. Код будет таким:

<?php
$handle = fopen('base.txt', 'r');

while(!feof($handle)){
	$read[] = fgets($handle);
}
?>

Обратите внимание на восклицательный знак перед вызовом функции feof(), об его использовании в PHP я уже говорил — он обозначает, если перевести на понятный язык, частицу «не». Поскольку в условии мы проверяем возвращает ли функция ЛОЖЬ, мы и указали частичку не, т.е., если прочитать условие — мы получим следующее: «пока(не ИСТИНА){читаем очередную строку}». В данном случае «не ИСТИНА» == ЛОЖЬ.

3. Формирование массива вывода данных

Отлично!

Мы считали файл построчно в массив $read. Теперь каждый элемент массива содержит 1 строку считанного файла. Но нас это не совсем устраивает, поскольку нам нужны вопрос и ответ в разделенном виде. Вспоминаем, именно для этих целей у нас в каждой строке и предусмотрен разделитель. Зная какой именно разделитель использован, а мы знаем это, можно разбить строку в нашем случае на 2 подстроки: в одной будет вопрос, во второй — ответ. Выполнить сформированную задачу нам поможет функция explode(), которая, собственно, и разбивает строку на подстроки.

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

explode("сепаратор", разбиваемая строка);

В качестве сепаратора указывается разделитель — в нашем случае использовано 2 слеша («//»). Как говорилось, можно использовать и любой другой разделитель — главное, чтобы он не встречался в части строки, которую мы хотим получить в качестве подстроки.

Поскольку на необходимо разбить на подстроки все элементы массива $read — необходимо пройтись по всем элементам массива в цикле. Перебирать элементы цикла будем при помощи цикла foreach(), который и существует специально для обхода элементов массива. Синтаксис оператора foreach():

foreach(имя массива as переменная){блок действий}

Здесь мы берем каждый конкретный элемент массива и присваиваем на каждой итерации цикла его значение как раз переменной, указанной после ключевого слова as. Ну а в блоке действий мы уже выполним нужный набор действий с указанной переменной.

Теперь код:

<?php
$handle = fopen('base.txt', 'r');

while(!feof($handle)){
	$read[] = fgets($handle);
}

foreach($read as $item){
	$data[] = explode('//', $item);
}

?>

В результате выполнения кода мы получили массив $data, который содержит еще 3 массива (по числу строк), в каждом из которых содержится по 2 элемента (вопрос-ответ). Теперь у нас есть многомерный массив. Осталось вывести его значения. Сделать это можно внутри того же цикла.

4. Выводим данные

Для того, чтобы понять что и как нам необходимо вывести, достаточно распечатать содержимое массива:

<?php
$handle = fopen('base.txt', 'r');

while(!feof($handle)){
	$read[] = fgets($handle);
}

foreach($read as $item){
	$data[] = explode('//', $item);
}
echo '<pre>';
print_r($data);
echo '</pre>';
?>

Взглянув на структуру полученного массива, не сложно будет увидеть, что для того, чтобы, к примеру, вывести второй вопрос, мы должны обратиться к индексу 1 массива $data и указать индекс 0 вложенного массива, т.е. так:

echo $data[1][0];

Чтобы вытащить ответ на этот вопрос — обращаемся уже ко второму элементу вложенного массива, т.е. к элементу с ключом 1:

echo $data[1][1];

Теперь, если мы для себя проследим структуру выводимых ключей всех пар вопрос-ответ, то получим следующее:

00
01

10
11

20
21

Видим, что вторые цифры в каждой паре чередуются (0 и 1), а первые цифры каждой пары увеличиваются на единицу — от нуля до трех. Соответственно, для вывода в каждой паре первой цифры мы организуем счетчик вне цикла (это будет переменная $i), а в цикле будем увеличивать его на единицу и присваивать его значение первому ключу массива. Ну а вторые цифры мы так и будем выводить — чередуя 0 и 1:

<?php
$handle = fopen('base.txt', 'r');

while(!feof($handle)){
	$read[] = fgets($handle);
}

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

Также мы закрыли открытый ранее файл функцией fclose() — здесь ничего сложного нет.

Вот и все…

Осталось перенести итоговый код в то место файла, где мы хотим видеть вывод пар вопрос-ответ — это блок page на странице faq.php. Все работает точно также, как и в предыдущем уроке с использованием БД. Можем в файле на новой строке через разделитель создать еще одну пару вопрос-ответ — она также после сохранения файла и обновления страницы будет выведена на экран.

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

До новых встреч!

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

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

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

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

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

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

Получить

Метки: , ,

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

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

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

  1. Людмила-Латофат

    Спасибо Вам, ОГРОМНОЕ! Мне нравятся, Ваши уроки.

  2. Шамшур Иван

    Не понял зачем только два раза проходит по одному и тому же массиву?
    Можно ведь проще:

    $handle = fopen(‘base.txt’, ‘r’);

    while(!feof($handle)){
    $row = fgets($handle);

    list($question,$answer) = explode(‘//’, $item);

    echo » .$question. »;
    echo » .$answer. »;
    }

    fclose($handle);

    • Шамшур Иван

      опечатался:

      $row = fgets($handle);

      list($question,$answer) = explode(‘//’,$row);

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

      Ого, сразу 3 комментария :) Отвечу в одном.
      Если присмотреться к коду, то по массиву мы проходимся только 1 раз… да-да, второго раза там нет :)
      Сначала формируется сам массив в цикле while(), ну а затем уже идет работа с массивом в цикле foreach().
      По второй части вопроса… Можно и проще, но урок, прежде всего, носит обучающую направленность. Поэтому весь процесс разбит на этапы для простоты усвоения — ведь нас смотрят не только гуру, но и новички ;) Именно поэтому на первом этапе мы учимся формировать массив, а на втором — работать с ним… хотя можно было все действия сделать в момент построчного чтения файла в переменную.
      Вообще, за что я люблю PHP — так это за то, что одну и ту же задачу можно реализовать несколькими способами, иногда даже десятком вариантов. Поэтому ждем 2-ю и 3-ю части урока (они уже записаны и ждут публикации) — в 3-ей части работа с файлом идет несколько иначе, способом, который гораздо короче и «проще», чем вариант из первой части и Ваш вариант (но это отнюдь не говорит об ущербности изначального варианта).
      Кстати, если бы Вы поделились с новичками своими знаниями в записанном уроке — было бы супер :)

  3. Шамшур Иван

    Обрезало html-код! Админ, установи BB-code в комментарии!

  4. Игорь

    Действительно ценная информация.Я пересмотрел очень много похожих ресурсов, и пока не встретил таких лаконичных и емких уроков как на этом сайте. Ничего лишнего, все конкретно. Мне нравиться. Спасибо!
    Игорь.

  5. Андрей Кудлай

    Пожалуйста;)
    А Вам спасибо за вдохновляющий комментарий :)

  6. Sitemen

    А почему бы не использовать БД SQLite?
    Минусы текстовых файлов отпадают, а все плюсы остаются.
    И задачи можно решать гораздо более сложные, чем просто с текстовыми файлами.

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

      Если вопрос адресован автору уроку, то отвечу цитатой из вступления к уроку: «Данный урок является логическим продолжением урока «Как сделать FAQ на сайте с использованием PHP-MySQL-jQuery». В комментариях к указанному уроку поступила просьба показать, как можно реализовать аналогичную «штуку», но без использования БД, а с использованием в качестве хранилища данных текстовые файлы.»
      Эта же задача уже была решена с использованием СУБД MySQL.
      Кстати, было бы неплохо, если бы Вы записали урок с использованием SQLite.

      • Sitemen

        Ну, на урок знаний не хватит. Просто сейчас как раз разбираюсь с этой темой, вижу преимущества использования текстовых БД, поэтому и предложил использовать не СУБД MySQL, а именно текстовую БД. Для сайтов, работающих без СУБД MySQL текстовая БД открывает много возможностей.
        И урок по этой теме с удовольствием посмотрел бы (или почитал).

  7. Андрей

    Конгениально! Для моего городского справочника то что надо!

  8. Андрей

    Здравствуйте, Андрей!
    Объясните, пожалуйста, как можно сделать так, чтобы в выведенном списке каждый вопрос «Шаг N» был ссылкой на файл, где выводился бы соответствующий ответ? Мне это нужно, поскольку я хочу использовать этот замечательный способ для справочника. Заранее благодарю.

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

      Здравствуйте, Андрей! :)
      Все очень просто… К примеру, на сервере в одном каталоге со скриптом имеется файл 1.txt — мы просто прописываем на него ссылку (a href=1.txt и т.д., к сожалению, полностью теги не могу писать, поскольку парсер их вырежет) в месте, где выводится вопрос.
      Например, так:
      echo » .$data[$i][0]. »;

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

      Как я говорил, все теги вырезались, но, думаю, мысль понятна.

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

      Андрей, сори, но я немного дезинформировал Вас. Дело в том, что сам вопрос сделать ссылкой не получится… точнее можно, но ссылка не будет работать как ей положено, поскольку по клику на ней будет срабатывать метод toggle().
      Задачу можно решить, немного изменив код jQuery и структуру вывода данных из файла. Также в файле БД нужно будет хранить ссылку на файл, который будет загружаться по клику. В общем, ниже ссылка, по которой можно скачать решение — http://narod.ru/disk/22858100001/faq_txt.rar.html
      Если возникнут проблемы, то можно записать урок :)

      • Андрей

        Большое спасибо, Андрей!
        Я сейчас больше жду урока по использованию в аналогичной ситуации SQLite! Но больше всего на данный момент меня беспокоит то, что когда я решил все это наконец реализовать у меня почему-то не стал работать файл faq.php и прочие php-файлы! Я задал подобный вопрос ниже, очень жду Вашей помощи по этой проблеме!

  9. Андрей

    Скажите, почему файл faq.php у меня не работает, а предлагается его сохранить, как загружаемый?

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

      Скорее всего потому, что сервер не поддерживает PHP. Соответственно, он не может обработать файл с расширением PHP как положено и предлагает его сохранить.

      • Андрей

        Все так, загрузил на хостинг с пхп и все нормально. Но почему же на денвере не работает, он ведь вроде держит пхп?

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

          Денвер отлично работает с PHP. В настройках сервера ничего не изменяли? В конфигурационном файле сервера httpd.conf (адрес — Буква локального диска:\usr\local\apache\conf) должна быть строка с примерно таким содержанием:
          AddType application/x-httpd-php .php .php5 .phtml
          Если ничего не поможет — проще переустановить Денвер, предварительно ПОЛНОСТЬЮ его удалив.

  10. Александр

    Спасибо Вам, ОГРОМНОЕ! Мне нравятся, Ваши уроки

  11. Koko

    Жду с нетерпением следующий урок.
    Привет из Болгарий, Андрей Кудлай!

    П.П.
    Проще прощего установить Debian, а за ним команду:
    sudo apt-get install lamp-server^
    и будет вам полное счастье.

    PHP создан израильтянами в системе UNIX и будет вам профи.

  12. Сергей Кудренко

    Спасибо, интересно. Стиль изложения очень хороший. Просто и доступно с уважением к обучаемому.
    Было бы интересно, что-бы вы подняли вопрос Jquery и Ajax. Попробовали реализовать тему поиска в стиле Google или Yandex. Сам я поробовал создать уроки по быстому поиску в интернет магазине у себя на сайте. Но они еще сыроваты.
    Еще одна тема которую я попытался реализовать это интернет магазин, именно корзина потребителя (выложены уроки на сайте). Было бы интересно, что бы вы подняли эту тему.

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

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