PHP Klassen - Template {}

Hallo liebe Community,

ich stecke z.Z. einfach fest und habe irgendwie einen Denkfehler
Mein Problem:

Ich habe eine tolle PHP Template Klasse:
Code:
<div id="wrapper">
<div id="header-top">{header-top}</div>
<div id="wrapper-inside">
<div id="header">{header}</div>
<div id="nav">{nav}</div>
<div id="content">{content}</div>
<div id="sidebar">{sidebar}</div>
</div>
<div id="footer">{footer}</div>
</div>
Die sieht so aus, mit meinen Script kann ich nun die geschweifeten Klammern durch Dateien füllen. Alles schön und gut, die Dateien werden leider als String ausgelesen und mein riesen Problem ist es, dass ich in manchen Dateien noch PHP befehle brauche. Die ich aber leider nicht benutzen kann da sie als String nur ausgelesen werden und eingefügt sind.

Ich denke, dass ist einfach nur eine Kleinigkeit, aber ich komme einfach nicht zur Lösung. Hat jemand von euch ein Tipp, wie ich den Code, der als String importiert wird, noch ausführen kann?

Achja, dies ist der Code mit dem ich die Dateien aufrufe (index.php)
Code:
$footer     =     file_get_contents("template/natur/footer.tpl");
$header_top =     file_get_contents("template/natur/header-top.tpl");
$header     =     file_get_contents("template/natur/header.tpl");
$nav        =    file_get_contents("template/natur/nav.tpl");
$sidebar    =    file_get_contents("template/natur/sidebar.tpl");

$tmp->setContent('header-top', $header_top);
$tmp->setContent('header', $header);
$tmp->setContent('nav', $nav);
$tmp->setContent('content', $content);
$tmp->setContent('sidebar', $sidebar);
$tmp->setContent('footer', $footer);

echo $tmp->vorlage;
Vielen Dank
Mani
 
Schau dir mal die Funktion eval() an.
Aber stelle sicher, dass du nicht irgendwelche User-Eingaben mit durch eval() schickst, sonst wird eval() ziemlich evil ;)
 
das hatte ich schon ausprobiert, leider vergeblich da ich immer eine fehlermeldung bekam.

Code:
[B]Parse error[/B]:  syntax error, unexpected T_STRING in [B]/mnt/web1/62/36/52512036/htdocs/index.php(24) : eval()'d code[/B] on line [B]1[/B]
 
Dieht für mich aus, als wenn du da Sonderzeichen ala " und ' nicht oder falsch maskieren würdest. Versuch mal die Anführungszeichen, in dem ausführbaren Teil der Datei, mit HTML-Entities zu maskieren, solllte dann denke ich klappen :)
 
hmmm, bei mir geht gerade garnichts mehr
:D glaube 5 tage durch arbeiten ist einfach zu viel ^^.

um es einfach zu halten, könnt ihr mir anhand diesem beispiels

Code:
$footer     =     file_get_contents("template/natur/footer.tpl");
$header_top =     file_get_contents("template/natur/header-top.tpl");
$header     =     file_get_contents("template/natur/header.tpl");
$nav        =    file_get_contents("template/natur/nav.tpl");
$sidebar    =    file_get_contents("template/natur/sidebar.tpl");

$tmp->setContent('header-top', $header_top);
$tmp->setContent('header', $header);
$tmp->setContent('nav', $nav);
$tmp->setContent('content', $content);
$tmp->setContent('sidebar', $sidebar);
$tmp->setContent('footer', $footer);

echo $tmp->vorlage;
sagen wo ich evil einbauen muss und wie das zum schluss auch der php code ausgeführt wird.
ich wäre euch sehr verbunden.
 
Hallo, mit eval() kommst du an dieser Stelle nicht weit, wenn deine Strings keinen PHP-Code , sondern hauptsächlich Ausgabetext (mit ein paar PHP-Scripting-Tags) enthält.
Du musst es irgendwie schaffen, deine Strings vom PHP-Interpreter ausführen zu lassen.

Das einfachste wäre es natürlich, wenn du statt irgendwelchen Template-Systemen die Ausgabeseite direkt durch den Interpreter jagst und an den entsprechenden Stellen einen PHP-include (include 'header.php';) ausführst, wie das ursprünglich von PHP vorgesehen war.

Da das offenbar nicht geht, musst du die einzelnen Strings sonst irgendwie durch den Interpreter bekommen.
Dazu kannst du die Ausgabepufferungs-Funktionen benutzen.
Zunächst musst du zu Begin deines Scriptes den Ausgabepuffer aktivieren (da sonst ggf. schon Text an den Client geschickt wird und daher alles nicht mehr funktioniert).

