【WordPress】ajax 实现站内搜索

写在前面:

最近想给自己的博客实现一个 站内搜索 功能,期望整个过程异步实现。这样用户体验度更好。

遇到问题:

  1. 如何实现文章的模糊匹配?
  2. wordpress 如何提供接口?
  3. 页面如何实现异步请求接口数据,并完成页面的渲染?

问题1 – 模糊搜索:

大胆尝试:

wordpress 原生自带有一个 wp_query 函数,它支持的参数非常完善灵活,实现整个网站与数据库的交互。比如调用最新文章、热门文章、自定义文章类型文章循环输出等。

在官方手册中也有介绍到:wp_query,支持多种 sql 语句的 比较符号:

【Wordpress】ajax 实现站内搜索

看!他说可以支持 like 或者 regexp 这种比较符号。

于是我们试一试:

$args   = [
    'posts_per_page'      => -1,  // 每页数量 -1 不限制数量
    'ignore_sticky_posts' => 1, // 
    'post_type'           => 'post', // 
    'post_status'         => 'publish', // 已经发布的文章
    'meta_query'          => [
        [
            'key'     => 'post_title',
            'value'   => 'Mac',
        //    'compare' => 'REGEXP',
            'compare' => 'LIKE',
        ],
    ],
];
$result = new WP_Query($args);
// 判断查询的结果,检查是否有文章
if ( $result->have_posts() ) :

    // 通过查询的结果,开始主循环
    while ( $result->have_posts() ) :
        $result->the_post(); //获取到特定的文章

        // 要输出的内容,如标题、日期等

    endwhile;
endif;

但是很遗憾,不知道是我的姿势不对,就是不起作用?? 如果有大佬解决了,望不吝赐教!

转换思路:

其实在数据库使用 like 的查询效率是非常低,所以我们可以把这一部分的逻辑由 php 自己实现。

if ($result->have_posts()) {
    while ($result->have_posts()) {
        $result->the_post();

        global $post;
        $post_title = get_the_title();
        // mb_stripos 不区分大小 判断字符串中是否存在另一个字符串
        if (mb_stripos($post_title, $keyword)) {
            $articles[] = [
                'id'         => get_the_ID(),
                'post_name'  => $post->post_name,
                'post_title' => $post_title,
                'post_date'  => $post->post_date,
            ];
        }
    }
}

所以,我们可以看到,通过 PHP 的 mb_stripos 可以实现字符串的模糊匹配,这样就可以筛选出我们想要的结果。

问题2 – 接口对接:

上面我们已经实现了文章的模糊匹配,接下来就要提供一个接口,来实现与前端的交互。所以,我们将会用到 wordpress 自带的 admin-ajax.php 文件。

实现原理:

要使用 admin-ajax.php 请求必然首先就是遇到如何使用 wordrpess 的钩子 hook 来做过滤。

//wp_ajax_nopriv_ 效验用户为未登录是启用的方法
add_action( 'wp_ajax_nopriv_search', 'search' );
//wp_ajax_ 效验用户为已登录是启用的方法
add_action( 'wp_ajax_search', 'search' );

具体接口:

我们看到上面 search 这个是我们要定义的搜索函数,逻辑就要用到了刚刚介绍的 模糊匹配 ,

但是其中几点需要注意到的是:

  1. header(“Content -Type: application/json”); // 指定返回头
  2. wp_die() //接口响应结束用这个函数结尾,否则会一直走到这个当前页面最下面,多返回一个 0;
  3. 需要将下面的代码添加到 if ( is_user_logged_in() ) 这个代码之前!!!!
/ 文章搜索
function search()
{
    $keyword = $_GET['keyword'] ?? $_GET['keyword'];
    // 指定返回头
    header("Content -Type: application/json");
    if (empty($keyword)) {
        echo $response = (json_encode([], JSON_UNESCAPED_UNICODE));
        wp_die();
    }
    $args     = [
        'posts_per_page'      => -1,
        'ignore_sticky_posts' => 1,
        'post_type'           => 'post',
        'post_status'         => 'publish',
    ];
    $result   = new WP_Query($args);
    $articles = [];
    if ($result->have_posts()) {
        while ($result->have_posts()) {
            $result->the_post();

            global $post;
            $post_title = get_the_title();
            if (mb_stripos($post_title, $keyword) !== false) {
                $articles[] = [
                    'id'         => get_the_ID(),
                    'post_name'  => $post->post_name,
                    'post_title' => $post_title,
                    'post_date'  => $post->post_date,
                ];
            }
        }
    }

    wp_reset_query();
    echo $response = (json_encode($articles, JSON_UNESCAPED_UNICODE));
    wp_die();
}

