前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Wordpress】ajax 实现站内搜索

【Wordpress】ajax 实现站内搜索

作者头像
redszhao
发布2021-08-09 15:21:30
1.3K0
发布2021-08-09 15:21:30
举报
文章被收录于专栏:北先生

写在前面:

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

遇到问题:

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

问题1 – 模糊搜索:

大胆尝试:

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

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

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

于是我们试一试:

Shell

$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);

123456789101112131415

$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);

Shell

// 判断查询的结果,检查是否有文章 if ( $result->have_posts() ) : // 通过查询的结果,开始主循环 while ( $result->have_posts() ) : $result->the_post(); //获取到特定的文章 // 要输出的内容,如标题、日期等 endwhile; endif;

1234567891011

// 判断查询的结果,检查是否有文章if ( $result->have_posts() ) :     // 通过查询的结果,开始主循环    while ( $result->have_posts() ) :        $result->the_post(); //获取到特定的文章         // 要输出的内容,如标题、日期等     endwhile;endif;

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

转换思路:

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

Shell

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, ]; } } }

1234567891011121314151617

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 来做过滤。

Shell

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

1234

//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() ) 这个代码之前!!!!

Shell

/ 文章搜索 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' );

123456789101112131415161718192021222324252627282930313233343536373839404142

/ 文章搜索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

效果展示:

问题3 – 异步渲染

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

Shell

$("#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); } }); } }

12345678910111213141516171819202122232425

$("#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 语法进行拼接。

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

Shell

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

1234567891011121314151617181920212223

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 worldvar str1 = "我叫{0},性别{1}".format("美男子", "男"); //log 我叫美男子,性别男var user = {name: "美男子",sex: "男",age: 20};var str2 = "我叫{name},性别{sex},今年{age}岁".format(user); //我叫美男子,性别男,今年20

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

Shell

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));

123456789101112131415

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/

喜欢(4) 打赏

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年5月26日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面:
    • 遇到问题:
      • 问题1 – 模糊搜索:
        • 大胆尝试:
        • 转换思路:
      • 问题2 – 接口对接:
        • 实现原理:
        • 具体接口:
        • 调用方式:
        • 效果展示:
      • 问题3 – 异步渲染
        • 效果演示:
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档