/**
* Der Pfad zur Template Datei
* @var <string> $file
*/
private $file;
/**
* Enthält alle Variablen die ersetzt werden.
* Im Index befindet sich der Variabelnname
* und der dazugehörige Wert ist der Wert der Variable
* @var <array> $vars
*/
private $vars = Array();
/**
* Konstrucktor
* Hier wird geprüft ob die angegebene Datei existiert.
* Wenn nicht wird eine Fehlermeldung ausgegeben.
* @param <string> $file der Pfad zur Templatedatei
*/
public function __construct ($file) {
if( is_file ($file) ) {
$this->file = $file;
} else {
die ( "<strong>FEHLER: </strong>Die angebene Template-Datei \"$file\" existiert nicht!");
}
}
/**
* Hier werden Variablen gesammelt die später im Template File eingesetzt werden
* @param <string> $var Name der Variable
* @param <string> $value Inhalt der Variable
*/
public function setvar($var, $value) {
$this->vars[$var] = $value;
}
/**
* Gibt die angegebene Variable zurück die mit setvar() definiert hat.
* Falls sie nicht existiert wird false zurückgegeben.
*
* @param <string> Variablenname
* @return <mixed> inhalt der Variable on success, <bool> false on failure.
*/
public function getvar($var) {
if ($this->varexists($var)) {
return $var;
} else {
return false;
}
}
/**
* Prüft ob eine Variable bereits mit setvar gesetzt wurde
*
* @param <string> Variabelnname
* @return <bool> true on success, false on failure
*/
public function varexists($var) {
return isset($this->vars[$var]);
}
/**
* Hier kann man mehrere Variabeln auf einmal angeben.
* Im index den Variablenamen und der dazugehörige wert ist der Inhalt der Variable
*
* @param <array> $array
*/
public function array_setvar($array) {
$keys = array_keys($array);
$value = array_values($array);
foreach( $keys as $k => $key){
if(!ctype_digit($key))
$this->setvar($key, $value[$k]);
}
}
/**
* Der Inhalt der Template Datei wird umgeformt, damit es eval ausführen kann.
* @return <string> Der geparste inhalt von der Datei dessen Pfad in der Eigenschaft $file festgelegt ist
*/
private function parse() {
//Die Template Datei wird ausgelesen
$var = file_get_contents($this->file);
//alle " werden escaped
$var = str_replace('"','\\"', $var);
$var = str_replace( '?}', ' echo "', str_replace('{?', '"; ', $var ));
$var = str_replace( '.}', ' . "', str_replace('{.', '" . ', $var ));
$var = preg_replace_callback('`"; (.*?) echo "`si', create_function( '$treffer', 'return str_replace(\'\\"\', \'"\',$treffer[0]);') , $var);
$var = preg_replace_callback('`" \. (.*?) \. "`si', create_function( '$treffer', 'return str_replace(\'\\"\', \'"\',$treffer[0]);') , $var);
return $var;
}
/**
* Gibt den Geparsten Inhalt der Template Datei aus
* @return <string>
*/
public function output() {
//Die Ausgabe wird angehalten
ob_start();
//Alle Variablen werden extrahiert
extract($this->vars, EXTR_SKIP);
//Die Ausgabe wird kommt in den Ausgabepuffer
eval('echo "' . $this->parse() . '";');
//Der Ausgabepuffer wird der variable ausgabe zugewiesen
$ausgabe = ob_get_contents();
//Der Ausgabepuffer wird geleert
ob_end_clean();
//Der Inhalt des Ausgabepuffers wird zurückgegeben
return $ausgabe;
}
}
?>
Da ihr jetzt sehrwahrscheindlich eh nur drübergeflogen seid, und nicht wisst um was es geht, mach ich euch ein Anwendungs Beispiel.
<?php
//Die Klasse wird eingebunden
require_once("mtpl.class.php");
//Das Objekt wird erstellt
$tpl = new mtpl("test.tpl");
//Drei Variabeln werden auf einmal gesetzt
$tpl->array_setvar(
Array(
'titel' => "Alphabet",
'heading' => "Die Buchstaben des Alphabet's",
'text' => "Hier sehen sie Alle 26 Buchstaben des Alphabets"
)
);
//Es werden alle Buchstaben des Alphabets geholt
$buchstaben = Array();
for($i = 0; $i<26; $i++){
$buchstaben[] = chr($i + 97);
}
//Die Variable "chars" wird gesetzt
$tpl->setvar('chars', $buchstaben);
//Das Template Wird geparst & ausgegeben
echo $tpl->output();
?>
Und das ist der Quellcode der in den Browser kommt:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Alphabet</title>
</head>
<body>
<h1>Die Buchstaben des Alphabet's</h1>
<p>Hier sehen sie Alle 26 Buchstaben des Alphabets</p>
<table border="1" cellpadding="2">
<tr>
<td>1</td>
<td>a</td>
</tr>
<tr>
<td>2</td>
<td>b</td>
</tr>
<tr>
<td>3</td>
<td>c</td>
</tr>
<tr>
<td>4</td>
<td>d</td>
</tr>
<tr>
<td>5</td>
<td>e</td>
</tr>
<tr>
<td>6</td>
<td>f</td>
</tr>
<tr>
<td>7</td>
<td>g</td>
</tr>
<tr>
<td>8</td>
<td>h</td>
</tr>
<tr>
<td>9</td>
<td>i</td>
</tr>
<tr>
<td>10</td>
<td>j</td>
</tr>
<tr>
<td>11</td>
<td>k</td>
</tr>
<tr>
<td>12</td>
<td>l</td>
</tr>
<tr>
<td>13</td>
<td>m</td>
</tr>
<tr>
<td>14</td>
<td>n</td>
</tr>
<tr>
<td>15</td>
<td>o</td>
</tr>
<tr>
<td>16</td>
<td>p</td>
</tr>
<tr>
<td>17</td>
<td>q</td>
</tr>
<tr>
<td>18</td>
<td>r</td>
</tr>
<tr>
<td>19</td>
<td>s</td>
</tr>
<tr>
<td>20</td>
<td>t</td>
</tr>
<tr>
<td>21</td>
<td>u</td>
</tr>
<tr>
<td>22</td>
<td>v</td>
</tr>
<tr>
<td>23</td>
<td>w</td>
</tr>
<tr>
<td>24</td>
<td>x</td>
</tr>
<tr>
<td>25</td>
<td>y</td>
</tr>
<tr>
<td>26</td>
<td>z</td>
</tr>
</table>
<p>Heute ist der 26.07 im Jahre 2010</p>
</body>
</html>
Erklärung des Output Vorgangs: In der Funktion output() wird die Ausgabepufferung aktiviert. Alles was jetzt Ausgegeben wird z.B. mit echo, kommt in den Ausgabepuffer. Nun werden alle Variabeln die Vorher gesetzt wurden extrahiert. d.h. ein $array['index'] = "inhalt" wird zu $index = "inhalt".
Danach wird die Parse Funktion aufgerufen, und die Am anfang angegebene Datei wird ausgelesen. Es werden alle " escaped & alle {. werden zu " . , .} wird zu . " , {? wird zu "; , ?} wird zu echo " . Mit den 2 preg_replace_callback werden die slashes vor " entfernt die sich in einen von den bereichen {? ?} oder {. .} befinden, damit keine Fehler aufstreten, wenn man darin strings schreibt mit dem Double Qout.
Das Ergebnis wird zurückgegeben und per eval & echo ausgegeben, damit die Variablen die wir aus den Array geholt haben ihre Wirkung nehmen.
Eval führt Folgenden PHP code aus:
<?
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head>
<title>$titel</title>
</head>
<body>
<h1>$heading</h1>
<p>$text</p>
<table border=\"1\" cellpadding=\"2\">
"; foreach($chars as $k => $char) { echo "
<tr>
<td>" . ($k + 1 ) . "</td>
<td>" . $char . "</td>
</tr>
"; } echo "
</table>
<p>Heute ist der " . date('d.m') . " im Jahre " . date("Y") . "</p>
</body>
</html>";
Das ganze geht so in den Ausgabepuffer. Der Ausgabepuffer wird der Variable $ausgabe zugewiesen. Der Ausgabepuffer wird geleert, und die Ausgabepufferung wird abgeschalten.
$ausgabe wird zurückgegeben. Und schliesslich dann in test.php mit echo ausgegeben...
mfg
Mogria
Post wurde schon 2x editiert, das letzte mal am 26.07.2010 um 18:55 von Mogria
Ich such das Oho daran. Die vielen Fragezeichen verwirren nur.
Ansonsten werden wiederum ganz normale php befehle in der Template datei verwendet. foreach unsw.
Was es wiederum dem Sine einer Template wiederspricht.
Selbiges haste in einer MVC Struktur ohne Templates.
Zudem entsteht weiters durch eval ein großes Sicherheitsrisiko.
Mfg Splasch
Post wurde schon 2x editiert, das letzte mal am 27.07.2010 um 23:58 von splasch
Orginal von splasch
Ich such das Oho daran. Die vielen Fragezeichen verwirren nur.
Ansonsten werden wiederum ganz normale php befehle in der Template datei verwendet. foreach unsw.
Was es wiederum dem Sine einer Template wiederspricht.
Selbiges haste in einer MVC Struktur ohne Templates.
Zudem entsteht weiters durch eval ein großes Sicherheitsrisiko.
Mfg Splasch
Das oho ist, das die Klasse klein ist und man trotzdem im Stande Schleifen & if statements zu machen. Und das mit den Fragezeichen könnte man ändern, ich fand das zeichen einfach nur passend ;-).
Solange ich niemand an meinen Templates rumfummelt, besteht kein sicherheitsriso.
Solange ich niemand an meinen Templates rumfummelt, besteht kein sicherheitsriso
Das ist definitive falsch. Jeder der diese Klasse 1 zu 1 übernihmt hat das Sicherheitsrisiko.
Beispiel:
Ein einfaches Gästebuch. Besucher schreiben Php befehle ins Gästebuch diese werden dann sofort ausgeführt und die ganze Webseite kann damit zuerstört werden oder andere unfug damit getrieben werden. Er kann dir damit alles löschen oder auch kopieren unsw. Im Grunde alles machen was er will.
Solange ich niemand an meinen Templates rumfummelt, besteht kein sicherheitsriso
Das ist definitive falsch. Jeder der diese Klasse 1 zu 1 übernihmt hat das Sicherheitsrisiko.
Beispiel:
Ein einfaches Gästebuch. Besucher schreiben Php befehle ins Gästebuch diese werden dann sofort ausgeführt und die ganze Webseite kann damit zuerstört werden oder andere unfug damit getrieben werden. Er kann dir damit alles löschen oder auch kopieren unsw. Im Grunde alles machen was er will.
Mfg Splasch
Was quatschst du hier für sche**se rum. Hast du dir die Klasse überhaupt angeschaut? Oder hast du einfach nur "eval" gesehen? Der inhalt der Variablen kann nicht ausgeführt werden, sondern wird lediglich ausgegeben.
Ein beispiel wir setzten die Variable "angriff" = "\"; fieser_hacker_angriff(); echo \"";
und in der Template datei steht nur $angriff
den code den eval nun ausführt ist:
echo "$angriff";
Was ist daran gefährlich ? Jetzt wird einfach das ausgegeben:
"; fieser_hacker_angriff(); echo "
Ich habs gerade mal zufällig entdeckt und bin zwar n ziemlicher Anfänger aber: Welchen Sinn hat das?
Ich seh in dieser tpl eigentlich nur normalen HTML- und PHP-Code (mal abgesehen davon, dass <?php ?> durch {? ?} ersetzt wurde).
Mir persönlich ist es egal, ob nun Sicherheitsbedenklich oder nicht, ich würds schon allein deswegen nicht nehmen, weil PHP mir das ganze von Haus aus ohne komplizierte, externe, Templateklasse bietet.
Oder kann mir jemand erklären, warum man diese (oder von mir aus auch irgendeine andere Template Engine) nutzen soll?
Kann vielleicht daran liegen, dass ich wirklich noch zu wenig Ahnung habe, aber ich seh überhaupt keinen Vorteil in sowas...
Naja, also wenn jemand sich in eine externe Template Engine einarbeiten kann, dann wird er auch in der Lage sein sich die Grundlagen zu PHP anzueignen?
Ich mein, dort steht zwar der Text des "Templates":
Es ist das selbe in Grün - nur das ich mir für die Kleinigkeit keine extra Klasse schreiben muss, geschweige denn mich Stundenlang in sowas wie Smarty einarbeiten muss.
Wie wir sehen: Bei mir brauch man trotz fehlender Template Engine keine PHP-Kentnisse die man nicht in 5 Sekunden auswendig lernen kann.
Beide Beispiele sind keine wirklich Template hab ich übrings damals auch schon erwähnt!
Das was du das sieht sind im besten fall View und in View ist wiederum php Code erlaubt.
Mfg Splasch
Post wurde schon 1x editiert, das letzte mal am 30.07.2012 um 00:53 von splasch
Ein MVC-Modell kann eine Template nutzen für den VIEW-Part, muss es aber nicht. Was hier gezeigt wird, sind auch Templates, da Templates primär erst mal nur Vorlagen sind. (Bitte nicht verwechseln mit Templates ins Programmiersprachen wie C++.)
diese Vorlagen dienen dazu, das Design von der grundlegenden Programmlogik zutrennen. Ein sehr einfache Template-Syntax würde in der Regel nur Platzhalter für die Werte enthalten. Komplexere Sprachen, wie z.B. auch XSLT ermöglichen weitere Funktionen.
Und auch Vorlagen, in den PHP-Code verwendet wird, wären Templates. Die Sprache macht ein Template nicht aus. Zur Vereinfachung, vor allem für Designer, wird aber die PHP-Syntax nicht nur beschnitten sondern auch so getrimmt, dass der Code wesentlich schneller geschrieben werden kann. (Smarty, WCF, Flow3) Guten Template-Engines ist dann aber gemein, dass sie, aufgrund der Geschwindigkeit, die Template-Syntax nach PHP übersetzten. Der einfachste Weg, Templates zu nutzen, ist aber ohne Umwege und die direkte Verwendung von PHP-Code!
Daher ist auch deine Aussage falsch und Template-Systeme müssen keine eigene Syntax mit liefern, können aber und können so auch, bei PHP bietet es sich an, Funktionen aus der Programmiersprache weiter leiten. Bei PHP bietet sich dies aus mehren Gründen an, da die Templates, wie erwähnt, aus Geschwindigkeitsgründen ohnehin nach PHP übersetzt werden. Du kannst dich da aber auch gerne mit weit professionelleren Entwicklern, als mit mir, darüber streiten.
Post wurde schon 2x editiert, das letzte mal am 30.07.2012 um 19:43 von Teralios
Danke GameR, dann lieg ich ja doch richtig, dass ne Template-Engine keine Vorteile für mich bietet.
Und ob der Vorteil bei großen Projekten, wo extra Designer angeheuert werden, lohnenswert ist, darüber lässt sich wahrscheinlich noch 20 Jahre streiten.
Ich bin immernoch der Meinung, dass es unnötig ist.
Sehr interessant dazu, hab ich auch noch den hier gefunden:
Der Artikel ist sehr aus der Sicht eines Entwicklers geschrieben und geht auf andere Punkte gar nicht oder vereinfacht es massiv, da er bestimmte Dinge als gegeben sieht, aber die nicht unbedingt so sind. Beispiel mit dem Smarty-PHP-Tag {php}, dieser lässt sich durch aus auch gezielt deaktivieren.
PHP ist durch aus eine Sprache, die man in HTML-Code einbetten kann, damit auch zum Teil Templatesprache, entsprechend aber, für HTML-Ausgaben, viel zu mächtig. Zudem gibt es zwar für bestimmte Schreibformen auch Kurzformen, so mit echo, die aber bestimmten Einstellungen in PHP voraussetzten. Ein <?= funktioniert eben nicht immer.
Eigene Template-Sprachen haben meist 2 Ziele: Erstens den Code lesbarer gestallten, das wird vor allem bei großen Templates mit vielen Variablen durch aus sichtbar, als auch die Sicherheit erhöhen. Das beginnt schon damit, dass bestimmte Funktionen im Template gar nicht ausführbar sind, da sie im Template einfach nicht zur Verfügung stehen. Solche Funktionen sind exec, system oder andere Funktionen, die Zugriff auf die Shell haben, genau so aber auch eval.
Neben diesen Funktionen gibt es zum Beispiel auch verschiedene Sicherheitskonzepte, aber auch Möglichkeiten mit Variablen umzugehen. Gutes Beispiel sind die Indikatoren im WCF. Die Variabel test mit dem Wert "<b>test</b>" wird unterschiedlich behandelt.
Wird im Template {$test} geschrieben, wird auch "<b>test</b>" ausgeben. Die Ausgabe ist aktiv gegen XSS-Geschützt. Wünscht man diesen Schutz nicht, sondern möchte gezielt HTML in einer Variable ermöglichen, schreibt man {@$test}. Nun ist die Ausgabe "test".
Da neben gibt es auch den Indikator #, der Zahlen passend formatiert. Die Schreibarbeit wird so stark minimiert.
Natürlich kann man jetzt Streiten, ob eine XSS-Verhinderung in der Programmlogik statt finden muss oder im Template, ich bin eher für letzteres, da man so auch schnell mal das Ausgabeformat ändern kann, ohne dass man jeden Controller noch mal neu schreiben muss oder den Controller unnötig aufbläht durch Vergleiche.
Der Artikel ist durch aus nicht schlecht, aber sehr einseitig und er vermeidet es, durch aus vorhandene, Vorzüge solcher System aufzuzählen, und macht seinen Beitrag dadurch auch angreifbar.