Уроки PHP - урок 2 - Работа с файлами: открытие, запись, чтение.
В прошлом уроке мы сделали каркас для нашей гостевой книги, блога или чата. Теперь остается лишь добавлять функционал. В этом уроке мы будем записывать наши записи в файлы и выводить записи из файлов.
В PHP есть много функций для работы с файлами, мы рассмотрим некоторые из них, скорее всего ваш сайт будет записывать данные в базу данных (в этом я уверен), а не в файлы, поэтому рассмотрим только некоторые из них, чтобы вы поняли суть. А работу с базой данных мы рассмотрим позже.
Итак, если у вас нет файлов, которые мы делали на прошлом уроке, вернитесь на урок назад и скачайте эти файлы.
Давайте перейдем на форму добавления записи:
/index.php?admin=1
С этой формы мы будем добавлять свои записи. Чтобы обрабатывать эти записи, нам нужно проверять на странице index.php (на эту страницу отправляют данные с формы) есть ли значения в переменной $_POST. А проверяется это очень просто:
if($_POST){ }
Не правда ли просто? Теперь внутри фигурных скобок нужно поместить обработку массива $_POST. Мы не будем писать код обработки прямо в фигурных скобках, а вынесем его в наш класс, а саму обработку будем вызывать через метод объекта. В файле index.php вызываем метод:
if($_POST){ $obj->write($_POST); }
А в файле simpleCMS.php у нас будет реализация метода write():
public function write($p) { // метод записи сообщения }
Зачем мы это делаем? Затем чтобы сократить код в файле index.php. Файл index.php нужен только для управления, а обработка массивов и вывод данных должен проводиться из другого файла, например файла нашего класса simpleCMS. Это разгранечение позволяет повысить эффективность кода. Если кто-то другой посмотрит на наш код, то он сразу разберется где у нас что лежит. Да и вам самим будет проще разбираться в коде, когда все лежит по полочкам.
Начнем писать обработку с простого, распечатаем наш массив $_POST передаваемый с формы. Для этого нужно вставить этот код:
public function write($p) { // метод записи сообщения print_r($p); }
Как видите мы обращаемся к локальной переменной $p, хотя передается в параметры метода write() суперглобальная переменная. Мы не обращаемся к суперглобальной переменной напрямую, потому что в других случаях мы можем захотеть сделать запись в блоге не через форму, а с помощью получения данных из XML файла. Использование локальной переменной позволяет нам унифицировать использование этого метода, сделать его общим для многих случаев.
Итак, заполняем форму и отправляем ее. У меня получились такие данные:
Array ( [title] => Иван [bodytext] => Привет, Мир! )
Если вы заполнили по другому, то и массив у вас будет другой. Мы вывели массив чтобы посмотреть какие ключи мы можем использовать. У нас это $p['title'] и $p['bodytext']. Теперь мы знаем какие у нас будут данные, осталось их записывать в файл. Итак, начинаем с записи в файл.
PHP запись в файл
Прежде, чем записать что-то в файл необходимо его "открыть на запись". Открыть на запись значит связать файл с переменной PHP. Вся работа над файлом в PHP сводится с действиями над переменной типа resource. Сейчас я покажу что это значит:
public function write($p) { // метод записи сообщения $message = fopen("messages/file.txt","w"); print_r($message); }
Для этого я создал файл file.txt в папке messages. И теперь если мы заполним форму и отправим ее, то получим:
Resource id #4
Resource - это тип переменной $message, а 4 это порядковый номер, id нашей переменной среди других переменных resource. И теперь если мы производим действия с перменной $message, то это автоматически отобразится и в файле. Записывать в файл мы будем построчно, чтобы потом также построчно читать из файла:
public function write($p) { // метод записи сообщения $message = fopen("messages/file.txt","w"); fputs ($message, $p['title']. "\r\n"); fputs ($message, $p['bodytext']); }
Символы \r\n в двойных ковычках (в одинарных может не работать), означают переход на новую строку, в результате в файле file.txt будет такой текст:
Иван
Привет, Мир!
После того как мы произвели все действия с файлом, надо удалить переменную файла, чтобы она не занимала место в оперативной памяти.
public function write($p) { // метод записи сообщения $message = fopen("messages/file.txt","w"); // открываем файл fputs ($message, $p['title']. "\r\n"); fputs ($message, $p['bodytext']); fclose ($message); //закрываем файл }
Наверно вы заметили что каждый раз когда мы заново пишем файл, то файл перезаписывается. Это все зависит от параметра в функции fopen. Мы можем также и дозаписывать файл или просто открывать его для чтения. Например так:
$message = fopen("messages/file.txt","r"); // открываем файл только для чтения
- r – открытие файла только для чтения.
- r+ - открытие файла одновременно на чтение и запись.
- w – создание нового пустого файла. Если на момент вызова уже существует такой файл, то он уничтожается.
- w+ - аналогичен r+, только если на момент вызова такой файл существует, его содержимое удаляется.
- a – открывает существующий файл в режиме записи, при этом указатель сдвигается на последний байт файла (на конец файла).
- a+ - открывает файл в режиме чтения и записи при этом указатель сдвигается на последний байт файла (на конец файла). Содержимое файла не удаляется.
Как написано выше, если мы открываем файл с помощью параметра w, то создается новый файл, имя которого берется из первого параметра. Давайте будем создавать имя файла соответвующее времени, получаемому с помощью функции time().
Функция time() возвращает количество секунд начиная с 1 января 1970 года.
У вас должно получится следующее:
public function write($p) { // метод записи сообщения $message = fopen('messages/'.time(),"w"); // открываем файл fputs ($message, $p['title']. "\r\n"); fputs ($message, $p['bodytext']. "\r\n"); fputs ($message, time()); fclose ($message); //закрываем файл }
Таким образом каждую секунду функцией time() будет возращаться все большее количество секунд и имена файлов будут иметь все больше число. Можете попробовать добавить новые записи и новые файлы появятся в папке messages. Теперь осталось читать файлы и выводить наши записи.
PHP чтение файла
Для того чтобы читать из файла, нужно открыть файл на чтение, для этого в функции fopen() мы будем использовать параметр r. Все необходимые нам файлы лежат в папке messages, для того чтобы прочитать все файлы мы будем использовать цикл while (пока файлы не закончатся).
Просматривать файлы в папке мы будем с помощью функции opendir(), которая открывает папку на чтение:
if (is_dir('messages')) { // проверяем наличие папки if ($dh = opendir('messages')) { // открываем папку на чтение while (($file = readdir($dh)) !== false) { // пока файлы существуют читаем их // выполняем нужные операции } closedir($dh); //закрываем директорию } }
Имена файлов мы получаем с помощью функции readdir(), то есть имена будут храниться в переменной $file. После окончания работы цикла закрываем папку, чтобы освободить место в оперативной памяти.
Теперь когда мы можем прочитать файлы, давайте будет дорабатывать метод display_public():
public function display_public() { // метод вывода сообщений $content = ''; if (is_dir('messages')) { // проверяем наличие папки if ($dh = opendir('messages')) { // открываем папку на чтение while (($file = readdir($dh)) !== false) { // пока файлы существуют читаем их if(substr($file, -4) == '.txt'){ // берем только .txt файлы $filename = 'messages/' . $file; // полное имя файла $message = fopen($filename, 'r'); // открываем файл $title = fgets($message); // читаем первую строку $body = fgets($message); // читаем вторую строку $time = fgets($message); // читаем третью строку print '<div class="post">'; // div оборачивающий запись print '<span class="time">' . date('d-m-Y', $time) . '</span><h2>' . $title . '</h2>'; // выводим время и заголовок print '<p>' . $body . '</p>'; // выводим текст сообщения print '</div>'; // конец оборачивающего div'a fclose($message); // закрываем файл } } closedir($dh); //закрываем директорию } } $content .= '<p><a href="/index.php?admin=1">Добавить сообщение</a></p>'; return $content; }
Я прокомментировал каждую строчку, если что-то не понятно, то пишите в комментариях, разъясню.
Не думаю что вам понадобится на практике построчное чтение из файла, но для понимания принципов работы php функций, работы с файлами и папками подобные уроки очень полезны.
Ниже исходных код промежуточного сайта.