Сохранение файла .php и сохранение включений тоже (возможно) - PullRequest
2 голосов
/ 09 января 2010

Настройка:

У меня есть стандартный файл .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>

и footer .php вот так:

<p>The end of my page</p>
</body>

Я пишу скрипт PHP, который позволяет вам редактировать любые элементы ".editable" на странице. Моя проблема в том, что эти редактируемые области могут появляться в любых включаемых файлах, а также в основной части index.php.

Мой php-код захватывает файл index.php с помощью file_get_contents (); который работает хорошо. Я также могу редактировать и сохранять любые «.editable» регионы в index.php.

Моя проблема:

Мне не удалось найти способ «найти» включения и проанализировать их для «.editable» регионов. Я ищу предложения о том, как мне работать со всеми включениями в index.php - проверяя их на наличие редактируемых областей. Нужно ли использовать регулярные выражения, чтобы найти «include * .php»? Я не уверен, с чего начать ...

Для тех из вас, кто хочет увидеть мой PHP-код. Я использую класс PHP: [текст ссылки] [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*(?:[a-z]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?]|[^\?\>])*\?>)/i';

Это соответствует довольно хорошо, хотя, похоже, возвращает нечетное) и 'при использовании preg_match. Я пытаюсь добавить немного безопасности в регулярное выражение, чтобы обеспечить совпадение только между тегами php - эта часть: (? = (?: [^ \ <\?] | [^ \?>]) * \?>) - но он возвращает только первое включение на странице. Любые советы о том, как улучшить это регулярное выражение? (Я был у него около 6 часов)

Ответы [ 6 ]

1 голос
/ 14 января 2010

Основываясь на предоставленном вами регулярном выражении, я немного его оптимизировал и исправил несколько важных ошибок:

~<[?].*?(?: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 () намного надежнее регулярных выражений.

1 голос
/ 09 января 2010

Я вас неправильно понял, не обращайте внимания на все после 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.

1 голос
/ 09 января 2010

Какой тип системы вы создаете?

Если он будет использоваться публикой, у вас будут серьезные проблемы с безопасностью. Люди могут включать свой собственный код PHP или JavaScript в поставляемый контент.

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

Если вы разрешите им включать HTML, используйте для очистки что-то вроде html cleaner , вставьте данные в базу данных с подготовленным оператором, используя PDO . Я уверен, что люди здесь будут рады ответить на любые ваши вопросы об использовании базы данных.

0 голосов
/ 10 января 2010

Хорошо, я наконец-то решил это. Если кто-то хочет найти в файле .php include, include_once, require, require_once, вы можете использовать следующее регулярное выражение с функцией php, например preg_match_all.

'/(?:include|include_once|require|require_once)\s*(?:[a-z]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?])*\?>)/i';

Это выглядит для любых включений и т. Д. В тегах. Ссылка это обратно на мой оригинальный пример. Мой код выглядит так:

$html = new simple_html_dom();
$html->load_file("index.php");

$findinclude = '/(?:include|include_once|require|require_once)\s*(?:[a-z]|"|\(|\)|\'|_|\.|\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;

Работа выполнена! Теперь я могу работать с этим, чтобы редактировать каждый файл по мере необходимости.

0 голосов
/ 09 января 2010

Вам нужно просто где-то хранить введенный пользователем текст, загружать его и выводить его вместе с вашим шаблоном 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.

0 голосов
/ 09 января 2010

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

У вас должны быть простые шаблоны с небольшим количеством PHP или без него, которые анализируются - тогда и только тогда вы должны вставить контент в DOM, после того как он будет должным образом очищен.

Способ решения проблемы «поиска включений» - вам это не нужно, PHP сделает это за вас - возможно, используйте ob_start и др. и затем включите файл шаблона. Затем захватите содержимое буфера (это будет HTML) и затем проанализируйте уже собранный шаблон с помощью анализатора DOM.

Пожалуйста, ПОЖАЛУЙСТА, убедитесь, что вы дезинфицируете все, что вводите в DOM.

В противном случае, тирания и разрушение наверняка обрушатся на ваш веб-сайт (и вас, в зависимости от того, что еще находится на вашем сервере).

...