Revision #14 has been created by klammeraffe on Jan 9, 2013, 8:09:04 PM with the memo:
some language corrections - only a start
Introduction
------------
ForIn 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
ion 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
,
For this you will need to which you can [download
ithere](http://www.zendframework.com/download/latest "download
ithere")
.
After downloading copy the Zend directory
that insidwith the library (with Zend directory inside)
into vendors
.
SIt should 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
a 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, abo
uve the TagCloud widget
```php
<?php
$this->widget('SearchBlock', array(
));
?>
```
after saving you will see 2 tag c
lou
lds 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 undefined of
sfset 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 likely 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!