Как удалить PHP код из строки?

у меня есть строка, в которой есть php-код, мне нужно удалить php-код из строки, например:

<?php $db1 = new ps_DB() ?><p>Dummy</p>

должен возвратить <p>Dummy</p>

и строка без php, например <p>Dummy</p> должен возвращать ту же строку.

Я знаю, что это можно сделать с помощью регулярного выражения, но после 4h я не нашел решения.

4 ответов


 <?php
 function filter_html_tokens($a){
    return is_array($a) && $a[0] == T_INLINE_HTML ?
      $a[1]:
      '';
 }
 $htmlphpstring = '<a>foo</a> something <?php $db1 = new ps_DB() ?><p>Dummy</p>';
 echo implode('',array_map('filter_html_tokens',token_get_all($htmlphpstring)));
 ?>

как отметил ircmaxell: для этого потребуется действительный PHP!

маршрут регулярных выражений будет (без учета " php " с короткими тегами. без конца ?> в строке / файле (по какой-то причине Zend рекомендует это?) и, конечно, UNgreedy & DOTALL шаблон:

preg_replace('/<\?.*(\?>|$)/Us', '',$htmlphpstring);

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

следующая инструкция удалит тег PHP:

preg_replace('/^<\?php.*\?\>/', '', '<?php $db1 = new ps_DB() ?><p>Dummy</p>');

если он не найдет совпадения, он ничего не заменит.


Ну, вы можете использовать DomDocument для этого...

function stripPHPFromHTML($html) {
    $dom = new DomDocument();
    $dom->loadHtml($html);
    removeProcessingInstructions($dom);
    $simple = simplexml_import_dom($d->getElementsByTagName('body')->item(0));
    return $simple->children()->asXml();
}

function removeProcessingInstructions(DomNode &$node) {
    foreach ($node->childNodes as $child) {
        if ($child instanceof DOMProcessingInstruction) {
            $node->removeChild($child);
        } else {
            removeProcessingInstructions($child);
        }
    }
}

эти две функции превратят

$str = '<?php echo "foo"; ?><b>Bar</b>';
$clean = stripPHPFromHTML($str);
$html = '<b>Bar</b>';

Edit: на самом деле, посмотрев на ответ Wrikken, я понял, что оба метода имеют недостаток... Мой требует несколько допустимой HTML-разметки (Dom приличный, но он не будет разбирать <b>foo</b><?php echo $bar). Wrikken требует действительного PHP (любые синтаксические ошибки, и он потерпит неудачу). Поэтому, возможно, сочетание двух (сначала попробуйте один. Если это не удается, попробуйте другой. Если оба терпят неудачу, на самом деле вы мало что можете сделать, не пытаясь выяснить точную причину их неудачи)...


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

function strip_php($str) {

  $newstr = '';

  //split on opening tag
  $parts = explode('<?',$str);

  if(!empty($parts)) {
      foreach($parts as $part) {

          //split on closing tag
          $partlings =  explode('?>',$part);
          if(!empty($partlings)) {

              //remove content before closing tag
              $partlings[0] = '';
          }

          //append to string
          $newstr .= implode('',$partlings);
      }
  }
  return $newstr;
}

это медленнее, чем регулярное выражение, но не требует допустимого html или php; для этого требуется только закрыть все теги php.

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

  $tag_diff = (substr_count($str,'<?') - (substr_count($str,'?>');

  //Append if there's one less closing tag
  if($tag_diff == 1) $str .= '?>';

  //Parse error if the tags don't add up
  if($tag_diff < 0 || $tag_diff > 1) die('Error: Tag mismatch. 
  (Opening minus closing tags = '.$tag_diff.')<br><br>
  Dumping content:<br><hr><br>'.htmlentities($str));