Volltextsuche in einer Text-Datei

Volltextsuche-Tutorial in PHP von Daniel Schwamm (26.02.2009)

Inhalt

1. Einführung

Wir betrachten hier ein Ein-Seiten-Script in PHP, mit dessen Hilfe eine kleine Datenbank in Form einer Text-Datei nach beliebigen Text-Passagen durchsucht werden kann. Der Suchbegriff lässt sich auf der Webseite über eine Form-Variable eingeben und die gefundenen Datensätze werden anschliessend in formatierter Weise ausgegeben.

2. Die Prominenten-Datenbank

Folgende Text-Datei "daten.txt" mit einer kleinen Promi-Datenbank sei gegeben:

00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
1;Musiker;Queen;GB;queen.jpg
2;Musiker;Billy Idol;GB;billy-idol.jpg
3;Musiker;Eminem;USA;eminem.jpg
4;Schauspieler;Kate Winslet;GB;kate-winslet.jpg
5;Schauspieler;Brad Pitt;USA;brad-pitt.jpg;
6;Angelina Jolie;Brad Pitt;USA;angelina-jolie.jpg
7;Musiker;Kate Bush;GB;kate-bush.jpg
8;Schauspieler;Kate Beckinsale;GB;kate-beckinsale.jpg
9;Schauspieler;Alyssa Milano;USA;alyssa-milano.jpg
10;Schauspieler;Rose McGowan;USA;rose-mcgowan.jpg
11;Schauspieler;Winona Ryder;USA;winona-ryder.jpg
12;Moderator;Guelcan Kamps;Deutschland;guelcan-kamps.jpg
13;Moderator;Collien Fernandes;Deutschland;collien-fernandes.jpg
14;Musiker;Britney Spears;USA;britney-spears.jpg
15;Musiker;Christina Aguilera;USA;christina-aguilera.jpg
16;Schauspieler;Charlize Therone;Suedafrika;charlize-therone.jpg
17;Musiker;Kylie Minogue;Australien;kylie-minogue.jpg

Jede Zeile entspricht einem Datensatz. Jeder Datensatz besteht wiederum aus 5 Feldern, die durch den Delimiter ";" abgegrenzt werden. Diese Felder enthalten jeweils "ID", "Kategorie", "Namen", "Land" und "Bild-Namen" eines Promis.

3. Der Script-Ablauf

Der Algorithmus des Scripts verfährt folgendermassen:
  • Wir holen uns den Wert der CGI-Variable "volltext" in "$volltext"
  • Die Variable "$ergebnis" wird auf Nichts gesetzt
  • Ist "$volltext" nicht leer, dann
    • öffnen wir die Text-Datei "daten.txt"
    • Wir durchlaufen sie zeilenweise, speichern den String in "$zeile"
    • Wir prüfen, ob "$volltext" in "$zeile" enthalten ist
    • Ist dem so, dann
      • spalten wir "$zeile" in ein Array "$zeile_ar" auf
      • wir füllen "$ergebnis" mit den Array-Werten aus "$zeile_ar"
    • Sind alle Datensätze fertig, schliessen wir "daten.txt" wieder
  • Wir geben die HTML-Form aus mit der INPUT-Variable "volltext"
  • Falls "$ergebnis" ungleich Nichts ist, hängen wir es hinten dran

Das Script behandelt also die alles entscheidende CGI-Variable "volltext" wie einen Parameter, der an eine gewöhnliche Funktion übergeben wird. Der Submit-Button der HTML-Form bewirkt einen quasi rekursiven Aufruf der Funktion, indem die PHP-Seite neu geladen wird.

4. Der Script-Source

Der Script-Source wird in der Datei "script.php" gespeichert. Aufgerufen wird das Programm dann wie eine gewöhnliche HTML-Datei mit einem Browser. Es muss jedoch eine gültige URL angegeben werden. Als lokale Datei funktioniert es nicht, da zur Interpretation der PHP-Befehle ein Web-Server benötigt wird.

00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>
<HTML>
<HEAD>
<META NAME='ROBOTS' CONTENT='INDEX, FOLLOW, ARCHIVE'>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=windows-1252'>
<TITLE>www.daniel-schwamm.de - PHP-Tutorials - Volltext-Suche in einer Text-Datei - Demo</TITLE>
<META name='author' content='Daniel Schwamm'>
<META name='Description' content='Demo zur Volltext-Suche in PHP: Positionen in Mini-Datenbank per Volltext-Suche ohne MySQL selektieren'>
<META name='Keywords' content='Software, Tutorial, PHP, Volltext, Suche, Textdatei, MySQL, Demo, Mini-Datenbank'>
<LINK rel='canonical' href='http://www.daniel-schwamm.de/loader.php?fn=php-tutorials/volltext-suche/script.php'>
</HEAD>

<?PHP
/*
Created 24.02.2009 09:36:23 by dirty DanPHPEd V2.2.5

volltext-such-demo von daniel schwamm

Aufbau der datenbank-tabelle: daten.txt

  ID; Kategorie; Name;       Land; Bild
  --------------------------------------------
  1;  Musiker;   Queen;      GB;   queen.jpg
  2;  Musiker;   Billy Idol; GB;   billy-idol.jpg
  ...
*/

//hole dan-hilfsfunktionen
include "../help-functions/dan-service.php";

//hole cgi-variable volltext.
//falls nicht vorhanden, setze volltext auf 'kate'
$volltext=dan_cgivar_get('volltext','kate');

$datensatz_c=0;
$ergebnis="
  <P style='text-align:center;'>
  <B>Kein Suchbegriff angegeben!</B>
  </P>
