Erstellen einer Flat-File-Blog-Engine mit Slim
German (Deutsch) translation by Valentina (you can also view the original English article)



In diesem Artikel erfahren Sie, wie Sie mit dem Slim-Framework eine Flatfile-Blog-Engine in PHP erstellen. Wenn Sie den Jargon nicht verstehen, machen Sie sich keine Sorgen. Wir werden einfach eine spartanische Blogging-Anwendung erstellen, die Textdateien anstelle einer Datenbank zum Speichern von Daten verwendet.
Wenn Sie ein Anfänger sind, ärgern Sie sich nicht! Wir beginnen mit den Grundlagen der Verwendung von Slim. Fangen wir nach dem Sprung an!
Einführung
Slim ist ein leichtes RESTful PHP-Framework zum Erstellen einfacher Websites. Es ist inspiriert von Sinatra, einem in Ruby geschriebenen Framework. Slim wird mit einigen minimalen Komponenten wie
Request, ResponseundViewgeliefert, die die einzigen erforderlichen Komponenten in unserer Flat-File-Blog-Engine sind.
Schritt 1: Erste Schritte
Lassen Sie uns zunächst eine Hallo-Welt-Anwendung einrichten. Zuvor müssen Sie das Slim-Framework auf Ihr System herunterladen. Wir werden nicht viel über Slim diskutieren, da es hier bei Nettuts+ bereits behandelt wurde. Idealerweise sollten Sie die folgenden Dateien in Ihrem Ordner haben:
-
Slim/- schlankes Gerüst -
Index.php- Die Indexdatei -
.htaccess- Zum Umschreiben von URLs
Öffnen Sie nun index.php, wo Sie im folgenden Abschnitt eine Reihe von HTML sehen. Ich habe alles entfernt und durch "Hallo Welt" ersetzt. Ihre index.php sollte jetzt hoffentlich so aussehen.
1 |
require 'Slim/Slim.php'; |
2 |
$app = new Slim(); |
3 |
$app->get('/', function () { |
4 |
echo "<h1>Hello world</h1>"; |
5 |
});
|
6 |
$app->run(); |
Ich habe auf meinem Computer einen Virtualhost erstellt. Dies ist die im Screenshot gezeigte URL. Passen Sie die URL basierend auf der Position von Slim auf Ihrem Computer an.
Navigieren Sie zur URL und Sie sehen eine Startseite mit dem Text "Hallo Welt".


get() ist eine Slim-Methode, die als erstes Argument eine Route und als letztes eine entsprechende Rückruffunktion verwendet. Außer get können wir auch Routen für die Verben POST, PUT und DELETE haben. Da Slim PHP 5.3 unterstützt, kann und wird die Rückruffunktion als anonyme Funktion geschrieben.
Schritt 2: Rendern Sie eine PHP-Seite
Der nächste Schritt ist das Rendern einer PHP-Datei. Bevor wir fortfahren, erstellen Sie ein Verzeichnis namens templates, in dem alle unsere Vorlagendateien gespeichert werden. Alle statischen HTML- oder Vorlagendateien, die wir erstellen, werden in diesem Ordner abgelegt. Mit Slim können wir den Pfad zu unseren Vorlagendateien in der Konfiguration angeben. Wir können eine Konfiguration wie unten gezeigt hinzufügen.
1 |
$app->config(array( |
2 |
'templates.path' => './templates' |
3 |
));
|
Lassen Sie uns eine About-Seite für unseren Blog erstellen. Erstellen Sie eine PHP-Datei mit dem Namen about.php und legen Sie sie im templates-Ordner ab. Fügen Sie den folgenden Code hinzu:
1 |
<html>
|
2 |
<head>
|
3 |
<title>A Slim Blog engine</title> |
4 |
</head>
|
5 |
<body>
|
6 |
<h1>About page</h1> |
7 |
<p>
|
8 |
This page is an example of static route, rendering a php file. |
9 |
</p>
|
10 |
</body>
|
11 |
</html>
|
Damit Slim eine Anfrage verarbeiten kann, müssen wir eine entsprechende Route definieren, die dieser URL zugeordnet werden kann. In unserem ersten Schritt haben wir dem index eine Route oder '/" hinzugefügt. Fügen wir nun eine weitere Route für unsere About-Seite hinzu.
1 |
$app->get('/about', function () use ($app) { |
2 |
$app->render('about.php'); |
3 |
});
|
Wenn Sie http://slim.local/about in Ihren Browser laden, sollte hoffentlich Folgendes angezeigt werden:


