Juni 1st, 2009 | |
Posted in Coding
Um eine ordentliche Suchfunktion in das eigene Web-Projekt zu integrieren bedarf es entweder einer Menge Arbeit oder der Nutzung von Lucene. Bei Lucene handelt es sich um eine plattformunabhängige Such- und Index-Programmierschnittstelle der Apache Software Foundation. Die Wikipedia setzt beispielsweise Lucene zur Volltextsuche ein.
Der einfachste Weg Lucene in CodeIgniter zu integrieren ist die Verwendung der Zend-Lucene-Bibliothek. Dazu gibt es ein gutes Tutorial von Fred Wu, das ich hier kurz zusammenfassen und um die Suchfunktionalität erweitern werde.
Zend-Bibliotheken in CodeIgniter integrieren
- Aktuelle Version des Zend-Frameworks hier herunterladen
- Paket entpacken und den Ordner Zend (unter Library) in das CodeIgniter-Verzeichnis application/libraries/ kopieren
- Das unten angegebene Script in das gleiche Verzeichnis kopieren(application/libraries/)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| /**
* Zend Framework Loader
*
* Put the 'Zend' folder (unpacked from the Zend Framework package, under 'Library')
* in CI installation's 'application/libraries' folder
* You can put it elsewhere but remember to alter the script accordingly
*
* Usage:
* 1) $this->load->library('zend', 'Zend/Package/Name');
* or
* 2) $this->load->library('zend');
* then $this->zend->load('Zend/Package/Name');
*
* * the second usage is useful for autoloading the Zend Framework library
* * Zend/Package/Name does not need the '.php' at the end
*/
class CI_Zend
{
/**
* Constructor
*
* @param string $class class name
*/
function __construct($class = NULL)
{
// include path for Zend Framework
// alter it accordingly if you have put the 'Zend' folder elsewhere
ini_set('include_path',
ini_get('include_path') . PATH_SEPARATOR . APPPATH . 'libraries');</code>
<code>if ($class)
{
require_once (string) $class . EXT;
log_message('debug', "Zend Class $class Loaded");
}
else
{
log_message('debug', "Zend Class Initialized");
}
}
/**
* Zend Class Loader
*
* @param string $class class name
*/
function load($class)
{
require_once (string) $class . EXT;
log_message('debug', "Zend Class $class Loaded");
}
}
?> |
Das war’s schon! Damit können jetzt die Bibliotheken des Zend-Frameworks in CodeIgniter genutzt werden. Man lädt die Bibliotheken folgendermaßen:
1
2
| $this->load->library('zend');
$this->zend->load('Zend/Name_der_Bibliothek'); |
Die Endung .php wird bei der Angabe des Bibliotheksnamen nicht benötigt.
Suchfunktionalität mittels Lucene in Codeiginter integrieren
Da jetzt die Zend-Bibliotheken in CodeIgniter nutzbar sind, steht einer Nutzung von Lucene ebenfalls nicht mehr im Weg. Schauen wir uns einmal den dazu benötigten Controller an (suche.php):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| <?php
class Suche extends Controller {
function Suche() {
parent::Controller();
// Zends Lucene-Bibliothek laden
$this->load->library('zend');
$this->zend->load('Zend/Search/Lucene');
// Suchindex festelegen
$this->search_index = APPPATH . 'search/index';
}
function index(){
$this->load->view('search_view');
}
function index_it() {
// Index erstellen (bisheriger Index wird gelöscht)
$index = Zend_Search_Lucene::create($this->search_index);
// Content, der indexiert werden soll aus DB auslesen
$query = $this->db->get('brand_content');
// Alle Content-Instanzen zum Index hinzufügen
foreach ($query->result() as $item) {
// Lucene Document für diese Content-Instanz erstellen
$doc = new Zend_Search_Lucene_Document();
// dieser Titel wird in den Suchergebnissen angezeigt
$doc->addField(Zend_Search_Lucene_Field::Text('title', $item->title));
// mit diesem Pfad werden die Suchergebnisse verknüpft
$doc->addField(Zend_Search_Lucene_Field::Text('path', '/brand/'.$item->parent.'/' . $item->slug.'/'));
// dieser Inhalt wird neben dem Titel indexiert
$doc->addField(Zend_Search_Lucene_Field::UnStored('content', $item->content));
// zum Index hinzufügen
$index->addDocument($doc);
echo 'Added ' . $article->title . ' to index.<br />';
}
$index->optimize();
}
function result() {
$data['results'] = array();
// falls der "search_query"-Parameter übergeben wurde Suche ausführen
if ($this->input->post('search_query')) {
// Index analysieren; Suchergebnisse auslesen
$index = Zend_Search_Lucene::open($this->search_index);
$data['results'] = $index->find($this->input->post('search_query'));
}
// View mit Suchergebnissen anzeigen
$this->load->view('search_view', $data);
}
} |
Im Konstruktor wird die Lucene-Bibliothek wie bereits gezeigt geladen und der Ort des Suchindexes festegelegt. Mit der Funktion index_it wird der Index aufgebaut. Diese Funktion hat natürlich nichts in einem öffentlich zugänglichen Controller verloren und ist hier nur aus Gründen der Einfachheit im Controller enthalten.
Die View, die von diesem Controller aufgerufen wird enthält ein Formular mit einem Feld Namens search_query. Dieses muss wie bei CodeIgniter üblich per POST an suche/result/ übergeben werden, wo die Auswertung des Indexes stattfindet. Die View folgt hier noch einmal kurz im Überblick (search_view.php).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| <html>
<head>
<title>Suche</title>
</head>
<body>
<h1>Suche</h1>
<?php if (empty($_POST['search_query'])):?>
<p>Bitte Suchbegriff eingeben!</p>
<form method="post" action="<?=base_url()?>suche/result/">
<input type="text" name="search_query" value="" size="40" maxlength="40"/>
<input type="submit" name="submit" value="suchen"/>
</form>
<?php else:?>
<?php if (count($results)):?>
<p><?php echo count($results) ?> Ergebnis(se) für die Suchanfrage <b><?php echo $_POST['search_query'];?></b></p>
<ul>
<?php foreach($results as $result):?>
<li><?=anchor(site_url($result->path), $result->title);?> (<?php echo round($result->score, 2) * 100;?>%)</li>
<?php endforeach;?>
</ul>
<?php else:?>
<p>Keine Ergebnisse für die Suchanfrage <b><?php echo $_POST['search_query'];?></b></p>
<?php endif;?>
<?php endif;?>
</body>
</html> |
Fragen und Anregungen oder Verbesserungsvorschläge zu diesem Code können natürlich gerne in den Kommentaren abgegeben werden.
Sollten Sie einen CodeIgniter-Entwickler für eines Ihrer Projekte suchen, dürfen Sie mich gerne kontaktieren!
Tags:
codeigniter,
lucene,
mysql,
suchmaschine,
volltextsuche,
zend