search
search copied to clipboard
Multi-model site search plugin for CakePHP
h1. Multi-model site search plugin for CakePHP
This plugin provides an easy to install and non-obstrusive solution to add a local search engine to your Cake app.
Features :
- Uses MySQL Full-Text engine.
- Easy install : download the files and create 1 db table, no matter how many Models you want to index.
- Non-obstrusive : you don't need to add Full-Text indexes on existing tables.
- Several search modes : natural language, natural language with query expansion, and boolean mode.
h1. 1. Installation
h2. 1.1. Files
To install, copy the 'search' directory to the 'plugins' folder:
git clone git://github.com/kalt/search.git
Or click 'download' and copy the content of the zip file into your 'plugins' folder.
h2. 1.2. DB table
Create one db table as described in search/config/sql/search.sql
h1. 2. Setup
h2. 2.1. Models
Link any model to the Searchable Behavior, and define the fields you want to index.
class Article extends AppModel
{
var $actsAs = array('Search.Searchable' => array(
'fields' => array('title', 'body')
));
}
That's it. Whenever you save or edit a record, the 'title' and 'body' fields will be indexed.
h2. 2.2. Search form
Create a search form anywhere (most of the time in the layout).
The form must contain a text input field named 'q'.
echo $form->create('Search', array('url' => array(
'plugin' => 'search',
'controller' => 'searches',
'action' => 'index'
)));
echo $form->input('q', array('label' => 'Keywords:'));
echo $form->end();
h2. 2.3. Search results page
Create a view to display the paginated search results : {app}/views/plugins/search/searches/index.ctp
Available data :
$q: Search terms.$data: Paginated results.
Example:
Search results
You searched for:
counter(array('format' => "Page %page% on %pages%, %current% results on %count%")); ?>
link($row['Article']['title'], array(
'plugin' => null,
'controller' => 'articles',
'action' => 'view',
$row['Article']['id']
));
$description = $row['Article']['body'];
break;
case 'Video':
$link = $html->link($row['Video']['title'], array(
'plugin' => null,
'controller' => 'videos',
'action' => 'play',
$row['Video']['id']
));
$description = $row['Video']['description'];
break;
} ?>
prev('
| numbers();?>
next(__('Next', true).' >>');?>
h2. 3. Options
h3. 3.1. Search modes
Two available search modes :
boolean(default) : MySQL performs a Full-Text boolean search, ie all terms must be in the results.natural: MySQL performs a Full-Text natural language search, ordering results by relevance.
More info on the Full-Text search functions : http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
To change the search mode, simply add this line in your {app}/config/bootstrap.php
Configure::write('Search.mode', 'natural');
h3. 3.2. Query expansion
This is an option for the natural language search mode only. More info here : http://dev.mysql.com/doc/refman/5.0/en/fulltext-query-expansion.html
Defaults to null : it will enable query expansion if the search query is only one word.
To redefine this option, simply add this line in your {app}/config/bootstrap.php
Configure::write('Search.withQueryExpansion', true/false);
If set to false, query expansion will never be used at all, even if the search query is only one word.
If set to true, query expansion will always be used.
h3. 3.3. Allowed characters in search terms
By default the allowed chars are alphanumeric only.
To add allowed characters, simply add your own list in your {app}/config/bootstrap.php
Configure::write('Search.allowedChars', array(' '));
Here, the only accepted characters will be alphanumeric and space ' '.
Defaults to valid french accents, and space ' '.
h2. 4. Pretty URL
The default search results URL is /search/searches/search+terms
You can redefine it by adding a simple route in {app}/config/routes.php
Router::connect(
'/search/*',
array('plugin' => 'search', 'controller' => 'searches', 'action' => 'index')
);
Will give you /search/search+terms
h2. 5. Index existing data
If you want to install this plugin in an existing app, with already filled tables, add the 3 following actions in your {app}/app_controller.php
/**
* Builds the search index for the current model based on existing data.
*/
function admin_build_search_index()
{
$this->autoRender = false;
$model =& $this->{$this->modelClass};
if(!isset($model->Behaviors->Searchable))
{
echo "Error : the {$model->alias} model is not linked with Searchable Behavior.";
exit;
}
$data = $model->find('all');
foreach($data as $row)
{
$model->set($row);
$model->Behaviors->Searchable->Search->saveIndex(
$model->alias,
$model->id,
$model->buildIndex()
);
}
echo "<pre>Search index for model {$model->alias} have been built.</pre>";
}
/**
-
Delete the search index for the current model.
*/
function admin_delete_search_index()
{
$this->autoRender = false;
$model =& $this->{$this->modelClass};
if(!isset($model->Behaviors->Searchable))
{
echo "
Error : the {$model->alias} model is not linked with Searchable Behavior.";
exit;
}
$model->Behaviors->Searchable->Search->deleteAll(array(
'model' => $model->alias
));
echo "
Search index for model {$model->alias} have been deleted.";
}
/**
- Rebuilds the search index for the current model based on existing data.
*/
function admin_rebuild_search_index()
{
$this->admin_delete_search_index();
$this->admin_build_search_index();
}
You can now go to /admin/{any_controller}/build_search_index to build the search index based on existing data. Beware, it could take some time, depending on the volume of existing data to index.
Any suggestion is welcome!