Wir haben der About-Seite eine Route hinzugefügt, auf der about.php unter ./templates angezeigt wird (erinnern Sie sich an die Konfigurationsvariable template.path?). Haben Sie bemerkt, dass wir in der get-Methode use ($app) verwendet haben? Nun, dies ist nur eine Möglichkeit, eine Variable innerhalb einer anonymen Funktion zu verwenden, die außerhalb ihres Gültigkeitsbereichs liegt.
Schritt 3: Der Vorlage Werte zuordnen
Jetzt können wir eine Vorlagenseite für eine Route anzeigen. Es ist an der Zeit, über die Anzeige einiger dynamischer Werte in der Vorlage nachzudenken, da wir möglicherweise nicht ständig statische Dateien rendern und bereitstellen. Mit der render()-Methode können wir Werte zuweisen, die in einer Vorlage gerendert werden sollen. Es sollte als zweiter Parameter als assoziatives Array übergeben werden. Lassen Sie uns den obigen Code so ändern, dass er so aussieht:
1 |
$app->get('/about', function () use ($app) { |
2 |
$data = array( |
3 |
'heading' => 'About page', |
4 |
'message' => 'This page is an example of static route, rendering a php file.' |
5 |
);
|
6 |
$app->render('about.php',$data); |
7 |
});
|
Und ändern Sie den Text der Vorlage ein wenig.
1 |
<body>
|
2 |
<h1><?php echo $heading; ?></h1> |
3 |
<p>
|
4 |
<?php echo $message; ?> |
5 |
</p>
|
6 |
</body>
|
Sie werden feststellen, dass Sie dieselbe Seite sehen können, wenn Sie die vorherige URL neu laden. In der Vorlagendatei verwendete Variablen sind die entsprechenden Schlüssel im assoziativen Array.
Schritt 4: Fügen Sie eine dynamische Route hinzu
Bisher haben wir mit einigen statischen Routen gespielt, '/' und '/ about'. Jetzt erstellen wir eine dynamische Route, d. H. Eine Route, die auf verschiedene URLs reagieren kann.
1 |
$app->get('/:param1/:param2', function ($param1,$param2) use ($app) { |
2 |
echo $param1 .' - ' . $param2; |
3 |
});
|
Slim ruft immer die erste Route auf, die der aktuellen HTTP-Anforderung entspricht. Dies bedeutet, dass alle statischen Routen vor dynamischen Routen definiert werden müssen.
Wenn Sie http://slim.local/first-param/second-param in Ihrem Browser laden, wird first-param-second-param angezeigt.
Die Route einer Variablen muss mit einem ':' beginnen. Slim übergibt den Wert dieser Variablen als Argument an unsere Rückruffunktion, damit wir sie analysieren und eine entsprechende Operation ausführen können. Slim erwartet genau zwei Parameter für die obige Route, da die beiden Routenvariablen obligatorisch sind. Wenn es nicht vorhanden ist, zeigt Slim einen 404-Fehler an. Wir können einen URL-Parameter optional machen, wie im nächsten Schritt gezeigt.
Schritt 5: Optionale Routenparameter
Um einen Routenparameter optional zu machen, schreiben Sie den obigen Code wie folgt um:
1 |
$app->get('/:param1(/:param2(/:param3))', function () use ($app) { |
2 |
$args = func_get_args(); |
3 |
foreach($args as $arg){ |
4 |
echo $arg . ' -- '; |
5 |
}
|
6 |
});
|
Damit sind der zweite und dritte Parameter optional. Wir können die Methode func_get_args() verwenden, um alle Argumente zu erhalten, die an die Rückruffunktion übergeben werden.
Okay, es ist Zeit, sich auf ernsthafte Geschäfte einzulassen. Jetzt haben wir alle erforderlichen Informationen, um eine Flat-File-Blog-Engine zu erstellen. Lassen Sie uns das oben diskutierte Wissen zusammenstellen, um es zu erstellen.
Schritt 6: Erstellen Sie ein Dateisystem
Wir müssen ein Dateisystem erstellen, bevor wir all diese verschiedenen Komponenten zusammenfügen. Hier ist ein einfaches Dateisystem für unsere Anwendung.


