demontpx / rigid-search-bundle
Symfony 的刚性搜索包
0.7.4
2021-01-06 17:51 UTC
Requires
- php: >=7.4
- ext-simplexml: *
- demontpx/util-bundle: ^0.6
- knplabs/knp-paginator-bundle: ^4.0|^5.0
- sensio/framework-extra-bundle: ^5.5
- symfony/form: ^4.4|^5.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- symfony/yaml: ^4.4|^5.0
README
提供了一种使实体可搜索的方法。
搜索结果将按相关性排序,相关性通过计算您可配置的索引字段的权重来得出。
安装
使用 composer 需要此包
composer require demontpx/rigid-search-bundle
用法:使实体可搜索
假设我们想索引一个 NewsItem
实体
class NewsItem { public function getId() { return $this->id; } public function getTitle() { return $this->title; } // ... }
第一步是创建一个新类,该类实现了 SearchDocumentExtractorInterface
接口。在这里,您定义需要搜索的字段以及它们之间的相对重要性。
class NewsItemDocumentExtractor implements SearchDocumentExtractorInterface { public function extractDocument($item): Document { // $item should be of the type NewsItem // The title, description and URL you put in here are only used for display and link to the item // They are not searchable unless you add them as fields as well (see below!) $document = new Document( $item->getTitle(), $item->getDescription(), $item->getPublishDate(), $this->generateUrl($item) ); // These are the fields on which items can be found // The last argument are the weight values, which can be any relative number $document->addField(new Field('title', $item->getTitle(), 1.0); $document->addField(new Field('text', $item->getText(), 0.8); $document->addField(new Field('category', $item->getCategoryName(), 0.2); $document->addField(new Field('tags', implode(' ', $item->getTagList()->toArray()), 0.25); return $document; } public function extractId($item): int { return $item->getId(); } }
第二步是创建另一个新类,该类实现了 ItemSearchManagerInterface
class NewsItemSearchManager implements ItemSearchManagerInterface { public function getClass(): string { // Classname of the entity return NewsItem::class; } public function getType(): string { // Short arbitrary unique name to describe the entity return 'news'; } public function getDocumentExtractor(): SearchDocumentExtractorInterface { // Return the class created earlier // You could, of course, also inject the extractor into this class using the service container and pass it here return new NewsItemDocumentExtractor(); } public function fetchAll(): array { // This method should return all searchable items of this type (ie: only published news items) // This is used when reindexing all items of this type // You should figure out for yourself where these entities should come from // For example: get these from an EntityRepository return $this->repository->fetchAllPublished(); } }
将此类注册为容器中的服务
MyBundle\NewsItemSearchManager: tags: [demontpx_rigid_search.item_search_manager]
如果一切配置正确,您应该可以使用此命令索引所有 news
项目
bin/console demontpx:search:reindex:type news
下一步是触发索引,当新闻条目被创建、更新或删除时手动删除。这可以通过事件实现,或者您可以在控制器中手动索引和从搜索索引中删除项目
class NewsItemController extends Controller { public function newAction() { $item = new NewsItem(); // ... Do your persist logic here $searchManager = $this->get('demontpx_rigid_search.search_manager'); $searchManager->index($item); } public function editAction(NewsItem $item) { // ... Do your persist logic here $searchManager = $this->get('demontpx_rigid_search.search_manager'); $searchManager->index($item); } public function removeAction(NewsItem $item) { $oldId = $item->getId(); // ... Do your remove logic here $searchManager = $this->get('demontpx_rigid_search.search_manager'); $searchManager->remove($item); // Doctrine ORM resets the item id to null after a delete, so you might want to use this: $searchManager->removeByClassAndId(get_class($item), $oldId); } }
用法:添加搜索字段并显示结果
第一步是将此添加到您的 routing.yaml
demontpx_rigid_search: resource: "@DemontpxRigidSearchBundle/Resources/config/routing.yml" prefix: /search
之后,您可以将此添加到任何 Twig 模板中
{{ render(controller('Demontpx\\RigidSearchBundle\\Controller\\SearchController::searchForm', {}, { query: app.request.query.get('query', '') })) }}
这将添加搜索输入字段。提交后,将显示搜索结果。
默认情况下,搜索结果页面将扩展 ::base.html.twig
模板。通过创建 app/Resources/DemontpxRigidSearchBundle/views/Search/searchResult.html.twig
来覆盖整个模板。