我正在尝试在默认的SearchResult页面中显示某些DataObjects(新闻)。因此结果应该显示正常的页面和新闻。
在Silverstripe 3中有没有简单的方法可以实现这一目标? 或者是否建议将其完全自定义编码 - 我的意思是自定义控制器/操作处理搜索请求并创建结果列表,然后我在自定义模板中显示?
我发现了这一点,但显然现在禁用搜索: https://github.com/arambalakjian/DataObjects-as-Pages
感谢和问候, 弗洛里安
答案 0 :(得分:8)
我通常会在启用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 和结果功能。
以下是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
数组中扩展$siteTreeClasses
,新闻部分可以对于我需要搜索的任何其他DataObject
,几乎都要复制。
我并不是说这是最好的解决方案,这肯定可以改进,但它对我有用,这可能是一个很好的说明点。
答案 1 :(得分:2)
我已将@ colymba的解决方案改编为silverstripe模块:https://github.com/burnbright/silverstripe-pagesearch
它允许在网址中设置pagetype。
答案 2 :(得分:1)
您需要大幅覆盖SearchForm->getResults()
。
它使用Database->searchEngine()
,但这些是针对SiteTree
和Page
类量身定制的。
“正确”的解决方案是将数据提供给Solr或Sphinx等搜索引擎。 为此,我们有与SS3兼容的“fulltextsearch”模块: https://github.com/silverstripe-labs/silverstripe-fulltextsearch 这将需要一些前期设置,并且只有在您自己主持Solr或准备为SaaS提供商付费时才可行。一旦你运行它,可能性是无穷无尽的,它是一个很好的工具!