Dies ist ein minimalistisches Dateisystem mit nur den erforderlichen Dateien/Ordnern. Alle Artikel werden im articles-Ordner gespeichert. Der assets-Ordner enthält unsere CSS- und JavaScript-Dateien sowie Bilder. Slim enthält die Framework- und Vorlagendateien.
Schritt 7: Fügen Sie eine Route für die Artikelansicht hinzu
Wenn Sie sich etwas verloren fühlen, sehen Sie hier kurz, wie unsere Anwendung aufgebaut ist.
- Der Artikel wird in eine Textdatei mit der URL als Dateinamen geschrieben.
- Unsere Anwendung ordnet URLs entsprechenden Artikeln zu.
- Zur Vereinfachung behalten wir die Metainformationen (wie Autorenname, Datum usw.) eines Artikels in der Textdatei in JSON. Es wird uns helfen, sie mit der in PHP eingebauten Funktion
json_decode()abzurufen. Inhalt und Metadaten werden durch eine Leerzeile getrennt.
Fügen wir eine Route hinzu, die einen Artikel aus dem Artikelordner basierend auf der URL lädt.
1 |
// add article location in configuration
|
2 |
$app->config(array( |
3 |
'templates.path' => './templates', |
4 |
'article.path' => './articles' // location of articles |
5 |
));
|
6 |
// '/post-url' will load post-url.txt file.
|
7 |
$app->get('/:article',function($article) use($app){ |
8 |
$path = $app->config('article.path'); |
9 |
//open text file and read it
|
10 |
$handle = fopen($path . '/' . $article . '.txt', 'r'); |
11 |
$content = stream_get_contents($handle); |
12 |
// split the content to get metadata
|
13 |
$content = explode("\n\n", $content); |
14 |
$rawMeta = array_shift($content); |
15 |
// metadata is json encoded. so decode it.
|
16 |
$meta = json_decode($rawMeta,true); |
17 |
$content = implode("\n\n", $content); |
18 |
$article = array('meta' => $meta , 'content' => $content); |
19 |
$app->render('article.php', $article); |
20 |
});
|
Wir haben eine dynamische Route mit einem einzelnen Routenparameter hinzugefügt. Die Rückruffunktion erhält den Wert für diesen Parameter, bei dem es sich um einen Dateinamen ohne Erweiterung handeln sollte. Als Nächstes extrahieren wir den Wert der Konfigurationsvariablen article.path, in der wir unsere Artikel aufbewahren.
In den nächsten beiden Zeilen lesen wir diese Datei und speichern ihren Inhalt in einer Variablen, $content. Wie bereits im vorherigen Absatz erwähnt, enthält ein Artikel Metadaten und tatsächlichen Inhalt, die durch eine einzelne Zeile ("\n\n") getrennt sind. Oft enthält der Inhalt eines Artikels viele andere Leerzeilen, die wahrscheinlich die aktuelle Methode beschädigen. Um dies zu vermeiden, verwenden wir das erste Element, um Metadaten abzurufen, und verbinden den Rest des Arrays mit derselben Leerzeile. Da die Metadaten im JSON-Format vorliegen, müssen wir sie von hier aus dekodieren und im $meta-Array speichern.
Erstellen Sie eine Vorlagendatei, um einen Artikel zu rendern, und legen Sie ihn im template-Ordner ab.
1 |
//article.php
|
2 |
echo '<h2>' . $meta['title'] . '</h2>'; |
3 |
echo $content; |
Lassen Sie uns jetzt unseren ersten Blog-Beitrag erstellen. Erstellen Sie eine neue Datei mit dem Namen first-article.txt, legen Sie sie im articles-Ordner ab und fügen Sie den Inhalt wie unten gezeigt hinzu. Stellen Sie sicher, dass Metadaten und Inhalt durch eine Leerzeile getrennt sind.
1 |
//first-article.txt |
2 |
{
|
3 |
"title" : "This is my first article", |
4 |
"date" : "02/15/2012", |
5 |
"slug" : "first-article", |
6 |
"author": "Author name" |
7 |
} |
8 |
|
9 |
Fruitcake jelly-o halvah marshmallow bonbon. Croissant candy canes chocolate cake muffin jelly beans liquorice.... (copy paste some lipsum) |


