teppokoivula / search-engine

SearchEngine 是一个 ProcessWire CMS/CMF 模块,用于索引和搜索站点内容。

资助包维护!
teppokoivula

安装次数: 1,007

依赖项: 2

建议者: 0

安全: 0

星标: 16

关注者: 5

分支: 6

开放问题: 2

类型:pw-module


README

SearchEngine 是一个模块,可以创建页面内容的索引,并使其易于搜索。

用法

  1. 安装 SearchEngine 模块。

模块将在安装过程中自动创建一个索引字段,因此如果您不希望它被命名为 "search_index",您应该在安装之前定义一个自定义字段(通过站点配置)。您稍后也可以更改字段名称,但您必须更新站点配置或模块设置(在管理员中)中的 "index_field" 选项。

  1. 将索引字段添加到您想要使其可搜索的模板中。

您可以通过模板设置、字段设置(“操作”选项卡)或通过从 SearchEngine 模块的配置屏幕找到的“索引模板”设置将索引字段添加到模板。将字段添加到模板后,每次保存使用该模板的页面时,索引字段将自动存储可索引字段的内容。

  1. 使用选择器在站点搜索索引中查询值或向您的模板文件添加适当的渲染调用。

使用 SearchEngine 有三种方式,您可以选择最适合您工作流程的方式

  • 您可以直接像 ProcessWire 中的任何其他 textarea 字段一样查询 search_index 字段(或您之前决定的名称)。这允许您在您的网站上构建完全定制的搜索功能,同时 SearchEngine 负责索引内容。
  • 您可以使用 $modules->get('SearchEngine')->find($input->get->q) 调用来通过 SearchEngine 查找结果。显然,您可以将任何搜索字符串传递给 find 方法,我们在这里使用 "q" GET 参数仅作为一个示例。
  • 您可以通过向您的搜索页面模板文件添加渲染调用让 SearchEngine 处理整个搜索功能:$modules->get('SearchEngine')->render()。该 render 方法是调用多个底层方法的快捷方式,但您也可以省略它,而是分别调用 renderStylesrenderScriptsrenderResultsrenderForm

如果您希望 SearchEngine 为您处理所有标记,则简单的方法只需要一个方法调用

<?php namespace ProcessWire; ?>
<body>
    <?= $modules->get('SearchEngine')->render() ?>
</body>

您可以将一个数组传递给 render,仅渲染特定功能。以下是一个仅渲染表单和结果列表而省略样式和/或脚本的示例

<?php namespace ProcessWire; ?>
<body>
    <?= $modules->get('SearchEngine')->render(['form', 'results']) ?>
</body>

最后,这是如何分别渲染所有部分的方法 - 此方法涉及一些额外步骤,但比其他方法提供了更多对渲染输出的控制

<?php namespace ProcessWire;
$searchEngine = $modules->get('SearchEngine');
...
<head>
    <?= $searchEngine->renderStyles() ?>
    <?= $searchEngine->renderScripts() ?>
</head>
<body>
    <?= $searchEngine->renderForm() ?>
    <?= $searchEngine->renderResults() ?>
</body>

多语言使用(语言支持)

SearchEngine 支持索引多语言内容。一旦 ProcessWire 的原生多语言功能启用,可以通过将索引字段转换为 FieldtypeTextareaLanguage 来启用对多语言索引的支持。

高级使用

如果您使用前面提到的任何一种方法渲染结果列表,SearchEngine 将自动寻找其设置中定义的查询参数 - 如果找到(GET),则为您执行搜索查询。如果您不希望模块为您处理这部分,您也可以自己执行查询(或只是不渲染结果列表)。

您可以使用选择器像访问任何其他 ProcessWire 字段一样访问搜索索引字段

