FAQ #51

Question: How do I add a search engine on my Cakephp site? Answer: Use fulltext index (presuming you use Mysql as the database) and by coaxing Cake's paginate method, you can create a decent search engine fairly quickly. Here's a full example...
//Your links table includes these fields
url VARCHAR(255) NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
status TINYINT NOT NULL DEFAULT 0,
FULLTEXT KEY `fulltext` (`title`,`description`)

//Your model search.php
<?php
class Search extends AppModel {
var $useTable = false;

var $validate = array(
'q' => array(
'notempty' => array(
'rule' => 'notempty',
'message' => 'Query cannot be empty',
),
'maxlength' => array(
'rule' => array('maxlength',100),
'message' => 'Query cannot be longer than 100 characters',
),
'minlength' => array(
'rule' => array('minlength',2),
'message' => 'Query cannot be shorter than 2 characters',
),
),
);
} //end of class
/*EOF*/

//Your controller search_controller.php
<?php

class SearchController extends AppController {
var $uses=array('Link');

function index(){
$this->set('title_for_layout',"Search results");
$query=(isset($this->data['Search']['q']))?$this->data['Search']['q']:'';
if(!$query) $query=(isset($this->params['url']['q']))?$this->params['url']['q']:'';
if(!$query){
$this->Session->setFlash(__("Invalid or empty search string",true));
}
else{
App::import('Sanitize');
$this->set('query',$query);
$query=Sanitize::escape($query);
$this->paginate = array(
'conditions' => array('Link.status'=>1,
"MATCH(Link.title,Link.description) AGAINST('$query' IN BOOLEAN MODE)"
),
'recursive'=>-1,
'limit'=>10,
);
$this->set('links', $this->paginate('Link'));
}

}


} //end of class
/*EOF*/

//Your search form which you can put anywhere in your layout:
<?php
echo $this->Form->create('Search',array('url'=>'/search'));
echo $this->Form->input('q',array('label'=>'Search'));
echo $this->Form->end();
?>

//Your search/index.ctp view, to display search results
<div id="bigtitle">Search Results</div>

<?php if($query):?>
<p>
Search for: <strong><? echo $query; ?></strong>

</p>
<?php
foreach($links as $link){
?>
<div id="result">
<div id="title"><?php echo $link['Link']['title'];?></div>
<div id="description"><?php echo $link['Link']['description'];?></div>
<div id="url">
<?php echo $this->Html->link($link['Link']['url'],$link['Link']['url']);?>
</div>
</div>
<?php
}
?>
<p>
<?php
//here's where we preserve the query for the next page of results
$paginator->options(array('url' => array_merge($this->passedArgs,
array('?' => "&q=".urlencode($query)))));
echo $this->Paginator->counter(array(
'format' => __('Page %page% of %pages%', true)
));
?> </p>

<div class="paging">
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
| <?php echo $this->Paginator->numbers();?>
|
<?php echo $this->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?>
</div>
<?php endif; ?>
Add comment