Um jetzt den PHP-Code in einem deiner eingefügten Strings zu ersetzen, gehst du so vor:
1. Speichern des aktuellen Ausgabepuffers in eine Zwischenvariable
2. Leeren (clean, nicht flush) des Ausgabepuffers
3. Anstatt die Zieldatei direkt in einen String zu laden, inkludierst du sie einfach (dadurch wird der PHP-Interpreter deinen Code ausführen
4. Du holst dir den aktuellen Inhalt (= ausgeführeter Code) des Ausgabepuffers in deine String-Variable
5. Du Leerst den Ausgabepufer noch einmal
6. Du schreibst den in (1) gespeicherten Originalinhalt wieder in den Puffer
7. Du kannst jetzt den String in deinem Template ersetzen

Damit du mal siehst, wie das funktionieren kann, zeige ich dir das mal:
Code:
// Am Anfang des Script:
ob_start();

// Strings in Variablen laden ...

// Vorher:
// $footer     =     file_get_contents("template/natur/footer.tpl");
// $header_top =     file_get_contents("template/natur/header-top.tpl");
// $header     =     file_get_contents("template/natur/header.tpl");
// $nav        =    file_get_contents("template/natur/nav.tpl");
// $sidebar    =    file_get_contents("template/natur/sidebar.tpl");

// Nachher:
$buffer_contents = ob_get_contents();

ob_clean();
include("template/natur/footer.tpl");
$footer = ob_get_contents();

ob_clean();
include("template/natur/header-top.tpl");
$header_top = ob_get_contents();

ob_clean();
include("template/natur/header.tpl");
$header = ob_get_contents();

ob_clean();
include("template/natur/nav.tpl");
$nav = ob_get_contents();

ob_clean();
include("template/natur/sidebar.tpl");
$sidebar = ob_get_contents();

ob_clean();
echo $buffer_contents;


$tmp->setContent('header-top', $header_top);
$tmp->setContent('header', $header);
$tmp->setContent('nav', $nav);
$tmp->setContent('content', $content);
$tmp->setContent('sidebar', $sidebar);
$tmp->setContent('footer', $footer);

echo $tmp->vorlage;

mfg, metax.
 
Hallo,
eval ist evil, also nicht verwenden.

Ich kann dir nur empfehlen, eine fertige Template-Engine, wie z.B. Smarty, zu verwenden. Bei größeren Projekten macht sich das auf alle Fälle bezahlt.


Gute Template-Engines sollten dann eigentlich auch include() im Template selber erlauben.
 
Danke für den Tipp,

fertige Template-Klassen/Engine verwende ich aus dem Grund nicht, da es mir wichtig ist, Produkte die ich verkaufe selber Programmiert und entwickelt zu haben.

Vorteile?

-Lernfaktor(!!!)
-Rechtlich abgesichert
-Verstehe den Code zu 200%

--------------------------------

Wäre sicher noch eine sehr gute Funktion, das mein Template System die include() Funktion erlaubt, bzw. es damit möglich ist.
 
Ich kann dir nur empfehlen, eine fertige Template-Engine, wie z.B. Smarty, zu verwenden.
Und ich kann dir davon nur abraten, die sogenannten "Template Engines" implementieren ihre eigenen Sprachkonstrukte, die noch nichtmal einfacher sind, als ihre Entsprechungen in php, "on-top". Der Mehrwert liegt gefühlt bei 0, der Overhead dafür ist gigantisch.

Eine meiner Websites, die im Template lediglich php's Kontrollflusselemente enthält und Werte ausschreibt, wird in ~32ms generiert, Smarty benötigt dazu ~400ms. Dafür darf ich dann {title} statt <?=$title?> schreiben.
 
:-P in meinen template darf man {title} schreiben und es besteht nur aus 100 zeilen code :) mit einem geschwindkeits verlust von 5ms~ :)
glaube ich sollte es mal zum kauf anbieten :D *g*
 
Und ich kann dir davon nur abraten, die sogenannten "Template Engines" implementieren ihre eigenen Sprachkonstrukte, die noch nichtmal einfacher sind, als ihre Entsprechungen in php, "on-top". Der Mehrwert liegt gefühlt bei 0, der Overhead dafür ist gigantisch.

Eine meiner Websites, die im Template lediglich php's Kontrollflusselemente enthält und Werte ausschreibt, wird in ~32ms generiert, Smarty benötigt dazu ~400ms. Dafür darf ich dann {title} statt <?=$title?> schreiben.

Aus diesen Grund hab ich mir dann auch meine eigene Template-Engine geschrieben. Ob ich jetzt {title} oder <?=$title?> schreibe ist mir eigentlich Wurst, solange der HTML-Code fein aufgeräumt ist ;-)
 
Eine meiner Websites, die im Template lediglich php's Kontrollflusselemente enthält und Werte ausschreibt, wird in ~32ms generiert, Smarty benötigt dazu ~400ms. Dafür darf ich dann {title} statt <?=$title?> schreiben.

Ich kenn mich mit Smarty im speziellen nicht aus, da ich für meine Anwendungen eine selbstentwickelte, recht umfangreiche Engine nutze und die ich damals speziell auf meine Art von Anwendung zugeschnitten habe.

Allerdings, was viele vergessen, ist das Caching unglaublich wichtig ist bei einer Template-Engine und das Maß der Dinge bzgl. Performance ist.

Gute Template-Engines übersetzen das Template in PHP-Code und speichern diesen in einem Cache-Ordner. Sofern sich das Template nicht verändert, wird einfach nur per include() die Datei aus dem Cache-Ordner geladen und dargestellt.

