This is a simple way to add a keyword search to an index view. I am a newcomer to Yii, so check out any comments for improvements on this approach.
A search for Web Apps will find all records where the content of the sepecified search columns includes either ‘Web’ or ‘Apps’.
A search for “Web Apps” will find all records where the content of the sepecified search columns includes the phrase ‘Web Apps’.
The example code is based on the ‘post’ entity in the blog tutorial. First create a search component. The widget, KeywordSearchComponent.php, goes in the /protected/components folder.
<?php
Yii::import('zii.widgets.CPortlet');
class KeywordSearchComponent extends CPortlet
{
protected function renderContent()
{
$this->render('keywordSearch');
}
}
The associated view, keywordSearch.php, goes in the /protected/components/views folder.
<div>
<?php echo CHtml::beginForm(array('post/index'), 'get'); ?>
<?php echo Chtml::label('Keyword Search ', 'searchbox'); ?>
<?php echo Chtml::textField('searchbox', $this->controller->currentSearchValue, array('size'=>20,'maxlength'=>128)); ?>
<?php echo CHtml::submitButton('Search'); ?>
<?php echo CHtml::endForm(); ?>
</div>
Now add the search widget to the index.php view above the CListView widget using the code:
<?php $this->widget('KeywordSearchComponent'); ?>
The controller (e.g. PostController.php) now needs to be amended. Add the following instance variables (amending the column names to those you wish to be included in the keyword search).
private $keywordSearchColumnArray = array('title', 'content','tags'); //Columns to search
public $currentSearchValue; //Current keword search string
Now add a new search condition to the actionIndex function. The following example is an amended version of the post demo code.
public function actionIndex()
{
//Original demo code to create a criteria object
$criteria=new CDbCriteria(array(
'condition'=>'status='.Post::STATUS_PUBLISHED,
'order'=>'priority',
'with'=>'commentCount',
));
//New code for the keyword search
if(isset($_GET['searchbox']) and strlen(trim($_GET['searchbox'])) > 0)
{
$this->currentSearchValue = trim($_GET['searchbox']);
$additionalCriteria = $this->makeKeywordSearchCondition($_GET['searchbox']);
$criteria->addCondition($additionalCriteria);
}
//Original demo code for the tag cloud search
if(isset($_GET['tag']))
$criteria->addSearchCondition('tags',$_GET['tag']);
//Original demo code to create the data provider object
$dataProvider=new CActiveDataProvider('Post', array(
'pagination'=>array(
'pageSize'=>Yii::app()->params['postsPerPage'],
),
'criteria'=>$criteria,
));
...
Finally, add the makeKeywordSearchCondition function:
/**
* Make the keyword search SQL.
* @param String Search string input by user
* @return String SQL condition
*/
private function makeKeywordSearchCondition($keywordStr){
$criteriaSql; //Search condition
//Split the string into an array of words and phrases
//The string: Android "Web Apps"
//will produce a two element array containing 'Android' and 'Web Apps'
$elementArray = array();
$regX = "/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|[\s,]+/";
$tempArray = preg_split ($regX, trim($keywordStr), 0, PREG_SPLIT_DELIM_CAPTURE);
foreach($tempArray as $ind => $str){
if(trim($str)){
array_push($elementArray, $str);
}
}
//Construct the search sql
foreach($this->keywordSearchColumnArray as $column)
{
foreach($elementArray as $value){
$value = addSlashes($value);
$value = '"%'.$value.'%"';
if($criteriaSql){
$criteriaSql .= ' OR';
}
$criteriaSql .= " $column LIKE $value";
}
}
return $criteriaSql;
}