if ($q = $sanitizer->selectorValue($input->get->q)) {
    // This finds pages matching the query string and returns them as a PageArray:
    $results = $pages->find('search_index%=' . $q . ', limit=25');

    // Render results and pager with PageArray::render() and PageArray::renderPager():
    echo $results->render(); // PageArray::render()
    echo $results->renderPager(); // PageArray::renderPager()

    // ... or you iterate over the results and render them manually:
    echo "<ul>";
    foreach ($results as $result) {
        echo "<li><a href='{$result->url}'>{$result->title}</a></li>";
    }
    echo "</ul>";
}

注意:尽管您可以使用任何操作符进行选择器,但在查询索引时,您可能会发现 *=%= 操作符最为有用。您可以在 ProcessWire 的选择器文档 中了解更多关于选择器操作符的信息。默认情况下,此模块将使用 *= 操作符进行内置功能。

或者,您可以将查找操作委托给 SearchEngine 模块

// This performs the query and returns a \SearchEngine\Query object:
$query = $modules->get('SearchEngine')->find($input->get->q);

// This object can be rendered manually, or you can use \SearchEngine\Renderer to render it:
// (First param is an array of custom arguments, second is the Query object.)
echo $modules->get('SearchEngine')->renderResults([], $query);

JSON 输出

Renderer 类提供了将搜索结果作为 JSON 字符串返回的支持,这对于实现 AJAX 搜索功能特别有用。JSON 输出由 Renderer::renderResultsJSON() 方法返回,您可以通过 results_json_fields 配置选项自定义返回的键和值。

results_json_fields 是键和字段名的数组。有两个“特殊”字段名前缀 - template.parent. - 它们提供了访问模板和父页属性的方法。

以下是如何在您的代码中使用 renderResultsJSON() 方法的示例

// Get the SearchEngine module.
$se = $modules->get('SearchEngine');

// Find pages matching our keyword ("composer"). You could also omit the query and let SearchEngine
// grab the keyword from the configured query GET param (if present).
$query = $se->find('composer');

// Return results as JSON.
$json = $se->renderResultsJSON([
    'results_json_fields' => [
        'title' => 'title',
        'desc' => 'summary',
        'url' => 'url',
        'parent' => 'parent.title',
        'template' => 'template.label',
    ],
    'results_json_options' => JSON_PRETTY_PRINT,
], $query);

var_dump($json);

... 例如,可能得到以下输出

{
    "results": [
        {
            "title": "Git ignore (.gitignore) file",
            "desc": "<p>The Wireframe boilerplate site profile includes an opinionated .gitignore file based on Bare Minimum Git project.<\/p>",
            "url": "\/docs\/wireframe-boilerplate\/git-ignore-file\/",
            "parent": "Wireframe boilerplate",
            "template": "Basic page"
        },
        {
            "title": "Directory structure",
            "desc": "<p>The directory structure outlined here is loosely based on the <a href=\"http:\/\/framework.zend.com\/manual\/1.12\/en\/project-structure.project.html\" rel=\"nofollow\">recommended project directory structure for Zend Framework 1.x<\/a>. Each component has it's place in the tree, and each directory exists for a reason.<\/p>",
            "url": "\/docs\/directory-structure\/",
            "parent": "Docs",
            "template": "Basic page"
        },
        {
            "title": "Wireframe boilerplate",
            "desc": "<p>Wireframe boilerplate is a ProcessWire starter site profile based on the Wireframe output framework.<\/p>",
            "url": "\/docs\/wireframe-boilerplate\/",
            "parent": "Docs",
            "template": "Basic page"
        },
        {
            "title": "ProcessWire Composer Installer",
            "desc": "<p>ProcessWire Composer Installer provides <a href=\"https:\/\/getcomposer.org\/doc\/articles\/custom-installers.md\" rel=\"nofollow\">Composer custom installers<\/a> for ProcessWire CMS\/CMF modules and site profiles. While not strictly required by Wireframe, it is an easy way to get started with either Wireframe or the Wireframe Boilerplate site profile.<\/p>",
            "url": "\/docs\/processwire-composer-installer\/",
            "parent": "Docs",
            "template": "Basic page"
        }
    ],
    "count": 4,
    "total": 4
}