"
;
if(
$volltext<>'')
{
  
//volltext vorhanden
  
$treffer_c=0;
  
$ergebnis="";

  
//datenbank oeffnen
  
$datei=fopen("daten.txt",'r') or die ("Kann Datei 'daten.txt' nicht lesen.");

  
//durchlaufe datenbank zeilenweise
  
while(!feof($datei))
  {
    
//lese eine zeile ein
    
$zeile=trim(fgets($datei,1024));
    
$datensatz_c++;

    
//taucht volltext in zeile auf?
    //volltext und zeile werden in kleinschrift umgewandelt
    //sodass nicht zwischen gross-/kleinschreibung unterschieden wird
    
if(strpos(strtolower($zeile),strtolower($volltext))===false)
    {
      
//nein, also zeile ignorieren
      
continue;
    };

    
//ok, volltext in zeile gefunden

    //zeilen-string in zeilen-array umwandeln
    
$zeile_ar=explode(";",$zeile);

    
//die spalten-werte in variable packen
    
$id       =$zeile_ar[0];
    
$kategorie=$zeile_ar[1];
    
$name     =$zeile_ar[2];
    
$land     =$zeile_ar[3];
    
$bild     =$zeile_ar[4];

    
//ausgabe bauen
    
$ergebnis.="
      <P style='text-align:center;'>
      <B>Datensatz:</B> 
$datensatz_c &nbsp;
      <B>ID:</B> 
$id &nbsp;
      <B>Kategorie:</B> 
$kategorie &nbsp;
      <B>Name:</B> 
$name &nbsp;
      <B>Land:</B> 
$land
      </P>
      <P style='text-align:center;'>
      <IMG src='
$bild' alt='$bild' title='$bild' height=200 border=2>
      </P>
      <HR width='60%'>
    "
;

    
//treffer-anzahl erhoehen
    
$treffer_c++;
  };

  
//datenbank wieder schliessen
  
fclose($datei);

  
//ergebnis anhand der treffer interpretieren
  
if($treffer_c>0)
  {
    
$ergebnis="
      <P style='text-align:center;'>
      Suchbegriff '
$volltext' <B>$treffer_c-mal</B> gefunden
      </P>
      
$ergebnis
    "
;
  }
  else
  {
    
$ergebnis="
      <P style='text-align:center;'>
      Suchbegriff '
$volltext' <B>nicht</B> gefunden
      </P>
    "
;
  };
};

//webseite ausgeben
echo trim("
<BODY style='font-family:arial;font-size:12px;background-color:#d0d0a0;'>

<H1 style='text-align:center;font-size:20px;'>Demo zur Volltext-Suche in PHP</H1>

<H2 style='text-align:center;font-size:16px;'>Positionen in Mini-Datenbank per Volltext-Suche ohne MySQL selektieren</H2>

<FORM action='script.php' method='get'>
<P style='text-align:center;'>
<B>Suche nach:</B> <INPUT type='text' name='volltext' value='
$volltext'>
<INPUT type=submit value='Go'>
</P>
</FORM>

<HR>

$ergebnis

</BODY>
</HTML>
"
);

?>

Hinweise zum Script:

  • Die Funktion "dan_cgivar_get" wird in den PHP-Hilfsfunktionen definiert. Mit ihrer Hilfe können CGI-Variablen eingelesen werden. Der erste Parameter gibt den Namen des Input-Feldes wieder (hier "volltext"), der zweite Parameter einen Default-Wert, den die Variable annehmen soll, falls sie leer sein sollte (hier "kate").
  • "datensatz_c" ist ein Zähler für die Anzahl aller Datensätze, "treffer_c" ein Zähler für die Anzahl Datensätze, die den Suchbegriff enthalten.
  • Die Funktion "fgets" liest eine Zeile aus einer geöffneten Datei, wobei der erste Parameter das Datei-Handle angibt, und der zweite Parameter bestimmt, wie viel Zeichen die Zeile maximal enthält.
  • Die Funktion "strpos" prüft, ob ein String in einem anderen String enthalten ist. Falls ja, liefert sie die Position im String zurück. Da diese Position durchaus "0" sein kann, was dem booleschen Wert "false" entspricht, muss explizit mit drei Gleichheitszeichen auf "false" geprüft werden. Das ist für einen Delphi-Programmierer recht ungewohnte Kost :-)
  • "$volltext" und "$zeile" werden mit strtolower in Kleinschrift umgewandelt, sodass Gross-/Kleinschrift bei der Suche keine Rolle spielt.
  • Die Funktion "explode" spaltet einen String in ein Array mit mehreren Feldern auf, auf die dann mittels "[x]"-Index zugegriffen werden kann.
  • Das HTML-Form-Action wird auf "script.php" gesetzt. Dies bewirkt, dass sich durch einen Klick auf den Submit-Button das Script selbst aufruft.
  • Die HTML-Input-Variable "volltext" enthält als Value "$volltext", sodass nach einer Suchaktion der Suchbegriff erhalten bleibt.

5. Volltext-Suche ausprobieren

Klicken Sie hier ...

PHP-Tutorials - Volltext-Suche

... um das Volltext-Suche-Script auszuprobieren. Nette Suchbegriffe sind z.B.:

  1. "kate" liefert alle Prominenten, deren Namen "kate" enthält
  2. "usa;" liefert alle Prominenten aus den USA
  3. "e" liefert alle Datensätze zurück, da in jedem Datensatz mindestens einmal "e" auftaucht