/edit2: Ok, ich habs hingekriegt.
Template Klasse - Rekursiv Pattern
Einklappen
X
-
Original geschrieben von TheBo
wenn die Klasse von rythmus (oder so) zumindest funktionieren würde ... mein Post bei seiner Klasse wird ignorier ... und in ICQ antwortet er auch nicht ...
ich "muss" auch andauernd support für meine scripte geben, und tuhe das auch nicht immer so gerne, aber ich weiss das ich anderen helfe.
Also, bitte melde dich mal bei mir ! (162424599)
Schreib doch am besten mal ne email.
Kommentar
-
So, weiter gehts mit Problemen.
Ich hab die Klasse jetzt auf folgendem Stand:
PHP-Code:class template {
var $open; // Starttag der Platzhalter
var $close; // Endtag der Platzhalter
var $clearopen; // Starttag _ohne_ escape!
var $clearclose; // Endtag _ohne_ escape!
var $values; // Werte der zu ersetzenden Strings
var $tplF; // Template Verzeichnis
var $fileType; // Endung der Templates (.tpl, .htm o.ä.)
// Definieren von Variablen
function template($open='{', $close='}', $fileType='.tpl', $tplF='./') {
$this->open = preg_quote($open, '/');
$this->close = preg_quote($close, '/');
$this->clearopen = $open;
$this->clearclose = $close;
$this->values = array();
$this->fileType = $fileType;
$this->tplF = $tplF;
}
// Den Platzhaltern Werte zuweisen
// Wenn isFile = true, wird versucht eine Datei als Wert einzubinden
function assign($var, $value, $isFile=false, $tplFolder=false) {
if($tplFolder == false) $tplFolder = $this->tplF;
if($isFile == true) {
if(!is_readable($tplFolder.$value.$this->fileType)) {
trigger_error('File <b>'.$tplFolder.$value.$this->fileType.'</b> is not readable.',ERROR);
} else {
$this->values[$var] = file_get_contents($tplFolder.$value.$this->fileType);
}
} else {
$this->values[$var] = $value;
}
}
// Ausgabe der Templates
function output($tpl) {
if(!is_readable($this->tplF.$tpl.$this->fileType)) {
trigger_error('File <b>'.$this->tplF.$tpl.$this->fileType.'</b> is not readable.',FATAL);
} else {
$content = file_get_contents($this->tplF.$tpl.$this->fileType);
echo $this->parse($content);
}
}
// replace var
function replace_var($key) {
return $this->values[$key[1]];
}
// Array ersetzen
function replace_array($ar) {
$pattern = '/'.$this->open.'(.*?)'.$this->close.'/iU';
$pattern2 = '/'.$this->open.'array name=([^'.$this->close.']+)'.$this->close.'(.*?)'.$this->open.'\/array'.$this->close.'/iUm';
$return = '';
for($i=0;$i<count($this->values[$ar[1]]);$i++) {
$string = $ar[2];
if(preg_match($pattern2, $string)) $string = $this->parse($string, $only=2);
foreach($this->values[$ar[1]][$i] AS $key => $val) {
$string = str_replace($this->clearopen.$key.$this->clearclose,$val,$string);
}
// $string = $this->parse($string, $only=1);
$return .= $string;
}
return $return;
}
// Parsen
function parse($string, $only=3) {
if($only != 2) {
// Ersetzen von Schleifen
$pattern = '/'.$this->open.'array name=([^'.$this->close.']+)'.$this->close.'(.*?)'.$this->open.'\/array'.$this->close.'/iUm';
$string = preg_replace_callback($pattern,array(&$this, 'replace_array'),$string);
}
if($only != 1) {
// Ersetzen von einfachen Platzhaltern
$pattern = '/'.$this->open.'(.*?)'.$this->close.'/i';
$string = preg_replace_callback($pattern,array(&$this, 'replace_var'),$string);
$string = $this->parse($string, $only=1);
}
return $string;
}
}
1. Das Script sucht beim Ersetzen eines Arrays nach dem ersten Vorkommen von {array name=xxx} und nach dem letzten {/array}, egal ob die zusammengehören. Die ? sind im Regexp vorhanden, ich wüsste nicht, wo ich da noch eins zwischenbauen sollte...
2. Wenn zwischen {array name=xxx} und {/array} ein Zeilenumbruch ist, trifft das Suchmuster nicht mehr zu, trotz Modifier "m".
Vielen Dank für Hilfe im Vorraus.
MfG Oli
Kommentar
-
U verwende ich bereits als Modifier.
Davon abgesehen, dass Verschachtelungen möglich sein sollen, gehts auch ohne nicht.
s bei Zeilenumbrüchen funktioniert, danke.
http://www.php-resource.de/tutorials/read/10/1/ laut diesem Tutorial ist m dafür aber geeignet, s wäre genau das Gegenteil.
Kommentar
-
Davon abgesehen, dass Verschachtelungen möglich sein sollen, gehts auch ohne nicht.
für verschachtelungen solltest du dir mal (?R) anschauen ... dient erstmal nur dazu, die richtige verschachtelung zu finden.
Code:#{array name=(.+)}(.+){/array}#isU
die { brauchst du scheinbar nicht slashen, weil php das wohl unterscheiden kann ...Zuletzt geändert von derHund; 15.10.2004, 23:22.Die Zeit hat ihre Kinder längst gefressen
Kommentar
-
hi derHund,
also dein Suchmuster funktioniert soweit.
Das mit dem (?R) hab ich allerdings nicht verstanden.
Ich hab mich mal hier (http://www.php-faq.de/ch/ch-regexp.html) umgesehen, aber da nichts darüber gefunden.
MfG Oli
Kommentar
-
Das mit dem (?R) hab ich allerdings nicht verstanden.
ganz unten, vorletzter abschnitt ... damit du den zugehörigen, schließenden tag findest ...Die Zeit hat ihre Kinder längst gefressen
Kommentar
-
so, da bin ich wieder.
Also so wie ich derHund verstanden habe, muss ich mein Pattern so aufbauen:
Suche nach alle {array name=x} ... {/array}, wo in ... kein weiteres {array name=x} enthalten ist.
Das wäre zumindest die Lösung, da er dann Verschachtelungen von Innen nach außen ersetzt.
Mit den Assertions ist das allerdings ein bisschen komisch.
Mein Suchmuster sieht so aus:
Code:#{array name=(.*?)} (.*) {/array}#isU
Code:#{array name=(.*?)} (.*(?!:{array name=(.*?)})) {/array}#isU
Ich hoffe, ich hab dich richtig verstanden, derHund.
MfG OliZuletzt geändert von OliOli; 20.10.2004, 17:36.
Kommentar
-
Hallo,
Leider bin ich nach etlich langem rumprobieren immer noch zu keiner Lösung gekommen. Ich fasse mal zusammen, wo ich derzeit stehe:
Ich suche nach wie vor, einen pattern, der in einem templates zeichenketten wie {array name=(.*)} (.*) {/array} ersetzt durch den Rückgabewert einer Funktion.
Mein code:
PHP-Code:$pattern = '/'.$this->open.'array'.$add.' name=(.*)'.$this->close.'(.*)'.$this->open.'\/array'.$this->close.'/isU';
$string = preg_replace_callback($pattern,array(&$this, 'replace_array'),$string);
- Ich komme mit dem greedy nicht so ganz zurecht. Wenn ich einerseits verschachtelte, aber auch aufeinander folgende arrays habe, dann wird logischerweise immer was falsch gemacht. Bsp:
{array name=asdj} ich bin ein verschachtelrtes {array name=zweites} array {/array} und und und {/array} <br> {array name=drittes} Ich stehe hinter den beiden anderen {/array}
Wenn ich den modifier U oder ein ? nicht verwende, dann nimmt der das {array name=xxx} vom allerersten array, und das {/array} vom allerletzten. Die gehören dummerweise nicht zueinander. Wenn ich den modifier benutze, dann nimmt er logischerweise das erste {array name=xxx} und das erste {/array}, die ja auch nicht zueinander gehören. Hier hab ich nur einen Lösungsansatz: Wenn ich den regex so wenig wie möglich fressen lasse, ihm aber sage, dass zwischen den tags kein array name=xxx} vorkommen darf, dann müsste er sich von innen nach außen vorarbeiten können. Wie ich das mache, ist mir aber schleierhaft. - Verschachtelungen sind zwar, das habe ich inzwischen soweit verstanden, mit (?R) also recursive pattern lösbar, aber wie genau das auszusehen hat, weiß ich noch nicht.
Wäre super nett, wenn ihr versucht mir nochmal zu helfen.
Immer bedenken, dass ich php (noch) nicht gut kann.
MfG Oli
Kommentar
- Ich komme mit dem greedy nicht so ganz zurecht. Wenn ich einerseits verschachtelte, aber auch aufeinander folgende arrays habe, dann wird logischerweise immer was falsch gemacht. Bsp:
-
hab ich auch schon dran gedacht, aber erstmal muss er ja das passende {/array} zum {array name=xxx} finden
kuckst du: http://pcre.nophia.de/evaluate/267c6...dex.php#output bzw. http://pcre.nophia.de/evaluate/1a7b9...dex.php#output
in \1 findest du den namen, in \2 den inhalt, den du erneut - vorzugsweise rekursiv - parsen mußt. siehe auch das beispiel in den codeschnipseln.Zuletzt geändert von derHund; 31.10.2004, 14:10.Die Zeit hat ihre Kinder längst gefressen
Kommentar
-
Vielen lieben Dank, alle zusammen.
Die Klasse funktioniert jetzt so, wie sie soll.
Hier nochmal das ganze:
PHP-Code:<?php class template {
var $open; // Starttag der Platzhalter
var $close; // Endtag der Platzhalter
var $values; // Werte der zu ersetzenden Strings
var $tplF; // Template Verzeichnis
var $fileType; // Endung der Templates (.tpl, .htm o.ä.)
var $m; // Zähler für Arrays
// Definieren von Variablen
function template($open='{', $close='}', $fileType='.tpl', $tplF='./') {
$this->open = $open;
$this->close = $close;
$this->values = array();
$this->fileType = $fileType;
$this->tplF = $tplF;
$this->m = 0;
}
// Den Platzhaltern Werte zuweisen
// Wenn isFile = true, wird versucht eine Datei als Wert einzubinden
function assign($var, $value, $isFile=false, $tplFolder=false) {
if($tplFolder == false) $tplFolder = $this->tplF;
if($isFile == true) {
if(!is_readable($tplFolder.$value.$this->fileType)) {
trigger_error('File <b>'.$tplFolder.$value.$this->fileType.'</b> is not readable.',ERROR);
} else {
$this->values[$var] = $this->parse(file_get_contents($tplFolder.$value.$this->fileType),2);
}
} else {
$this->values[$var] = $value;
}
}
// Ausgabe der Templates
function output($tpl) {
if(!is_readable($this->tplF.$tpl.$this->fileType)) {
trigger_error('File <b>'.$this->tplF.$tpl.$this->fileType.'</b> is not readable.',FATAL);
} else {
$content = file_get_contents($this->tplF.$tpl.$this->fileType);
echo $this->parse($content);
}
}
// replace var
function replace_var($key) {
return $this->values[$key[1]];
}
// Array ersetzen
function replace_array($ar) {
$pattern = '/'.$this->open.'array name=(.*?)'.$this->close.'(.*)'.$this->open.'\/array'.$this->close.'/is';
$return = '';
for($i=0;$i<count($this->values[$ar[1]]);$i++) {
$string = $ar[2];
if(preg_match($pattern, $string))
$string = $this->parse($string, $only=1);
foreach($this->values[$ar[1]][$i] AS $key => $val) {
$string = str_replace($this->open.$key.$this->close,$val,$string);
}
$return .= $string;
}
return $return;
}
// Parsen
function parse($string, $only=3) {
if($only != 1) {
foreach($this->values AS $key => $val) {
if(!is_array($val)) {
$string = str_replace($this->clearopen.$key.$this->clearclose,$val,$string);
}
}
}
if($only != 2) {
$pattern = '/'.$this->open.'array name=(.*)'.$this->close.'(((?R)|(.*))*)'.$this->open.'\/array'.$this->close.'/isU';
$string = preg_replace_callback($pattern,array(&$this, 'replace_array'),$string);
}
return $string;
}
} ?>- Normale Platzhalter entweder durch strings oder durch Dateien ersetzen, in denen wiederum Platzhalter entahlten sein dürfen. (AFAIK unendlich tiefe verschachtelung möglich)
- Ersetzen von arrays, nach dem Schema {array name=ARRAY_NAME} text {ARRAY_ITEM} {/array}. Verschachtelungen beliebig tief möglich.
MfG Oli
Kommentar
Kommentar