Datenbank-Struktur
2008-11-04Die Datenbank soll alle dynamischen Inhalte (Content) aufnehmen und hat folgenden Struktur:
CREATE TABLE cms4ds_content ( Content_ID int(11) NOT NULL auto_increment, TS timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, Titel varchar(200) collate latin1_general_ci NOT NULL, Titel_Datum datetime default NULL, Hide_Date char(1) collate latin1_general_ci default NULL, Content varchar(32000) collate latin1_general_ci default NULL, Rubrik varchar(200) collate latin1_general_ci default NULL, Sequence int(11) default NULL, Comments char(1) collate latin1_general_ci default NULL, PRIMARY KEY (Content_ID) )
Die einzelnen Spalten kurz erläutert:
- Content_ID ist ausschließlich zur besseren Verarbeitung angelegt und ist der Primär-Schlüssel
- TS führt den Zeitstempel bei Änderungen mit; wird nicht direkt genutzt
- Titel enthält den Titel eines Inhaltsbeitrags (Posts)
- Titel_Datum enthält das veröffentliche Datum und wird als zweiter Sortierbegriff bei der Anzeige der Beiträge genutzt. Es wird absteigend sortiert, d. h. das jüngste Titel_Datum steht an erster Stelle. Die kann man für einen Blog nutzen.
- Hide_Date ist ein Schalter, er wenn er auf 'y' steht, das Titel_Datum in der Ausgabe unterdrückt
- Content enthält den eigentlichen Inhalt des Beitrags
- Rubrik kann mehrer Werte durch Leerstellen getrennt enthalten. Steuert die jeweilige Seitenanzeige, d. h. alle Beiträge einer Rubrik werden auf einer Seite angezeigt
- Sequence kann eine Zahl enthalten, die als erster Sortierbegriff bei der Anzeige der Beiträge genutzt wird. Es wird aufsteigend sortiert.
- Comments kann ein Zeichen enthalten. Wenn ein Zeichen eingegeben wird (z. B. 'y'), dann wird die Kommentierungs-Funktionalität für diesen Beitrag eingeschaltet. Bei 'g' wird die einleitende Überschrift 'Kommentare' nicht ausgegeben (sinnvoll für z. B. eine Gästebuch).
Datenbank-Konnektion
2008-11-05In der Datei cms4ds.php.inc wird die Datenbank-Konnektion festgelegt. Hier müßte man auch Anpassungen vornehmen, wenn Benutzer, Kennwort, Datenbank-Server und Datenbank anders lauten.
<?php
$conn = @mysql_connect("localhost","root");
mysql_select_db("cms4ds",$conn);
$editor='cms4ds_editor.php?action=';
?>In den php-Dateien (z. B. cms4ds.php, cms4ds_editor.php, cms4ds_rss.php), in denen ein Datenbankzugriff erfolgt, wird diese Datei dann per require eingebunden.
Der Pfad für den Seiten-Editor kann man auch in dieser Datei anpassen.
Datenbank-Abfrage
2008-11-05In dem PHP-Skript cms4ds.php wird die Datenbank-Abfrage ausgeführt:
<?php
function iso8859_mydecode($html){ // simple translation of german letters
$a = array('ä'=>"xC3xA4",'ö'=>"xC3xB6",'ü'=>"xC3xBC",
'Ä'=>"xC3x84",'Ö'=>"xC3x96",'Ü'=>"xC3x9C",'ß'=>"xC3x9F");
return strtr($html,$a);
}
function utf8_mydecode($html){ // reverse simple translation of german letters
$a = array("xC3xA4"=>'ä',"xC3xB6"=>'ö',"xC3xBC"=>'ü',
"xC3x84"=>'Ä',"xC3x96"=>'Ö',"xC3x9C"=>'Ü',"xC3x9F"=>'ß');
return strtr($html,$a);
}
$t0=sscanf(microtime(),"%f %s");
require "cms4ds.php.inc";
$where=
preg_replace('/([^a-zA-Z%'0-9äöüÄÖÜß_(), ])/','',utf8_mydecode($_REQUEST['where']));
$recs = mysql_query("select * from cms4ds_content where find_in_set('"
.$where."',replace(Rubrik,' ',',')) order by Sequence, Titel_Datum desc");
$out='';
while ($rec = mysql_fetch_assoc($recs)) {
$out.='<div class="content" style="display:block"><h3 onclick="bookmark(''
.$rec['Titel'].'')">'.$rec['Titel'].'</h3>'
.($rec['Hide_Date']=='y'?'':'<i>'.substr($rec['Titel_Datum'],0,10))
.($rec['Autor']==''?'':' - ').$rec['Autor'].'</i><p>'.$rec['Content'].'</p>';
if (substr($_SERVER['REMOTE_ADDR'],0,7)=='192.168') {
$out.='<p style="position:absolute;top:150px;margin-left:-50px">'
.'<a target="_blank" onclick="window.open(''.$editor
.'new','','top=200,left=300,width=600,height=700')">new/lt;/a><br/>'
.'<a target="_blank" onclick="window.open(''.$editor
.'search&Content_ID='.$rec['Content_ID']
.'','','top=120,left=250,width=616,height=540')"%gt;edit</a></p>';
}
$out.='</div>';
}
@mysql_close($conn);
$t1=sscanf(microtime(),"%f %s");
print $out;
?>
<!--#set var="t" value="<?php print 'PHP: '.($t1[0]-$t0[0]).' sek. | ' ?>" -->
Zunächst zwei einfache Zeichen-Code-Umwandlungs-Hilfsfunktionen.
Die Variable $t0 wird mit einem Zeitstempel geladen, wie auch später die Variable $t1, um den Datenbank-Abfrage-Teil hinsichtlich seiner Dauer messen zu können. Diese wird dann in der letzten Zeile berechnet und in eine Rückgabe-Variable ableglt.
Der Abfrage-Inhalt wird auf problematische Inhalte (Sonderzeichen) untersucht und falls welche vorliegen, werden diese entfernt.
Die eigentliche Datenbank-Abfrage schließt sich an. Hierbei wird eine spezielle Abfrage verwendet (find_in_set), die es erlaubt, auch mehrere Rubriken in einem Beitrag zu unterschiedlichen Seiten zu laden. Die Sortierung (order by) erfolgt zweistufig: Sollte das Sequence-Feld vorliegen, wird zuerst danach aufsteigend sortiert; wäre das Sequence-Feld immer gleich (oder NULL), dann würde ausschließlich nach dem Titel_Datum absteigend sortiert werden.
Alle Beiträge werden in folgender Struktur ausgegeben:
<div class="content" style="display:block" >
// damit auch ein Bookmark-Integration erfolgen kann, wird der Titel hierfür vorbereitet
// bookmark()-Funktion wird unter javascript erläutert
<h3 onclick="bookmark('Titel')">Titel</h3>
//falls das Hide_Date ungleich y ist, dann wird zudem das Titel_Datum ausgeben
//falls der Autor existiert wird er auch mit ausgegeben, getrennt mit einem '-'
<i>Titel_datum - Autor</i>
<p>Content</p>
//falls die Ausgabe im lokalen Netz erfolgt (Adress-Raum 192.168.x.x),
//dann wird der Editor-Aufruf eingebaut
<p style="position:absolute;top:150px;margin-left:-50px">'
.'<a target="_blank" onclick="window.open(''.$editor.'new','','top=200,
left=300,width=600,height=700')">new</a><br/>'
.'<a target="_blank" onclick="window.open(''.$editor.'search&Content_ID='
.$rec['Content_ID'].'','','top=120,left=250,width=616,height=540')">edit</a></p>
</div>
Logfile-Datenbank
2008-11-05Die Logfile-Datenbank-Tabelle hat den folgenden Aufbau:
CREATE TABLE cms4ds_log ( Log_ID int(11) NOT NULL auto_increment, TS timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, IP varchar(15) collate latin1_general_ci NOT NULL, REFERER varchar(100) collate latin1_general_ci default NULL, USER_AGENT varchar(100) collate latin1_general_ci default NULL, `Page` varchar(120) collate latin1_general_ci default NULL, PRIMARY KEY (Log_ID) )
Das PHP-Skript cms4ds_log.php hat die Aufgabe, die User-Zugriffe zu protokollieren:
<?php
if (empty($_SERVER['HTTP_REFERER'])) die("Ein Fehler ist aufgetreten!");
else {
$url = parse_url($_SERVER['HTTP_REFERER']);
if ($url['host']!= $_SERVER['SERVER_NAME']) die("Ein Fehler ist aufgetreten!");
}
require "cms4ds.php.inc";
$fields=$_SERVER['REMOTE_ADDR']."','".$_SERVER['HTTP_REFERER']."','"
.$_SERVER['HTTP_USER_AGENT']."','".$_REQUEST['loc'];
mysql_query("insert into cms4ds_log (IP,REFERER,USER_AGENT,Page) "
."values ('".$fields."')");
$recs=
mysql_query("select substring(TS,1,13) as c from cms4ds_log group by IP,
substring(TS,1,13)");
$count = mysql_num_rows($recs);
print $count;
@mysql_close($conn);
?>
Das Skript wird in der Funktion index() wie folgt aufgerufen:
myXMLHTTPRequest.open("GET", "cms4ds_log.php?loc="
+location.pathname+location.search, false);
myXMLHTTPRequest.send(null);Datenbank-Struktur für Kommentare
2009-05-06Für die Kommentierungs-Funktion wird eine eigene Tabelle verwendet.
CREATE TABLE cms4ds_comments ( Comment_ID int(11) NOT NULL auto_increment, TS timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, Content_ID int(11) NOT NULL, Autor varchar(32) collate latin1_general_ci default NULL, Email varchar(128) collate latin1_general_ci NOT NULL, Content varchar(3000) collate latin1_general_ci default NULL, IP varchar(15) collate latin1_general_ci default NULL, PRIMARY KEY (`Comment_ID`) ) AUTO_INCREMENT=1 ;
Die einzelnen Spalten kurz erläutert:
- Comment_ID ist ausschließlich zur besseren Verarbeitung angelegt und ist der Primär-Schlüssel
- TS führt den Zeitstempel bei Änderungen mit; wird nicht direkt genutzt
- Content_ID ist der Fremdschlüssel (Link) auf die cms4ds_content-Tabelle
- Autor enthält den Namen des Kommentators
- Email enthält die E-Mail-Adresse des Kommentators. Wird zur Zeit nicht weiter genutzt
- Content enthält den eigentlichen Inhalt des Beitrags
- IP enthält die IP-Adresse des Kommentators und wird abgespeichert, um zu verhindern, dass jemand Kommentare spammt. Eingestellt ist per PHP-Skript, dass erst nach 300 Sekunden ein neuer Beitrag eingegeben werden darf
Kommentar-Funktionalität
2009-05-06Die Kommentar-Funktionalität wird in der Datei cms4ds.php integriert:
... } if ($rec['Comments']!='') $out.=comments($rec['Comments'],$rec['Content_ID']); $out.='</div>'; } ...
Die Funktion comments() bekommt den Kommentar-Typ-Schalter und die Beitrags-ID als Parameter mit. Sie sucht nach vorhandenen Kommentare, gibt sie aus und bietet in einem iframe die Möglichkeit an, neue Kommentare zu verfassen:
function comments($type,$id){
if ($type == 'g') $out='';
else $out='<h4 style="margin-bottom:15px">Kommentare</h4>';
$recs = mysql_query(
"select * from cms4ds_comments where Content_ID ='".$id."' order by TS");
while ($rec = mysql_fetch_assoc($recs))
$out.='<div style="margin-bottom:5px;border-bottom:1px dotted #69c;'
.'padding-bottom:5px">von <b>'.$rec['Autor']
.'</b> am '.substr($rec['TS'],0,16).'<br/>'.bb($rec['Content']).'</div>';
$out.='<iframe src="cms4ds_comment.php?Content_ID='.$id.'" width="97%" height="238px"
marginheight="0" marginwidth="0" frameborder="0"></iframe>';
return $out;
}
Im iframe wird die Datei cms4ds_comments.php geladen, die die Ausgabe der Kommentareingabefelder, das Prüfen und Abspeichern übernimmt. Verschieden Funktionen überprüfen die Eingaben, und das Zeitverhalten in Relation zur letzten Eingabe, um Spam und Hacks zu verhindern. Eine Vorabansicht wird per Doppelklick ins Kommentarbeitragsfeld via Javascript angeboten. Hierbei werden auch Vorsorgemaßnahmen (HTML-Tag-Ersetzung) vorgenommen.
Über den Kommentar-Typ könnten man auch weitere Ausgabesteuerungen vornehmen, z. B. auch, dass zwar Kommentare angezeigt, aber keine weiteren mehr erfasst werden dürfen; also so etwas wie das Schließen einer Beitrags-Kommentierung herbeiführen.