请注意,返回的字段值(对于特定的搜索结果)可能是一个空字符串,也可能为 null。null 返回值可能发生在您指定了一个对于该特定页面不存在的字段。

重建搜索索引

如果您想重建(重新创建)所有页面或匹配特定选择器的页面的搜索索引,您可以通过 Admin GUI(模块配置屏幕)进行,或者您可以通过 API 执行以下请求

// All indexable pages:
$modules->get('SearchEngine')->indexPages();

// Indexable pages matching a selector string:
$modules->get('SearchEngine')->indexPages('template=basic-page');

// Alternatively index just a single page (passing in a Page object):
$modules->get('SearchEngine')->indexPage($page);

选项

默认情况下,该模块将创建一个名为 'search_index' 的搜索索引字段,并在页面保存时将标题、标题、摘要和正文的值存储到该索引字段中。您可以通过 ProcessWire Admin 中的模块配置屏幕修改默认行为,或者在您的站点配置文件或其他适用位置定义 $config->SearchEngine 数组。

以下提供了可用选项的摘要。请注意,这不是一个完整的列表 - 请检查 SearchEngine.module.php 文件开头附近的 $defaultOptions 数组,以获取所有可用选项的列表。一些选项可以通过管理员(模块配置屏幕)进行修改,而 所有 选项都可以通过代码定义 - 如果您通过站点配置定义了一个选项,则它 不能 通过管理员覆盖。

您还可以将自定义选项传递给某些方法调用。例如,大多数以 render 前缀命名的方法接受一个自定义渲染参数数组(请参阅下面的“render_args”),这样您就可以在特定情况下选择性地覆盖模块和站点默认值。

$config->SearchEngine = [

    // Index field defines the field to store indexed data in. Default value is "search_index".
    'index_field' => 'search_index',

    // This is an array of all the fields you want to index. Currently there is no way to
    // index "all compatible fields", but such an option may be added in the future. (This
    // is, in fact, a matter of security: by indexing *all* fields you could inadvertently
    // expose sensitive data.)
    'indexed_fields' => [
        // ...
    ],

    // This is an array of fieldtypes that the module should be considered compatible with.
    // You should only modify these values if you're sure that the field in question is
    // indeed compatible with the indexing process.
    'compatible_fieldtypes' => [
        // ...
    ],

    // Currently prefixes contains just the "link" prefix – more may be added in the future.
    'prefixes' => [
        // The "link" prefix is added to indexed links and enables "link:https://..." queries.
        'link' => 'link:',
    ],

    // Find arguments are pretty self-explanatory. These are the defaults and apply only to
    // SearchEngine::find(); custom selectors are not affected.
    'find_args' => [
        'limit' => 20,
        'sort' => 'sort',
        'operator' => '*=',
        'query_param' => 'q',
        // The "selector_extra" option is appended to automatically generated selector string.
        // You might use this to, for example, return just a subset of all indexed templates.
        'selector_extra' => '',
    ],

    // This array is passed directly to the MarkupPagerNav core module, see
    // https://processwire.com/docs/front-end/markup-pager-nav/ for more details.
    'pager_args' => [
        // ...
    ],

    // Render arguments affect the rendered output from the SearchEngine module.
    'render_args' => [

        // At the moment there's only one "theme" available ("default").
        'theme' => 'default',

        // By default theme-files (styles and scripts) are served minified; setting
        // this option to `false` will serve unmodified, original assets instead.
        'minified_resources' => true,

        // Various attributes used by the search form and results list when rendered.
        'form_action' => './',
        'form_id' => 'se-form',
        'form_input_id' => 'se-form-input',
        'results_summary_id' => 'se-results-summary',
        'results_id' => 'se-results',

        // Summary of each result (in the search results list) is the value of this field.
        'result_summary_field' => 'summary',

        // Highlighting basically wraps each instance of the search term in the summary
        // text with a predefined tag and class (default element is `<strong></strong>`).
        'results_highlight_query' => true,

        // These settings define the fields used when search results are rendered as JSON.
        'results_json_fields' => [
            'title' => 'title',
            'desc' => 'summary',
            'url' => 'url',
        ],

        // This integer is passed to the json_encode call in renderResultsJSON method.
        // See https://php.ac.cn/json_encode for supported values.
        'results_json_options' => 0,

        // This defines whether a pager should be rendered at the end of the results list.
        'pager' => true,

        // Array of classes to use in templates. You can add new classes here as well.
        'classes' => [
            // ...
        ],

        // Array of strings to use in templates. You can add new classes here as well. Note
        // that most of these are `null` in the $defaultOptions array; the reason for this
        // is simply that methods cannot be called when declaring class properties, so the
        // values are set in SearchEngine::__construct().
        'strings' => [
            // ...
        ],

        // Template strings. These are used to render markup on the site.
        'templates' => [
            // ...
        ],

    ],

    // Currently the requirements array only holds the query min length argument.
    'requirements' => [
        'query_min_length' => 3,
    ],

];

