如何在 Drupal 9 中实现 Algolia Search(第 2 部分)
已发表: 2022-09-13在本系列的前一章中,我们向您介绍了配置 Algolia 仪表板和您的 Drupal 站点以索引 Algolia 上的站点内容的过程。 在本章中,您将学习如何在您的 Drupal 网站上显示 Algolia 搜索结果。
要显示搜索结果,您需要创建一个 Drupal 自定义块并将该块放在/search页面上。 此外,您还将了解如何使用 Algolia 的InstantSearch库。 请注意,此过程假设您对如何在 Drupal 中创建自定义模块有基本的了解,因此我们不会深入探讨创建自定义模块的过程。 阅读本文以了解如何在 Drupal 9 中以编程方式创建自定义模块。
这是 2 部分系列文章的第二章。 单击此处阅读我们讨论如何配置 Algolia 和 Drupal 的第一部分。
为界面构建自定义块
我们将使用以下结构来创建我们的自定义块。
algolia_search_interface - js/ - algolia.js - src/ - Plugin - Block - DemoSearchBlock.php - templates/ - algolia_search_interface-block.html.twig - algolia_search_interface.info.yml - algolia_search_interface.libraries.yml - algolia_search_interface.module
声明库
如前所述,我们将使用 Algolia 的 InstantSearch 库来访问搜索结果。 因此,让我们在 algolia_search_interface.libraries.yml 中声明所有库,如下所示:
algolia-javascript: js: https://cdn.jsdelivr.net/npm/[email protected]/dist/algoliasearch-lite.umd.js : { type: external } https://cdn.jsdelivr.net/npm/[email protected] : { type: external } js/algolia.js: {preprocess: false} dependencies: - core/drupalSettings css: theme: https://cdn.jsdelivr.net/npm/[email protected]/themes/algolia-min.css: { type: external, minified : true }
访问和设置变量
在演示搜索块(DemoSearchBlock.php)中,我们将简单地从 Drupal 配置中访问 Algolia 变量,并使用以下代码将它们分配给 drupalSettings:
public function build() { // Get Algolia config. $config = $this->configFactory->get('search_api.server.algolia_search'); $app_id = $config->get('backend_config.application_id'); $api_key = $config->get('backend_config.api_key'); $index_name = $this->configFactory->get('search_api.index.vehicles_data')->get('options.algolia_index_name'); return [ '#theme' => 'demo_search_block', '#attached' => [ 'library' => 'algolia_search_interface/algolia-javascript', 'drupalSettings' => [ 'app_id' => $app_id, 'index_name' => $index_name, 'api_key' => $api_key, ], ], '#cache' => [ 'contexts' => [ 'url.path', 'url.query_args', ], ], ]; }
添加模板
现在您需要为自定义块添加模板。 因此,让我们在 algolia_search_interface.module 中为我们的自定义块定义 hook_theme:
/** * Implements hook_theme(). */ function algolia_search_interface_theme($existing, $type, $theme, $path) { return [ 'demo_search_block' => [], ]; }
定义容器
现在,让我们定义我们的模板数据来呈现搜索结果。 我们将简单地定义 InstantSearch 库将呈现结果的容器。 我们将在 algolia_search_interface-block.html.twig 中添加 4 个容器:
- Searchbox (#searchbox) - Search results (#hits) - Facets (#filter-widget) - Pagination (#pagination)
<div class="demo-instant-search"> <div class="algolia-searchbox"></div> <div class="align-left"> <div class="filter-header">{{ 'Manufacturer'|t }}</div> <div></div> </div> <div class="right-col"> <div></div> </div> </div> <div></div>
显示搜索结果
现在,您拥有了显示搜索结果所需的所有要素。 那么让我们看看如何使用 InstantSearch 来显示我们的结果。
首先,让我们从 drupalSettings 变量中获取索引名称、应用程序 ID 和应用程序键。 我们需要将它们传递给 algolia.js 中的 Algolia API。
const index_name = drupalSettings.index_name; const app_id = drupalSettings.app_id; const api_key = drupalSettings.api_key;
准备好应用程序键和索引名称后,您需要初始化并启动 InstantSearch。
const search = instantsearch({ indexName: index_name, searchClient: algoliasearch(app_id, api_key), }); search.start();
此时,您不会在搜索页面中看到任何差异,因为您尚未将任何小部件添加到 InstantSearch。 因此,让我们在即时搜索中添加一个搜索框小部件。
search.addWidget( instantsearch.widgets.searchBox({ container: '#searchbox', }) );
请注意,我们使用了InstantSearch的addwidget()函数来添加单个小部件。 当使用多个小部件时, addwidget()是不可行的。 您将需要以下列方式使用它:
search.addWidgets([ instantsearch.widgets.searchBox({ container: '#searchbox', }), instantsearch.widgets.hits({ container: '#hits' }), ]);
现在您将能够在搜索页面上看到搜索结果。 但正如我们所见,结果是非常原始的格式:
为了改进这一点,让我们使用模板属性格式化结果,如下所示:
instantsearch.widgets.hits({ container: '#hits', templates: { item: ` <h3 class="title">{{{title.value}}}</h3> <p class="detail"> {{{field_manufacturer}}} </p> <p class="uri">{{{uri}}} </p> `, }, }),
请注意,虽然结果看起来不错,但有时我们需要对数据进行一些处理,然后才能将其显示在页面上。 例如在上面的代码中,URI 值是`public://`格式。 在这里,我们可以使用transformItems属性来根据我们的要求更改结果。
instantsearch.widgets.hits({ container: '#hits', transformItems(items) { return items.map(item => ({ ...item, url: item.uri.replace('public://', /sites/default/files/'), })); }, templates: { item: ` <h3 class="title">{{{title.value}}}</h3> <p class="detail"> {{{field_manufacturer }}} </p> <p class="uri">{{{url}}} </p> `, }, })
一旦结果集就位,您现在可以移动以显示构面数据以过滤我们的搜索条件。 您将使用相同的addWidgets()函数来显示构面。
search.addWidgets([ instantsearch.widgets. refinementList({ container: '#filter-widget, attribute: 'field_manufacturer', }), ]);
属性选项定义了我们想要显示分面的字段名称。 请记住,这也需要在 Algolia 仪表板中进行预配置。
最后,让我们添加分页以显示更多结果。
search.addWidgets([ instantsearch.widgets. pagination({ container: '#pagination, }), ]);
我们完成了! 这就是最终代码的样子
const index_name = drupalSettings.index_name; const app_id = drupalSettings.app_id; const api_key = drupalSettings.api_key; if(index_name && app_id && api_key) { const search = instantsearch({ indexName: index_name, searchClient: algoliasearch(app_id, api_key), }); search.addWidgets([ instantsearch.widgets.searchBox({ container: '#searchbox', }), instantsearch.widgets.hits({ container: '#hits', transformItems(items) { return items.map(item => ({ ...item, url: item.uri.replace('public://', '/sites/default/files/'), })); }, templates: { item: ` <h3 class="title">{{{_highlightResult.title.value}}}</h3> <p class="detail"> {{{_highlightResult.field_manufacturer.value}}} </p> <p class="uri"><img src="{{{url}}}" /></p>`, }, }), instantsearch.widgets.refinementList({ container: '#filter-widget', attribute: 'field_manufacturer', }), instantsearch.widgets.pagination({ container: '#pagination', }) ]); search.start(); } else { throw "Algolia settings missing";}
最后的想法
当我们结束我们的两部分文章系列时,我们希望您对 Algolia 有足够的了解。 我们已经介绍了如何将 Algolia 搜索与 Drupal 集成以构建强大的消费级搜索。 我们还讨论了使用 InstantSearch 库来自定义搜索结果。 正在寻找一家 100% 专注于 Drupal 的公司,可以帮助您建立雄心勃勃的 Drupal 体验,同时利用网络的精华? 我们很乐意听取您的意见!