私は通常、を有効にした後、カスタム検索機能を一緒に使用しますFulltextSearchable
。だから_config.php
私は
FulltextSearchable::enable();
Object::add_extension('NewsStory', "FulltextSearchable('Name,Content')");
名前とコンテンツをDBField
検索可能にしたいものに置き換えます。そして、各検索可能ファイルDataObject
は、検索インデックスを有効にするためにクラスにこれを持っています(拡張機能を有効にする前に、これを追加してdev / buildを実行する必要があり、MySQL DBでのみ機能します)。
static $create_table_options = array(
'MySQLDatabase' => 'ENGINE=MyISAM'
);
次にPageController
、カスタムのsearchForm関数とresults関数があります。
テンプレート
search
で呼び出される検索フォームを返す関数は次のとおりです。$search
public function search()
{
if($this->request && $this->request->requestVar('Search')) {
$searchText = $this->request->requestVar('Search');
}else{
$searchText = 'Search';
}
$f = new TextField('Search', false, $searchText);
$fields = new FieldList(
$f
);
$actions = new FieldList(
new FormAction('results', 'Go')
);
$form = new Form(
$this,
'search',
$fields,
$actions
);
//$form->disableSecurityToken();
$form->setFormMethod('GET');
$form->setTemplate('SearchForm');
return $form;
}
results
そしてここでクエリを処理するカスタム関数...
function results($data, $form, $request)
{
$keyword = trim($request->requestVar('Search'));
$keyword = Convert::raw2sql($keyword);
$keywordHTML = htmlentities($keyword, ENT_NOQUOTES, 'UTF-8');
$pages = new ArrayList();
$news = new ArrayList();
$mode = ' IN BOOLEAN MODE';
//$mode = ' WITH QUERY EXPANSION';
//$mode = '';
$siteTreeClasses = array('Page');
$siteTreeMatch = "MATCH( Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords ) AGAINST ('$keyword'$mode)
+ MATCH( Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords ) AGAINST ('$keywordHTML'$mode)";
$newsItemMatch = "MATCH( Name, Content ) AGAINST ('$keyword'$mode)
+ MATCH( Name, Content ) AGAINST ('$keywordHTML'$mode)";
//Standard pages
foreach ( $siteTreeClasses as $c )
{
$query = DataList::create($c)
->where($siteTreeMatch);
$query = $query->dataQuery()->query();
$query->addSelect(array('Relevance' => $siteTreeMatch));
$records = DB::query($query->sql());
$objects = array();
foreach( $records as $record )
{
if ( in_array($record['ClassName'], $siteTreeClasses) )
$objects[] = new $record['ClassName']($record);
}
$pages->merge($objects);
}
//news
$query = DataList::create('NewsStory')->where($newsItemMatch);
$query = $query->dataQuery()->query();
$query->addSelect(array('Relevance' => $newsItemMatch));
$records = DB::query($query->sql());
$objects = array();
foreach( $records as $record ) $objects[] = new $record['ClassName']($record);
$news->merge($objects);
//sorting results
$pages->sort(array(
'Relevance' => 'DESC',
'Title' => 'ASC'
));
$news->sort(array(
'Relevance' => 'DESC',
'Date' => 'DESC'
));
//output
$data = array(
'Pages' => $pages,
'News' => $news,
'Query' => $keyword
);
return $this->customise($data)->renderWith(array('Search','Page'));
}
検索したいすべてのPageクラスを追加し、それを配列に拡張SiteTree
します。Newsパーツは、検索が必要な他のクラスにほぼコピーできます。$siteTreeClasses
DataObject
私はこれが最善の解決策であると言っているわけではなく、これは間違いなく改善することができますが、それは私にとってはうまくいき、これは良い述べ点かもしれません。