Настройка:
У меня есть стандартный файл .php (index.php), который содержит два включает: один для заголовка (header.php) и один для нижнего колонтитула (footer.php). Файл index.php выглядит так:
index.php
<?php include header.php; ?> <h2>Hello</h2> <p class="editable">Lorem ipsum dolar doo dah day</p> <?php include footer.php; ?>
header.php:
<html> <head> <title>This is my page</title> </head> <body> <h1 class="editable">My Website rocks</h1>
и нижний колонтитул .php:
<p>The end of my page</p> </body>
Я пишу PHP-скрипт, который позволяет вам редактировать любой элемент «.editable» на странице. Моя проблема в том, что эти редактируемые области могут появляться в любых включенных файлах, а также в основной части index.php.
Мой php-код захватывает файл index.php файлом_get_contents (); который работает хорошо. Я также могу редактировать и сохранять любые «разрешенные» регионы в index.php.
Мой вопрос:
Я не смог найти способ «находить» включения и разборки через те, для «соответствующих» регионов. Я ищу предложения о том, как я буду работать через все входящие в index.php – проверять их на редактируемые регионы. Нужно ли использовать регулярные выражения для поиска «include * .php»? Я не уверен, куда даже начать …
Для тех из вас, кто может пожелать увидеть мой PHP-код. Я использую класс PHP: [link text] [1], который позволяет мне писать код наподобие:
// load the class and file $html = new simple_html_dom(); $html->load_file("index.php"); // find the first editable area and change its content to "edited" $html->find('*[class*=editable]', 0)->innertext = "Edited"; // save the file $html->save(index.php);
[1]: http://simplehtmldom.sourceforge.net/manual_api.htm простой парсер php dom
ОБНОВИТЬ
Я играл с регулярными выражениями, чтобы попытаться совместить их. Я довольно мусор в регулярном выражении, но я думаю, что приближаюсь. Вот что я имею до сих пор:
$findinclude = '/(?:include|include_once|require|require_once)\s*(?:[az]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?]|[^\?\>])*\?>)/i';
Это соответствует достаточно хорошо, хотя кажется, что возвращает нечетное) и «при использовании preg_match. Я пытаюсь добавить немного безопасности в регулярное выражение, чтобы убедиться, что оно совпадает только между php-тегами – эта часть: (? = (?: [^ \ <\?] | [^ \?>]) * \?>) – но он возвращает только первое включение на странице. Любые советы о том, как улучшить это регулярное выражение? (Я был у него около 6 часов)
Какую систему вы создаете?
Если это будет использоваться общественностью, у вас возникнут серьезные проблемы с безопасностью. Люди могут включать свой собственный PHP-код или JavaScript в поставляемом контенте.
Это не стандартный способ создания динамического контента. Для большинства целей вам нужно создать один шаблон, а затем разрешить пользователям сохранять свои изменения в базе данных. Затем вы должны заполнить информацию в шаблоне из базы данных для отображения.
Если вы разрешаете им включать HTML, используйте что-то вроде очистителя html для его очистки, вставьте данные в свою базу данных с помощью подготовленного оператора с использованием PDO . Я уверен, что люди здесь будут рады ответить на любые вопросы, которые могут возникнуть по поводу использования базы данных.
Я вас неправильно понял, не обращайте внимания на все после hr
.
Чтобы сделать то, что вы хотите, я думаю, самый простой способ – представить страницу в браузере, построить какой-то javascript, который находит и редактирует редактируемые области и передает это в файл PHP через AJAX.
Затем PHP-файл получит контент и место, где он должен изменить содержимое, но я до сих пор не очень хорошо понимаю, как это делает статическая CMS, но есть некоторые проекты с открытым исходным кодом, здесь и здесь . Я предлагаю вам изучить их код, чтобы узнать, как они это делают.
Это действительно просто, вместо того, чтобы включать файл следующим образом:
file_get_contents('/path/to/file.php');
Вы должны сделать это вот так:
file_get_contents('http://your-host.com/path/to/file.php');
Кроме того, взгляните на QueryPath , кажется, намного лучше, чем SimpleHTMLDom.
Основываясь на регулярном выражении, которое вы предоставили, я немного его оптимизировал и исправил некоторые важные ошибки:
~<[?].*?(?:include|require(?:_once)?)\s*?(?:[(]?['"])(.+?)(?:['"][)]?)\s*?;.*?(?:[?]>)?~is
И в preg_match_all()
:
preg_match_all('~<[?].*?(?:include|require(?:_once)?)\s*?(?:[(]?[\'"])(.+?)(?:[\'"][)]?)\s*?;.*?(?:[?]>)?~is', $html, $includes);
Он должен соответствовать именам файлов с цифрами, цифрами, тире, символами подчеркивания, косой чертой, пробелами, точками и т. Д.
Кроме того, имя файла сохраняется в ссылке # 1, а конечный PHP-тег является необязательным.
Стоит отметить, что функция token_get_all () намного надежнее, чем регулярные выражения.
Если пользователи могут отправлять контент в них, а затем они попадают в файл PHP, то у вас есть серьезные проблемы.
У вас должны быть простые шаблоны, в которых у них мало или вообще нет PHP, которые анализируются – тогда и только тогда вы должны вставлять содержимое в DOM после правильной очистки.
Способ решения проблемы «найти вопрос включает» – вам не нужно, PHP делает это для вас – возможно, используйте ob_start и др. а затем включить файл шаблона. Затем возьмите содержимое буфера (которое будет HTML), а затем проанализируйте уже собранный шаблон с помощью анализатора DOM.
Пожалуйста, пожалуйста, ПОЖАЛУЙСТА, убедитесь, что вы санируете все, что вы вводите в DOM.
В противном случае тирания и уничтожение наверняка будут опускаться на ваш веб-сайт (и вы, в зависимости от того, что еще находится на вашем сервере).
Вам нужно просто сохранить введенный пользователем текст где-нибудь и загрузить его и вывести его с помощью вашего шаблона PHP.
Я хотел бы изучить возможность использования базы данных. В этом нет ничего тяжелого или медленного, и на самом деле это то, за что они нужны. Если вы не хотите использовать базу данных, вы можете использовать файлы вместо этого. Я бы предложил сохранить данные в файле в формате JSON, чтобы создать некоторую структуру.
Вот очень простая система для использования файлов для хранения и получения JSON-кодированных данных.
Создайте массив того, что вы хотите сохранить после редактирования
$user_data=array('title'=>$user_supplied_info,'content'=>$user_supplied_words); $json_data=json_encode($user_data); file_put_contents('path_to/user_data/thisuser',$json_data);
Затем, когда пришло время отображать страницу
<?php $user_data=array('title'=>'My page rocks!','content'=>'lorems ipso diddy doo dah'); $file_data=file_get_contents('path_to/user_data/thisuser'); if(!$user_data){$no_data=true;}//file not found $data_array=json_decode($user_data,true); if(!is_array($data_array)) { $no_data=true; }//maybe the json could not be parsed else { $user_data=array_merge($user_data,$data_array); } ?> <html> <head> <title>This is my page</title> </head> <body> <h1 class="editable"><?php echo $user_data['title']?></h1>
И так далее. Массив по умолчанию содержит стандартный контент для редактируемых разделов, которые печатаются, если пользователь не предоставил никаких. Если они есть, они загружаются и затем объединяются с массивом по умолчанию. Данные, загруженные из файла, будут перезаписывать информацию массива по умолчанию, если она доступна, в части array_merge.
Хорошо, я, наконец, решил. Если кто-то хочет найти какие-либо include, include_once, require, require_once в .php-файле, тогда вы можете использовать следующее регулярное выражение с помощью php-функции, такой как preg_match_all.
'/(?:include|include_once|require|require_once)\s*(?:[az]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?])*\?>)/i';
Это ищет любые включения и т. Д. В тегах. Обратившись к нему обратно к моему оригинальному примеру. Мой код выглядит так:
$html = new simple_html_dom(); $html->load_file("index.php"); $findinclude = '/(?:include|include_once|require|require_once)\s*(?:[az]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?])*\?>)/i'; if (preg_match_all($findinclude, $html,$includes)): // shift the array to the left $incfiles = $includes[0]; $i = 0; // then loop through the includes array and print our filename foreach ($incfiles as $inc) { print basename(preg_replace('/[^a-zA-Z0-9\s\.\_\/]/', '', $inc)."\n"); } endif;
Работа выполнена! Теперь я могу работать с этим, чтобы редактировать каждый файл по мере необходимости.