Название статьи конечно звучит громко, но на самом деле я расскажу лишь о базовой концепции создания файлового менеджера, а точнее редактора текстовых файлов (ну и конечно приведу несколько примеров и то что в итоге мы можем получить).
Поставим задачу. Мы хотим видеть страницу на которой будет располагаться древовидное представление нужной директории. Под данным деревом будет располагаться текстовый редактор. Должна быть возможность сохранить изменения в файле.
Так как велосипеды придумывать не нужно, то писать качественный текстовый редактор смысла нет (да и долго это будет). Поэтому воспользуемся готовым решением в виде PHP класса CKEditor.
Создадим php файл, подключим CKEditor и зададим шаблон страницы:
<?php include_once( 'ckeditor/ckeditor.php' ) ; $editor_name = "editor1"; $dog_path = "docs/"; if (!$_POST) { echo '<form action="" method="post">'; echo '<div style="height:250px;overflow:scroll;" id="fm"></div>'; echo '<div id="ed">; $CKEditor = new CKEditor(); $CKEditor->editor($editor_name, ""); echo "<input type='hidden' name='act' value='edit' />"; echo '<input type="submit" value="Сохранить"/>'; echo '<div>'; echo '<form>'; } else if ($_POST && isset($_POST["act"])) { /* Так как у нас будет действие редактирования, то без запроса не обойтись, Будем слать его на эту же страницу */ } ?>
Думаю данный шаблон в описании не нуждается, все достаточно понятно. Теперь нам нужно заполнить верхний div файлами и папками из каталога docs. Сделаем мы это с помощью функции, рекурсивной функции, описание которой ниже:
function dirTree($path, $level = 0) { if (!is_dir($path)) { echo "Path is not dir!"; return; } if (substr($path, -1) != "/") $path .= "/"; $d = opendir($path); while (false !== ($filename = readdir($d))) { if ($filename == "." || $filename == "..") continue; if (!is_dir($path.$filename)) { for ($i = 0; $i < $level; ++$i) echo "-"; echo "<span onclick=\"LoadFile('".$path.$filename."');\"><input type='radio' value='".$path.$filename."' name='radio_file_sel' style='cursor:pointer;' />".$filename."</span>"; echo "<br/>"; } else { echo "<b style='cursor:pointer;' onclick=\"var f = document.getElementById('".$level."_folder_".$filename."'); if (f.style.display=='block') f.style.display='none'; else f.style.display='block';\">".$filename."</b><br/>"; echo "<div id='".$level."_folder_".$filename."' style='display:none;'>"; dirTree($path.$filename, $level + 1); echo "</div>"; } } closedir($d); }
Данный код демонстрирует как можно вывести содержимое всех файлов и папок по указанному пути. Здесь стоит отметить несколько моментов:
1) Проверка if ($filename == «.» || $filename == «..»). Необходима так как PHP так же отображает путь текущего каталога (.) и путь каталога родителя (..);
2) for ($i = 0; $i < $level; ++$i) echo «-«;. Создает отступ для более красивого отображения каталогов и файлов.
3) После отображения папки, создается скрытый див, в котором отображается его содержимое путем рекурсивного вызова функции. За отображение\скрытие данного содержимого отвечает javascript.
4) В качестве значения каждого radio указывается полный путь к файлу. Это необходимо для сохранения отредактированного файла.
5) Скрипт LoadFile, который срабатывает при нажатии на файл, отвечает за загрузку содержимого файла в редактор. Реализовывать данный скрипт можно разными способами, поэтому рассматривать мы его не будем. Однако отметим, что за загрузку данных в редактор отвечает следующий код:
CKEDITOR.instances.[имя редатора].setData([текст]);
В нашем случае, при реализации скрипта inline (т.е. в файле php) код можно написать так:
var mytext = "текст из документа"; CKEDITOR.instances.<?php echo $editor_name; ?>.setData(mytext);
Объект CKEDITOR создается автоматически при создании формы редактора.
Теперь осталось только дописать сохранение изменений в файле. При нажатии кнопки сохранить, запрос уйдет на эту же страницу. Текст из редактора посылается в переменной с именем нашего редактора. Имя файла который нужно сохранить в переменной radio_file_sel.
Имеем:
if (file_exists($_POST["radio_file_sel"])) { $f = fopen($_POST["radio_file_sel"], "w+"); fwrite($f, $_POST[$editor_name]); fclose($f); echo "Файл '".$_POST["radio_file_sel"]."' успешно сохранен!
"; }
В итоге получаем картину:
<?php include_once( 'ckeditor/ckeditor.php' ) ; function dirTree($path, $level = 0) { if (!is_dir($path)) { echo "Path is not dir!"; return; } if (substr($path, -1) != "/") $path .= "/"; $d = opendir($path); while (false !== ($filename = readdir($d))) { if ($filename == "." || $filename == "..") continue; if (!is_dir($path.$filename)) { for ($i = 0; $i < $level; ++$i) echo "-"; echo "<span onclick=\"LoadFile('".$path.$filename."');\"><input type='radio' value='".$path.$filename."' name='radio_file_sel' style='cursor:pointer;' />".$filename."</span>"; echo "<br/>"; } else { echo "<b style='cursor:pointer;' onclick=\"var f = document.getElementById('".$level."_folder_".$filename."'); if (f.style.display=='block') f.style.display='none'; else f.style.display='block';\">".$filename."</b><br/>"; echo "<div id='".$level."_folder_".$filename."' style='display:none;'>"; dirTree($path.$filename, $level + 1); echo "</div>"; } } closedir($d); } $editor_name = "editor1"; $dog_path = "docs/"; if (!$_POST) { ?> <script type='text/javascript> function LoadFile(filename) { var f = ""; //получаем в переменную f текст из файла filename, например ajax-ом CKEDITOR.instances.<?php echo $editor_name; ?>.setData(f); } </script> <?php echo '<form action="" method="post">'; echo '<div style="height:250px;overflow:scroll;" id="fm">'; dirTree($dog_path); echo '</div>'; echo '<div id="ed">; $CKEditor = new CKEditor(); $CKEditor->editor($editor_name, ""); echo "<input type='hidden' name='act' value='edit' />"; echo '<input type="submit" value="Сохранить"/>'; echo '<div>'; echo '<form>'; } else if ($_POST && isset($_POST["act"])) { if ($_POST["act"] == "edit") { if (file_exists($_POST["radio_file_sel"])) { $f = fopen($_POST["radio_file_sel"], "w+"); fwrite($f, $_POST[$editor_name]); fclose($f); echo "Файл '".$_POST["radio_file_sel"]."' успешно сохранен!
"; } } } ?>
Вот по сути и все. Теперь по аналогии можно добавить кнопки удаления файлов, создание нового файла. Для удобства можно заменить древовидное представление файлов более подходящим для Вашей задачи.