Stelle ich bei meiner Engine das Caching aus, dauert es doch erheblich bis die Seite geladen ist. Mit Caching läuft das ganze aber rasend schnell.


So lässt sich evt. auch die 400ms bei Smarty erklären. War dort das caching evt. deaktiviert? Oder war dies der erste Aufruf der Seite, bei dem die ganzen Templates erstmals übersetzt werden müssen?



Viele selbstentwickelte Template-Engines ignorieren dies komplett und parsen das Template bei jedem neuen Aufruf, was bei ansteigendem Funktionsumfang immer langsamer wird.

Das
PHP:
ob_clean();
include("template/natur/header.tpl");
$header = ob_get_contents();
könnte man wahrscheinlich deutlich effizienter lösen, in dem im kompilierten Template dann später schlicht <?php include('datei.php'); ?> steht.
 
Der Test war tatsächlich ohne Caching, allerdings hatte das den Grund, dass beinahe im minutentakt Änderungen an der DB erfolgten, die Auswirkungen auf den Inhalt der Seite hatten (und damit die Seiten sowieso ständig verdrängt würden). Allerdings parst ja meine "Lösung" auch bei jedem Aufruf die ganze Seite, und ist doch mehr als Faktor 10 schneller..

Die Effizienz des Caches sinkt ja gerade mit der Häufigkeit der Änderungen und steigt vor allem mit der Komplexität des Codes der Seite. In meinem Fall lassen sich auch im Idealfall nicht mehr als diese ~32ms einsparen, das ist höchstens eine RTT (CPU-Last spare ich auch kaum ein).

Insofern hab ich bei Template Engines immer ein "Mit Kanonen auf Spatzen"-Gefühl, gerade was die inflationäre Verwendung angeht. Wenn Performance-Probleme eintreten, macht es natürlich Sinn, über Caches und als Konsequenz evtl. vorgefertige Template Engines nachzudenken, aber bis zu diesem Zeitpunkt bekommt man auch ohne sie eine saubere Code/HTML-Trennung hin.
 
Warum will man z.B. eine Schleifen mit Pseudocode machen, wenn man die gleiche Schleifen in PHP machen kann? Irgendwie gibt es eine Grosse Zahl von Programmierern, die meinen, dass man HTML von PHP trennen muss. Falsch!
Man muss die Geschäftslogik, von der Ausgabelogik trennen, und wenn man für eine Ausgabelogik Schleifen und den ganzen Kram braucht, dann macht das doch ruhig mit PHP.
Es ist allen langsam klar geworden, dass HTML ohne zusätzliche Schleifen und if-Abfragen heute nicht mehr wirklich funktionieren kann. Wenn das aber die bittere Realität ist, warum muss man dann eine neue Sprache entwickeln, wenn man schon PHP zur Hand hat?
Die frei erfundene Geschichte, dass Designer Smarty-Code besser als PHP-Code verstehen, ist schlicht eine Lüge und {varname} ist genaus so verständlich wie <?=$varname ?>, aber die meiste Designer verstehen eben beides nicht.

In meinen Augen macht es kaum Sinn eine Scriptsprache wie PHP durch eine neue Scriptsprache, die mit PHP geparst werden muss um dann wieder zu PHP zurück zukehren, zu ersetzen.

http://articles.sitepoint.com/print/beyond-template-engine
 
Eben. PHP ist schließlich selbst eine Template-Sprache.

In neueren Projekten mache ich auch die Ausgabetemplates in PHP. Nur die Berechnungen für die auszugebenden Daten (also die Business-Logik) sollte vorher an anderer Stelle geschehen.
Normalerweise läuft das bei mir so:
1. Der Request landet bei einer zentralen Dispatcher-Stelle, die die Engine hochfährt, die Caches lädt und die nötigen Klassen einbindet.
2. Aus dem Request wird abgelegen, welcher Handler den Request verarbeiten soll und dieser wird ausgerufen
3. Der Handler hat Zugriff auf die zentrale Datenstruktur, die alle Sachen wie Authemtifizierung, Datenbankzugriff und so übernimmt.
4. Der Handler berechnet aus den Daten alle nötigen Ausgabewerte.
5. Das Ausgabetemplate für diesen Handler wird aufgerufen und zeigt die Ausgabedaten in der richtigen Maske an.

Dadurch braucht man keine Template-Sprache, sondern muss nur im Template die Ausgabedaten ausgeben. Schleifen und Conditions sind dann auch kein Problem.
BTW: Das Standardmodell in Java (über die JSP-Templates) läuft genauso.
Du hast erst ein Java-Servlet, dass die Geschäftslogik vollzieht und die Ergebnisse als Java-Beans (serialisierbare Datencontainer) in den Speicher legt (in den Request, die Session oder global) und dann die Ausgabe über JSPs (vom Format so ähnlich wie PHP), welche dann diese nur noch ausgaben müssen.
Damit lassen sich auch super so Model-View-Controler (MVC) Entwurfsmuster realisieren: Die Datenbans sind das Datenmodell, das Servlet übernimmt den Controller und die JSP ist das "View", also die Ausgabe.

mfg, metax.
 
Zurück
Oben