Yii Framework Forum: Add a keyword search to an index view - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Add a keyword search to an index view How to add a keyword search to an index view

#1 User is offline   Mike (UK) 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 16
  • Joined: 01-August 10
  • Location:Exeter, UK

Posted 16 September 2010 - 01:15 AM

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;
}			

1

#2 User is offline   Mike (UK) 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 16
  • Joined: 01-August 10
  • Location:Exeter, UK

Posted 16 September 2010 - 01:58 AM

A correction to my code. In keywordSearch.php I have hard coded the route to 'post/index'. To make the widget portable it needs to use $this->controller->getRoute(), so the keywordSearch view becomes:

<div>
<?php echo CHtml::beginForm(array($this->controller->getRoute()), '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>

0

#3 User is offline   Mike (UK) 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 16
  • Joined: 01-August 10
  • Location:Exeter, UK

Posted 12 October 2010 - 12:58 PM

Notes for Postgresql users:

In Postgres, unlike MySQL, the keywords are case sensitive.

Becuase Postgres does not like double quotes the following line in the makeKeywordSearchCondition function:

$value = '"%'.$value.'%"';  


must be changed to:

$value = "'%".$value."%'";


This change will work OK with MySQL.
0

#4 User is offline   ahmad 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 2
  • Joined: 29-January 11

Posted 08 February 2011 - 01:45 PM

View PostMike (UK), on 16 September 2010 - 01:15 AM, said:

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;
}			



thank you very much for you sharing.
I try your code, but there is a problem with this variable "$criteriaSql;" in beginning of "makeKeywordSearchCondition" function. I don't know which default value for this variable, so I put "$criteriaSql = "";".

If you have any idea please tell me.

Thanks again.
0

#5 User is offline   Mike (UK) 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 16
  • Joined: 01-August 10
  • Location:Exeter, UK

Posted 10 February 2011 - 11:21 AM

View Postahmad, on 08 February 2011 - 01:45 PM, said:

thank you very much for you sharing.
I try your code, but there is a problem with this variable "$criteriaSql;" in beginning of "makeKeywordSearchCondition" function. I don't know which default value for this variable, so I put "$criteriaSql = "";".

If you have any idea please tell me.

Thanks again.


The $criteriaSql = ""; is fine
0

#6 User is offline   brzk 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 9
  • Joined: 16-May 15

Posted 27 November 2016 - 03:21 AM

View PostMike (UK), on 16 September 2010 - 01:15 AM, said:

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;
}			



thx it's work and helpfull

regards
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users