preg_replace durch preg_replace_callback ersetzen

Biki

Grünschnabel
Hallo zusammen,
da hier so wunderbar geholfen wird, trau ich mich mal - nachdem ich schon endlos probiert habe - mein Problem zu schildern.

Es wird dringend Zeit preg_replace mit dem Modifier e auszutauschen aber ich komme damit einfach nicht zurecht.
Wenn ich mehrer preg_replace_callback-Funktionen habe, muss ich dann für jedes Austauchen einen neuen Variablen-Namen nehmen oder kann die Funktion immer function ($m) heißen?

Hier ist mein Hauptproblem
PHP:
$stack[$p][$key]['PARSED'] = preg_replace('/(\{\s*(\w+)\((.*)\)\s*\})/e', '(method_exists(\'Template\', \'tpl_$2\'))?$this->tpl_$2("$3"):"$1"', $stack[$p][$key]['FUNC']);

Die Variablen $3 und $1 tauchen öfter auf und ich hab bei einer "leichteren" Stelle mal angefangen

PHP:
function tpl_calc($param)
    {
      $param =
        preg_replace('/{(\w+)}/e', '$this->getval("$1", true)',
        preg_replace('/\{('. PREG_FLT. ')\}/', '$1',
        preg_replace('/('. PREG_FLT. ')|\b\w+\b/', '{$0}', $param
      )));
      do
        $param = preg_replace(
          '/^\s*('. PREG_FLT. ')\s*([-\/\^|&!*+%]|&~|\|\||&&|!=)\s*('. PREG_FLT. ')/e',
          '$1$3$4', $tmp = $param);
      while ($tmp!=$param);
      return $param;
    } // Template::tpl_cal