自动生成搜索结果描述(摘要)

从版本 0.24.0 开始,SearchEngine 具有自动生成搜索结果描述的能力。您可以通过指定 _auto_desc 作为 desc 键的名称来触发此行为。请注意,但这有一些值得注意的注意事项

  • 在启用此功能之前,您必须 绝对 确定,您要索引的每一件事都可以公开显示。当 SearchEngine 自动生成描述时,它不知道索引的哪些部分打算公开显示,哪些部分可能只是为了使其可搜索而被添加到索引中。
  • 自动生成的描述可能至少在一段时间内包含来自多个字段的数据。这意味着此类摘录可能不是完全逻辑的(并且它们很可能不是完整的句子等。)

主题

SearchEngine 支持主题的概念。主题位于 themes 目录下,在各自的子目录下(例如 /themes/theme-name/),并且每个主题都需要包含(至少)一个配置文件(/themes/theme-name/config.php)。以下是一个主题配置文件的示例

<?php namespace ProcessWire;

$theme_args = [
    'theme_styles' => [
        // array of styles, such as:
        [
            'name' => 'style',
            'ext' => 'css',
        ],
    ],
    'theme_scripts' => [
        // array of scripts, such as:
        [
            'name' => 'script',
            'ext' => 'js',
        ],
    ],
    'render_args' => [
        // array of render arguments, such as:
        'form_id' => 'my-search-form',
        'strings' => [
            'results_heading' => __('Custom results heading'),
        ],
    ],
    'pager_args' => [
        // array of pager options
    ],
];

主题可能包含样式和脚本文件(夹),在这种情况下,还应有一个特定类型的目录来存储它们(例如 /themes/theme-name/scripts//themes/theme-name/styles/)。对于每个文件,都应有一个在 theme_stylestheme_scripts 数组中命名的“源”文件(例如 style.css),以及一个以 ".min" 命名的压缩版本(例如 style.min.css)。

注意:不建议修改模块目录中的文件,因为它们可能在更新中被覆盖。您可以通过搜索引擎模块配置屏幕的“高级”部分来配置自定义主题的路径。

要求

  • ProcessWire >= 3.0.112
  • PHP >= 7.1.0

安装

此模块可以像其他 ProcessWire 模块一样安装,只需将搜索引擎目录下载或克隆到您的 /site/modules/ 目录中。或者,您可以通过运行 composer require teppokoivula/search-engine 使用 Composer 安装搜索引擎。

开发

搜索引擎核心 JS 文件与 parcel.js 打包,主题样式使用 clean-css 压缩。这两个都只需要最少的配置,这就是为什么只需要在 package.json 中定义的 "build" 脚本。为了为搜索引擎构建生产资产

  • 全局安装 Parcel:npm install -g parcel-bundler
  • 全局安装 clean-css 和 clean-css-cli:npm install -g clean-css && npm install -g clean-css-cli
  • 在搜索引擎模块目录中运行构建脚本:npm run build

许可证

本项目受 Mozilla 公共许可证第 2.0 版本许可。