Difference between #14 and #15 of
Adding search to Yii blog example (using Zend Lucene)

Revision #15 has been created by klammeraffe on Jan 9, 2013, 8:10:39 PM with the memo:

Reverted to revision #13
« previous (#14)

Changes

Title unchanged

Adding search to Yii blog example (using Zend Lucene)

Category unchanged

Tutorials

Yii version unchanged

Tags unchanged

blog, demo, search, zend, zf, lucene, tutorial

Content changed

Introduction ------------ InFor this tutorial I will add a search to the blog demo. The search would be based on Zend Lucene. Requirements and Preparation --------------------------- * Yii framework -  I will work with the current version [yii-1.1.8.r3324](yii.googlecode.com/files/yii-1.1.8.r3324.tar.gz "1.1.8") extract the archive oin your server... * Now go to your **yii-1.1.8.r3324\demos\blog\protected** directory and create there a **vendors** directory In the vendors directory you should put the Zend Framework library which you can,
 
For this you will need to
[download hereit](http://www.zendframework.com/download/latest "download hereit"). After downloading copy the Zend directory with ththat inside library (with Zend directory inside) into vendors. It sShould look like this now (I copied only the Search directory...): <center> ![](http://i31.fastpic.ru/big/2011/1007/35/815528faa31a322de17366764b489335.png "") </center> * add under runtime directory, a new one and call it search, it will be used for the index files that Zend Lucene will create.
Make sure it is writable!
[...]
-------------------------------
For this we will create a widget or if to be more specific a CPortlet!
The most simple way is
to go to your components directory and, create SearchBlock.php file. And copy inside code from tag cloud. change class name to SearchBlock. Now lets insert it ! Go to views/layouts/column2.php add this, abouve the TagCloud widget ```php <?php       $this->widget('SearchBlock', array(       ));  ?> ``` after saving you will see 2 tag cloulds in your main blog page...
lets now edit it and change it to some search form
[...]
class SearchBlock extends CPortlet
{
public $title='Search'; protected function renderContent() {        echo CHtml::beginForm(array('search/search'), 'get', array('style'=> 'inline')) . CHtml::textField('q', '', array('placeholder'=> 'search...','style'=>'width:140px;')) . CHtml::submitButton('Go!',array('style'=>'width:30px;')) . CHtml::endForm(''); }
}
```
[...]
class SearchController extends Controller
{
/**  * @var string index dir as alias path from <b>application.</b>  , default to <b>runtime.search</b>  */ private $_indexFiles = 'runtime.search'; /**  * (non-PHPdoc)  * @see CController::init()  */ public function init(){ Yii::import('application.vendors.*'); require_once('Zend/Search/Lucene.php'); parent::init(); }     public function actionCreate() {
 
}
 
 
    {
 
    }
 
    
 
    
public function actionSearch() {
 
    {
 
    
}
}
```
[...]
To do more advanced stuff, you will need to learn it

Also the [api ](http://framework.zend.com/apidoc/core/db_Search_Lucene.html#%5CZend_Search_Lucene "") for the Lucene class
 

Creating Search Index
[...]
```php
/**
 * Search index creation  */     public function actionCreate() {
 
    {
 
    
$index = new Zend_Search_Lucene(Yii::getPathOfAlias('application.' . $this->_indexFiles), true);
 
    
 
    
$posts = Post::model()->findAll();      foreach($posts as $post){      $doc = new Zend_Search_Lucene_Document();
 
    
 
    
$doc->addField(Zend_Search_Lucene_Field::Text('title', CHtml::encode($post->title), 'utf-8')
 
);
 
 
$doc->addField(Zend_Search_Lucene_Field::Text('link',
 
CHtml::encode($post->url)
 
, 'utf-8')
 
);
 
 
$doc->addField(Zend_Search_Lucene_Field::Text('content',
 
CHtml::encode($post->content)
 
, 'utf-8')
 
);
 
 
 
                                          CHtml::encode($post->title), 'utf-8')
 
            );
 
            
 
            $doc->addField(Zend_Search_Lucene_Field::Text('link',
 
                                          CHtml::encode($post->url)
 
, 'utf-8')
 
);   
 

 
$doc->addField(Zend_Search_Lucene_Field::Text('content',
 
                                          CHtml::encode($post->content)
 
                                          , 'utf-8')
 
            );
 
           
 

 
$index->addDocument($doc); }
 
     }
 
    
$index->commit();     echo 'Lucene index created';     } ``` First I found all the posts with **Post::model()->findAll();** and than I added post to search index one by one, his content title and link fields Now you should navigate to 
**http://localhost/yii-1.1.8.r3324/demos/blog/index.php/search/create**
And you will see "Lucene index created"
[...]
```php
public function actionSearch()
{
 
    {
 
    
$this->layout='column2';      if (($term = Yii::app()->getRequest()->getParam('q', null)) !== null) {         $index = new Zend_Search_Lucene(Yii::getPathOfAlias('application.' . $this->_indexFiles));         $results = $index->find($term);         $query = Zend_Search_Lucene_Search_QueryParser::parse($term);
 
 
       
 
 
        
$this->render('search', compact('results', 'term', 'query')); }
 
    }
 
    
}
```
[...]
$this->pageTitle=Yii::app()->name . ' - Search results';
$this->breadcrumbs=array(
'Search Results',
);
?>
[...]
<h3>Search Results for: "<?php echo CHtml::encode($term); ?>"</h3>
<?php if (!empty($results)): ?>
    <?php foreach($results as $result):  ?>
 

 
<p>Title: <?php echo $query->highlightMatches(CHtml::encode($result->title)); ?></p>         <p>Link: <?php echo CHtml::link($query->highlightMatches(CHtml::encode($result->link)), CHtml::encode($result->link)); ?></p>         <p>Content: <?php echo $query->highlightMatches(CHtml::encode($result->content)); ?></p> <hr/>
 
        <hr/>
 
    
<?php endforeach; ?>
 
    
 
<?php else: ?>     <p class="error">No results matched your search terms.</p> <?php endif; ?> ``` As you can see because I passed to the view the $query, I can use Zend's highlightMatches ...<br>  (if your search results not in Eenglish, you might have some encoding issues with highlightMatches, so you might consider using your own highlighter for greater flexibility and encoding issues free)<br>  Also I created a real link from the linked I passed and created via **$doc->addField(Zend_Search_Lucene_Field::Text('link' ...** And that's it
try to search the word "it"
And you will get:
[...]
</center>

So don
't continue reading, until you spend some time thinking about it and trying your self!
[...]
```php
<?php for($i = $currentPage * $pages->pageSize - $pages->pageSize, $end = $currentPage * $pages->pageSize; $i<$end;$i++):
?>

 

 
<p>Title: <?php echo $query->highlightMatches(CHtml::encode($results[$i]->title)); ?></p>         <p>Link: <?php echo CHtml::link($query->highlightMatches(CHtml::encode($results[$i]->link)), CHtml::encode($results[$i]->link)); ?></p>         <p>Content: <?php echo $query->highlightMatches(CHtml::encode($results[$i]->content)); ?></p> <hr/>
 
        <hr/>
 
    
<?php endfor; ?> ``` and add after this 
[...]
```php
<?php $this->widget('CLinkPager', array(
    'pages' => $pages,
)) ?>
```
[...]
What will happen if you have 2 pages, but only 4 records?
You will get undefin
ed offsset errors...

Consider this as homework ;-)
[...]
---------------------------

Actually if you want it pass between pages via ajax, and don't handle the offset issues etc. ( it is easy but... we still most lik
ely want ajax) So you can consider doing the pagination via CArrayDataProvider You have there example http://www.yiiframework.com/doc/api/1.1/CArrayDataProvider Just pass the result array than you can create CListView with some basic view for search result element, and you are done... CArrayDataProvider will do all the dirty work for you!
29 1
47 followers
Viewed: 88 642 times
Version: 1.1
Category: Tutorials
Written by: dckurushin
Last updated by: klammeraffe
Created on: Oct 7, 2011
Last updated: 11 years ago
Update Article

Revisions

View all history