Wenn ich das richtig verstanden habe muss das erste preg_replace folgendermaßen ersetzt werden.
PHP:
preg_replace_callback('/{(\w+)}/', function ($m) { return $this->getval($m[1], true);},

Muss die Variable $1 in der nächsten Zeile auch durch $m[1] ersetzt werden?
Bei der nächsten Umstellung bin ich mir schon gar nicht mehr sicher, was zu tun ist.
PHP:
preg_replace_callback(
          '/^\s*('. PREG_FLT. ')\s*([-\/\^|&!*+%]|&~|\|\||&&|!=)\s*('. PREG_FLT. ')/',
          function ($m) { return $m[1]$m[3]$m[4];}, $tmp = $param);
Vermutlich liege damit allerdings falsch.
Für Hilfe wäre ich echt dankbar.
Schöne Grüße
Biki
 

Sempervivum

Erfahrenes Mitglied
Wenn ich mehrer preg_replace_callback-Funktionen habe, muss ich dann für jedes Austauchen einen neuen Variablen-Namen nehmen oder kann die Funktion immer function ($m) heißen?
Die Funktion selber ist in dem Fall ja anonym und hat keinen Namen. Was Du meinst, ist der Name des Parameters $m und der kann jedes Mal gleich sein, die Funktion wird jedes Mal mit dem richtigen Wert für diesen Parameter aufgerufen.
 

Biki

Grünschnabel
Vielen Dank, Sempervivum.
Dann habe ich diese Frage schon einmal geklärt.
Kannst du mir sagen, ob mein Ersetzungsversuch richtig ist?
Ich habe viele Beispiele gefunden, wo z.B. ("\\1") in der Funktion durch $m[1] ersetzt wurde.
Hier habe ich $1 durch $m[1] ersetzt.
Schöne Grüße
Biki
 

Biki

Grünschnabel
Mittlerweile habe ich herausgefunden, dass es keinen Unterschied macht, ob ("$1") oder ("\\1") verwendet wird.
Wieder ein Problem weniger.

Außerdem denke ich, dass bei callback einige Zeichen (z.B. \ ) wegfallen müssen.
Alter Code:
PHP:
$stack[$p][$key]['PARSED'] = preg_replace('/(\{\s*(\w+)\((.*)\)\s*\})/e', '(method_exists(\'Template\', \'tpl_$2\')) ? $this->tpl_\\2("$3") : "$1"', $stack[$p][$key]['FUNC']);
Neu:
PHP:
$temp1 = 'Template';
$temp2 = 'tpl_$2';
$stack[$p][$key]['PARSED'] = preg_replace_callback('/(\{\s*(\w+)\((.*)\)\s*\})/', function($m){return(method_exists($temp1, $temp2)) ? $this->$temp2($m[3]) : $m[1];  }, $stack[$p][$key]['FUNC']);
Aber irgendwie funktioniert es trotzdem nicht.
Was mache ich denn da falsch?
 

Sempervivum

Erfahrenes Mitglied
Poste am besten mal einen Musterstring, den Du überarbeiten willst und beschreibe, was geändert werden soll.
 

Biki

Grünschnabel
Ja, gerne. Entschuldige, wenn das alles etwas konfus klingt, aber ich muss das irgendwie hinkriegen und habe nicht wirklich Ahnung davon.
Hier mal die gesamte Funktion
PHP:
      function parseTemplateString($tpl) {
          $parsedTpl = $tpl;
          $stack = array();
          $stackPointer = 0;
          $stackPointerStatus = array(TRUE);
          $tplPointer = 0;
          while ($tplPointer < strlen($tpl)) {
              $posOpen = strpos($tpl, '{', $tplPointer);
              $posClose = strpos($tpl, '}', $tplPointer);
              if ($posOpen == FALSE && $posClose == FALSE) {
                  $tplPointer = strlen($tpl);
              } elseif (($posOpen < $posClose) && $posOpen !== FALSE) {
                  if ($stackPointerStatus[$stackPointer] == TRUE) {
                      $stack[$stackPointer][] = array('START' => $posOpen);
                      $stackPointerStatus[$stackPointer] = FALSE;
                  } else {
                      $stackPointer++;
                      $stack[$stackPointer][] = array('START' => $posOpen);
                      $stackPointerStatus[$stackPointer] = FALSE;
                  }
                  $tplPointer = $posOpen + 1;
              } elseif (($posOpen > $posClose) || $posOpen == FALSE) {
                  $tplPointer = $posClose + 1;
                  $stackPointerStatus[$stackPointer] = TRUE;
                  $l = count($stack[$stackPointer]) - 1;
                  $stack[$stackPointer][$l]['END'] = $posClose;
                  $stackPointer--;
              }
          }
          for ($p = count($stack) - 1; $p >= 0; $p--) {
              if (is_array($stack[$p])) {
                  foreach ($stack[$p] as $key => $value) {
                      $stack[$p][$key]['FUNC'] = substr($tpl, $value['START'], ($value['END'] - $value['START'] + 1));
// replace functions
//--- UM DIESEN TEIL GEHT ES ---------------------------------------------------------------------------------
$stack[$p][$key]['PARSED'] = preg_replace('/(\{\s*(\w+)\((.*)\)\s*\})/e', '(method_exists(\'Template\', \'tpl_$2\')) ? $this->tpl_$2("$3") : "$1"', $stack[$p][$key]['FUNC']);
//--- UM DIESEN TEIL GEHT ES ---------------------------------------------------------------------------------
                  }
              }
          }
          #$tplReplacementOffset
          $replacePos = 0;
          for ($r = 0; $r < count($stack); $r++) {
              if (is_array($stack[$r])) {
                  foreach ($stack[$r] as $key => $value) {
                      $parsedTpl = str_replace($stack[$r][$key]['FUNC'], $stack[$r][$key]['PARSED'], $parsedTpl);
                  }
              }
          }
          $text = $parsedTpl;
          if (is_array($this->vars)) {
              foreach ($this->vars as $name => $value) {
                  if (($name != "content") || (strpos($text, '{'.$name.'}') !== false)) {
                      $text = str_replace('{' . $name . '}', $this->getval($name), $text);
                  }
              }
          }
          return $text;
      }
Den markierten Teil habe ich geändert
preg_replace --- preg_replace_callback
/e --- /
\'Template\' >>> 'Template'
\'tpl_$2\' >>> 'tpl_$2'
$this->tpl_$2("$3") >>> $temp2($m[3])
hier habe ich eine zusätzliche Variable erstellt ($temp2), da ich mit tpl_$2 und tpl_$m[2] eine Fehlermeldung erhielt
(Parse error: syntax error, unexpected '$'
Parse error: syntax error, unexpected '$m')
"$1" >>> $m[1]
PHP:
$temp2 = 'tpl_$2';
$stack[$p][$key]['PARSED'] = preg_replace_callback('/(\{\s*(\w+)\((.*)\)\s*\})/', function($m){return(method_exists('Template', 'tpl_$2')) ? $this->$temp2($m[3]) : $m[1];}, $stack[$p][$key]['FUNC']);

Kann es sein, dass die Seite erst dann wieder richtig angezeigt wird, wenn ich alle PREG_REPLACE_EVAL ersetzt habe?
Danke fürs Anschauen
Biki
 
Zuletzt bearbeitet:

Sempervivum

Erfahrenes Mitglied
Der ganze Code war gar nicht mal nötig. Was fehlt ist jedoch ein Beispielstring und eine Beschreibung, wie dieser geändert werden soll und wie er nachher aussehen soll.
 

Biki

Grünschnabel
Puh - ich habs raus gekriegt.
Aus
Code:
$stack[$p][$key]['PARSED'] = preg_replace('/(\{\s*(\w+)\((.*)\)\s*\})/e', '(method_exists(\'Template\', \'tpl_$2\')) ? $this->tpl_$2("$3") : "$1"', $stack[$p][$key]['FUNC']);
wird
Code:
 $stack[$p][$key]['PARSED'] = preg_replace_callback('/(\{\s*(\w+)\((.*)\)\s*\})/', function($m){$tpll = 'tpl_'.$m[2];return(method_exists('Template', 'tpl_'.$m[2])) ? $this->$tpll($m[3]) : $m[1];}, $stack[$p][$key]['FUNC']);

Danke für Denkanstöße, Sempervivum