Ausgezeichnet! Sie können jetzt Artikel veröffentlichen. Aber warte! Wir haben noch keine Listingseite. Wir müssen alle in unserem System verfügbaren Artikel mit ihrem Titel und einer kleinen Beschreibung auflisten. Um dies zu erreichen, müssen wir den Artikelordner analysieren, um alle Artikel zu finden und sie einem Array hinzuzufügen, das sie nacheinander liest.
Schritt 8: Erstellen Sie eine Listingseite
1 |
$app->get('/', function() use ($app){ |
2 |
$path = $app->config('article.path'); |
3 |
$dir = new DirectoryIterator($path); |
4 |
$articles = array(); |
5 |
foreach($dir as $file){ |
6 |
if($file->isFile()){ |
7 |
$handle = fopen($path . '/' . $file->getFilename(), 'r'); |
8 |
$content = stream_get_contents($handle); |
9 |
$content = explode("\n\n", $content); |
10 |
$rawMeta = array_shift($content); |
11 |
$meta = json_decode($rawMeta,true); |
12 |
$content = implode("\n\n", $content); |
13 |
$articles[$file->getFilename()] = array('meta' => $meta, 'content' => $content); |
14 |
}
|
15 |
}
|
16 |
$app->render('index.php',array('articles' => $articles)); |
17 |
});
|
Hier haben wir der Startseite eine Route hinzugefügt. Wir verwenden die in PHP integrierte Directoryiterator-Klasse, um jede Datei im Verzeichnis zu durchlaufen. Jeder Artikel wird dem $articles-Array hinzugefügt. Aus der Vorlagendatei (index.php) können wir diese Artikel wie unten gezeigt durchlaufen.
1 |
foreach($articles as $article){ |
2 |
echo "<h1> ". $article['meta']['title'] ." </h1> "; |
3 |
echo substr(strip_tags($article['content']), 0,200) |
4 |
. '... <a href="/' . $article['meta']['slug'] |
5 |
. '">Read more >> </a>'; |
6 |
}
|
Unsere Startseite ist jetzt fertig. Es werden alle Artikel in unserem Blog mit dem entsprechenden Titel und einem Teil des Inhalts aufgelistet.