add_action( 'wp_ajax_nopriv_search', 'search' );
add_action( 'wp_ajax_search', 'search' );

调用方式:

示例:https://zhaoshuai.me/wp-admin/admin-ajax.php?action=search&keyword=cdn

上面我们用了 wordpress 的钩子函数,所以我们调用的时候用参数 action ,后面拼接相对应的 function

效果展示:

【Wordpress】ajax 实现站内搜索

问题3 – 异步渲染

其实很简单,前两部已经完成大部分的工作。我们只需要添加一个监听输入框值变化的事件,使用 JQuery 的 ajax 请求接口就OK了。

$("#input-search").bind("input propertychange", function (event) {
    search();
});

// 搜索文章
function search() {
    var host = document.location.host;
    var protocol = document.location.protocol;

    var keyword = $("#input-search").val();
    if (keyword.length > 0) {
        $.ajax({
            type: "GET",
            url: protocol + '//' + host + "/wp-admin/admin-ajax.php?action=search&keyword=" + keyword,
            data: {},
            dataType: "json",
            success: function (data) {
                addArticle(data);
            },
            error: function (data) {
                console.log(data);
            }
        });
    }
}

上面我们可以看到,这样可以正确拿到接口返回的数据,接下来就是最重要的数据拼装。

由于我们没有框架去做,只能将 Html 标签 与 Js 语法进行拼接。

我们这里是用了 正则表达式 ,写了一个规则,可以通过 键值 格式化我们定义好的字符串,来人上代码!

String.prototype.format = function () {
    if (arguments.length === 0) {
        return this;
    }
    var param = arguments[0];
    var s = this;
    if (typeof (param) == 'object') {
        for (var key in param)
            s = s.replace(new RegExp("\\{" + key + "\\}", "g"), param[key]);
        return s;
    } else {
        for (var i = 0; i < arguments.length; i++)
            s = s.replace(new RegExp("\\{" + i + "\\}", "g"), arguments[i]);
        return s;
    }
};

// 示例:
var str1 = "hello {0}".format("world"); //log   hello world
var str1 = "我叫{0},性别{1}".format("美男子", "男"); //log 我叫美男子,性别男
var user = {name: "美男子",sex: "男",age: 20};
var str2 = "我叫{name},性别{sex},今年{age}岁".format(user); //我叫美男子,性别男,今年20

下面我利用上面的这个 函数,格式化我们要渲染的每个元素。

var item = "<li id='post-{id}'>\n" +
    "        <time class='mod-archive__time' datetime='{post_date}'> {show_date} </time>\n" +
    "        <span>—</span>\n" +
    "        <a href='{post_link}' title='{post_title}'> {post_title} </a>\n" +
    "    </li>";

var fix = {
    'id': article['id'],
    'show_date': show_date,
    'post_date': article['post_date'],
    'post_title': article['post_title'],
    'post_link': protocol + '//' + host + '/' + article['post_name']
};

$("#articles").append(item.format(fix));

是不是整个流程就已经很流畅了!!!

效果演示:

http://simple.zhaoshuai.me/search/

【Wordpress】ajax 实现站内搜索
喜欢(6) 打赏

评论4

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #0
    学习了!
  2. #0
    Gel Viagra Amoxicillin 500 Mg Capsule Tev Buy Cialis Cialis Versus Levitra Viagra Kaufen Bei Apotheke
    KelSilt2020-01-17 13:19:38回复
  3. #0
    大佬,可以提供下代码下载地址吗?正好我用的也是cu主题。
    贼冷的冰雨2020-09-26 16:43:55回复
    • https://zhaoshuai.me/2019-06-14/ 看一下这个文章里面有下载链接
      zhaoshuai2020-09-27 10:36:20回复

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

小北在线

小北在线

  • 扫描二维码,微信联系 扫描二维码,微信联系