Schritt 9: Erstellen Sie eine Archivseite
Als nächstes erstellen wir eine 'Archiv'-Seite. Da wir erwarten, dass die Archivseite Filter enthält, die auf Jahr, Monat und Datum basieren, fügen wir eine Route mit optionalen Parametern hinzu. Die Archivseite unterstützt die folgenden URLs.
- /archives
- /archives/yyyy
- /archives/yyyy/mm
- /archives/yyyy/mm/tt
Um dies zu erreichen, laden wir alle Artikel und filtern sie basierend auf den Argumenten, die an die Rückruffunktion übergeben werden. Ich habe alles in eine Klasse verschoben, damit wir unseren Code wiederverwenden können. Eine Route, die die oben genannten URLs unterstützt, sieht ungefähr so aus:
1 |
// assign $this to another variable as it is not supported inside closure
|
2 |
$blog = new Blog(); |
3 |
$slim->get('/archives(/:yyyy(/:mm(/:dd)))', function() use ($blog,$slim) {}); |
Beachten Sie, dass auf dieser Route Jahr, Monat und Datum optionale Parameter sind. /archives ist der einzige erforderliche Teil der URL. Als nächstes müssen wir diese Route implementieren, die basierend auf den optionalen Parametern reagiert.
1 |
$args = func_get_args(); |
2 |
//load all articles
|
3 |
$articles = $blog->loadArticles(); |
4 |
$archives = array(); |
5 |
// check count($args) for optional route params
|
6 |
if(count($args)>0) { |
7 |
switch(count($args)){ |
8 |
case 1 : //only year is present |
9 |
$format = 'Y'; |
10 |
$date = $dateFormat($args,$format); |
11 |
break; |
12 |
case 2 : //year and month are present |
13 |
$format = 'Y-m'; |
14 |
$date = $dateFormat($args,$format); |
15 |
break; |
16 |
case 3 : //year, month and date are present |
17 |
$format = 'Y-m-d'; |
18 |
$date = $dateFormat($args,$format); |
19 |
break; |
20 |
}
|
21 |
// filter articles
|
22 |
foreach($articles as $article){ |
23 |
if($dateFormat($article['meta']['date'], $format) == $date){ |
24 |
$archives[] = $article; |
25 |
}
|
26 |
}
|
27 |
}
|
28 |
else{ |
29 |
$archives = $articles; |
30 |
}
|
31 |
// render archives
|
32 |
$slim->render('archives.php',array('archives' => $archives)); |
In der switch-Anweisung erstellen wir das zu filternde Datum anhand der übergebenen Argumente. Dieses Datum wird mit dem Datum jedes Artikels verglichen. Wenn sie übereinstimmen, wird es dem $archives-Array hinzugefügt. $dateFormat() ist eine anonyme Funktion innerhalb der Route zum Formatieren von Daten.
1 |
$dateFormat = function($args,$format){ |
2 |
$temp_date = is_array($args) ? implode('-', $args) : $args; |
3 |
$date = new DateTime($temp_date); |
4 |
return $date->format($format); |
5 |
};
|
Wir können Bedingungen für eine Route schreiben, die von den Argumenten erfüllt werden sollten, um das Jahr, den Monat und das Datum zu validieren, die an die Route übergeben wurden.
1 |
$slim->get('/archives(/:yyyy(/:mm(/:dd)))', function() use $blog { |
2 |
})->conditions( |
3 |
array( |
4 |
'yyyy' => '(19|20)\d\d' |
5 |
,'mm'=>'(0[1-9]|1[0-2])' |
6 |
,'dd'=>'(0[1-9]|[1-2][0-9]|3[0-1])' |
7 |
));
|
Hier sollte das Jahr mit 19 oder 20 beginnen, gefolgt von zwei beliebigen Ziffern. Der Monat sollte zwischen 1 und 12 liegen und das Datum sollte zwischen 01 und 31 liegen.
Hier ist die Archivseite, die ich mit dem obigen Code erstellt habe. Wenn Sie bemerkt haben, dass ich Twitter Bootstrap zum Anwenden einiger grundlegender Stile verwendet habe, erhalten Sie ein zusätzliches Cookie!


Schritt 9: Würzen Sie es auf
Nun, wir besitzen jetzt ein funktionierendes Modell einer Flat-File-Blog-Engine. Als nächstes müssen wir die Anwendung organisieren, um Codeduplizierungen zu vermeiden und Funktionen wie Kommentieren usw. hinzuzufügen. Verschieben wir diesen Code zur besseren Organisation von index.php in eine separate Klasse.
Bisher haben wir die View-Klasse des Slim-Frameworks verwendet. Wir können eine benutzerdefinierte Ansichtsklasse erstellen, die Slim_View erweitert, um einige zusätzliche Funktionen wie das Festlegen eines Basislayouts, globale Einstellungen usw. hinzuzufügen. Wenn Sie lieber Artikel in Markdown schreiben möchten, können Sie auch einen Markdown-Parser hinzufügen.
Wir sollten uns auch mit der Verbesserung der Ästhetik der Anwendung befassen. Ich bevorzuge die Verwendung von Twitter Bootstrap, da es wirklich sehr einfach zu verwenden und anzupassen ist. Ich denke nicht, dass es eine gute Idee ist, sich hier mit diesen Details zu befassen. Ich habe sie zu einer einfachen Anwendung namens TextPress zusammengestellt, die hier heruntergeladen werden kann.
Einpacken
Fast alle Flat-File-Blog-Engines bevorzugen es, in der Cloud zu leben. Weiteres Git wird höchstwahrscheinlich zum Veröffentlichen von Artikeln verwendet. Mit unserer Engine können Sie Beiträge mit einer einfachen Textdatei erstellen und über die Befehlszeile veröffentlichen. Da es kein zu hackendes Admin-Panel gibt, ist es viel sicherer als fast jedes andere Content-Management-System. Vor allem das Hosting ist einfach, da Plattformdienste wie PHP Fog es uns ermöglichen, Anwendungen frei in der Cloud zu hosten.
Das war's auch schon. Lassen Sie mich wissen, wenn Sie Fragen in den Kommentaren unten haben und vielen Dank für das Lesen!



