WordPress分类标签AI自动补全功能实现教程

 在制作这个功能前,我没有去搜索有没有相关的功能插件,所以如果你已经找到了功能插件,我觉得可以不用看教程手动麻烦。

此工具的主要功能为:解决wordpress在建设中文网站,由于中文的分类、标签无法自动转换成英文而使用,中文都是转码了,很不友好SEO,而且市面常见的转拼音,我觉得对于谷歌SEO优化属于没啥意义,SEO一向以精细化为准,所以开始了以下功能的开发。

如果你也想跟我一样手动操作下,那么请跟着我下面的步骤。

1、备份数据库

再开始修改前备份我们的网站数据库是很好的习惯,我的是MySQL,想必大家大多都是这个。

2、检查关于分类、标签的表

表前缀_terms,内有如下字段:

字段名含义
term_id每个分类、标签或自定义分类的唯一ID,用于在其他表中引用。
name分类、标签或自定义分类的名称,用户在后台创建或编辑时输入的。
slugURL友好名称,基于name自动生成,用于构建分类等的URL。
term_group一个保留字段,现代WordPress中通常不被直接使用,可能用于高级用例或自定义开发。

需要根据 name 完善 slug 值,那么思路就是根据name的值提交Prompt给AI生成转换的英文,当然AI会生成一些别的提示词在里面,这时候我们需要过滤出英文字段。

第一轮测试如下:

更新成功:爆款内容创作 -> 1buzzworthycontentcreation2
更新成功:小红书专业号 -> xiaohongshuprofessionalaccount
更新成功:无需露脸直播 -> livewithoutvisibleface
更新成功:顶部导航 -> topnavigation
更新成功:家庭摄影 -> familyphotography
更新成功:精准人群营销 -> precisiontargetedmarketing
更新成功:高效提示词编写 -> efficientpromptwordcreation
更新成功:创意表达 -> creativeexpression
更新成功:快速上手视频号 -> quickstartvideoplatform
更新成功:精准曝光提升 -> precisionexposureenhancement
更新成功:抖音AI数字人 -> tiktokaidigitalhuman
更新成功:WordPress -> wordpress

很显然,不是我们想要的结果,英文中间的空格也被过滤掉了。

经过几轮测试,发现过滤效果都不是很理想,还是得从Prompt工程入手。

目前调试出的这个Prompt貌似可行,代入脚本继续尝试。

又经过十几轮测试,发现还是会有点小问题,批量去做还是有5%左右误差,当分类标签变多,不是很好维护,还是得人工审核,于是还是做了半手动的脚本:

搞定,并没有完全搞定,此时生成的英文中间有空格,不是-链接,wp是无法访问这种链接,空格在浏览器中解释会转码导致无法访问,还需要进一步优化,最终做出了插件形式,当然关注我的朋友,我直接送你一份在线版,已加鉴权,管理员登录才可以访问该页面。

主要思路有:

1、查出表前缀_terms表中slug值为空(非Null),且不是英文,包含%号中文转码的字段

2、slug显示出原始转码的字符,输入修改的信息点击修改后更新SQL表数据

3、点击AI生成,请求api发送转英文Prompt带入当前name值,返回的时候要过滤英文中间空格替换为-破折号,跟检查尾部是否含有.(若有则删除),另检查是否包含中文(包含则过滤)

最终修改_terms表slug的在线版为:

slug代码示例:

<?php
// 引入 WordPress 配置文件
require_once('../wp-config.php');

// 加载 WordPress 环境
require_once('../wp-load.php'); // 根据您的目录结构调整路径

// 检查用户是否已登录并且是管理员
if (!is_user_logged_in() || !current_user_can('manage_options')) {
    wp_redirect(wp_login_url()); // 未登录或没有权限,重定向到登录页面
    exit();
}

// 创建 MySQLi 连接
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

// 检查连接
if ($mysqli->connect_error) {
    die('连接失败: ' . $mysqli->connect_error);
}

// 每页显示的条数
$limit = 10;
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$offset = ($page - 1) * $limit;

// 处理更新请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $term_id = $_POST['term_id'];
    $slug = $_POST['slug'];

    // 更新数据库中的 slug
    $update_stmt = $mysqli->prepare("UPDATE 表前缀_terms SET slug = ? WHERE term_id = ?");
    $update_stmt->bind_param('si', $slug, $term_id);
    $update_stmt->execute();
    $update_stmt->close();
    
    header("Location: " . $_SERVER['PHP_SELF'] . "?page=$page"); // 更新后重定向
    exit();
}

// 查询 表前缀_terms 表中的数据(包含 slug 为空字符串或包含 % 的记录)
$stmt = $mysqli->prepare("SELECT term_id, name, slug FROM 表前缀_terms WHERE slug = '' OR slug LIKE '%\%%' LIMIT ?, ?");
$stmt->bind_param('ii', $offset, $limit);
$stmt->execute();
$result = $stmt->get_result();
$terms = $result->fetch_all(MYSQLI_ASSOC);

// 查询总记录数(包含 slug 为空字符串或包含 % 的记录)
$total_stmt = $mysqli->query("SELECT COUNT(*) FROM 表前缀_terms WHERE slug = '' OR slug LIKE '%\%%'");
$total_terms = $total_stmt->fetch_row()[0];
$total_pages = ceil($total_terms / $limit);
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>表前缀 Terms 可编辑表</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body {
            background-color: #f8f9fa; /* 背景颜色 */
        }
        h1 {
            margin-bottom: 20px; /* 标题底部间距 */
        }
        .table th, .table td {
            vertical-align: middle; /* 垂直居中 */
        }
        .pagination {
            justify-content: center; /* 中心对齐 */
        }
        .form-control {
            width: 80%; /* 输入框宽度 */
            display: inline-block; /* 行内块显示 */
        }
        .btn-primary, .btn-warning {
            margin-left: 10px; /* 按钮左侧间距 */
        }
    </style>
    <script>
        function generateSlug(termId, name) {
            const prompt = `请将【${name}】转换成英文,直接输出转换的英文,不要有任何其他的信息。`;
            fetch('slug_generator.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ prompt }) // 修改为传递 prompt
            })
            .then(response => response.json())
            .then(data => {
                if (data.slug) {
                    document.querySelector(`#slug_${termId}`).value = data.slug; // 填充到相应的输入框
                } else {
                    alert(data.error || '生成的 slug 无效,请重试。');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                alert('请求失败,请重试。');
            });
        }
    </script>
</head>
<body>
<div class="container mt-5">
    <h1 class="text-center">表前缀 Terms 可编辑表</h1>
    <table class="table table-bordered table-striped">
        <thead class="table-dark">
            <tr>
                <th>Term ID</th>
                <th>Name</th>
                <th>Slug</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($terms as $term): ?>
                <tr>
                    <td><?php echo htmlspecialchars($term['term_id']); ?></td>
                    <td><?php echo htmlspecialchars($term['name']); ?></td>
                    <td>
                        <form method="POST" action="" class="d-flex">
                            <input type="hidden" name="term_id" value="<?php echo htmlspecialchars($term['term_id']); ?>">
                            <input type="text" id="slug_<?php echo htmlspecialchars($term['term_id']); ?>" name="slug" value="<?php echo htmlspecialchars($term['slug']); ?>" class="form-control" required>
                            <button type="submit" class="btn btn-primary">修改</button>
                            <button type="button" class="btn btn-warning" onclick="generateSlug(<?php echo htmlspecialchars($term['term_id']); ?>, '<?php echo htmlspecialchars($term['name']); ?>')">AI生成</button>
                        </form>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

    <!-- 分页 -->
    <nav>
        <ul class="pagination">
            <?php for ($i = 1; $i <= $total_pages; $i++): ?>
                <li class="page-item <?php echo $i === $page ? 'active' : ''; ?>">
                    <a class="page-link" href="?page=<?php echo $i; ?>"><?php echo $i; ?></a>
                </li>
            <?php endfor; ?>
        </ul>
    </nav>
</div>

<script src="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

<?php
// 关闭连接
$mysqli->close();
?>

slug_generator.php 文件为请求ai返回翻译的英文slug

再来修改表前缀_term_taxonomy这个表:

字段名称数据类型描述
term_taxonomy_idbigint(20)该字段是表的主键,唯一标识每个分类法项目,自动递增。
term_idbigint(20)关联到 wp_terms 表中的 term_id,用于将术语与分类法关联。
taxonomyvarchar(32)表示分类法的类型,例如 category(分类)、post_tag(标签)等,确定术语的分类类型。
descriptionlongtext对应术语的详细描述,可以是任意长度的文本。
parentbigint(20)如果该分类法项目有父项,则 parent 存储父项的 term_taxonomy_id,用于创建层级结构。
countbigint(20)该分类法下的条目数量,例如某个标签下有多少篇文章或某个分类下有多少内容。

处理思路:

1、主要是修改description,term_id跟上面表前缀_terms中的term_id关联,用于取栏目或者标签的name值来生成description

2、taxonomy分为category跟post_tag,大致逻辑与上面处理slug一致,只是描述要生成中文的,一句话。

3、前端显示逻辑,取出description为空(不是Null)的值,并联表查询对应的term_id的name值展示。

代码示例:

<?php
// 引入 WordPress 配置文件
require_once '../wp-config.php';

// 加载 WordPress 环境
require_once('../wp-load.php'); // 根据您的目录结构调整路径

// 检查用户是否已登录并且是管理员
if (!is_user_logged_in() || !current_user_can('manage_options')) {
    wp_redirect(wp_login_url()); // 未登录或没有权限,重定向到登录页面
    exit();
}


// 数据库配置
$servername = DB_HOST;
$username = DB_USER;
$password = DB_PASSWORD;
$dbname = DB_NAME;

// 创建数据库连接
$mysqli = new mysqli($servername, $username, $password, $dbname);

// 检查连接
if ($mysqli->connect_error) {
    die('连接失败: ' . $mysqli->connect_error);
}

// 每页显示的条数
$limit = 10;
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$offset = ($page - 1) * $limit;

// 处理更新请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $term_id = $_POST['term_id'];
    $description = $_POST['description'];

    // 更新数据库中的 description
    $update_stmt = $mysqli->prepare("UPDATE 表前缀_term_taxonomy SET description = ? WHERE term_id = ?");
    $update_stmt->bind_param('si', $description, $term_id);
    $update_stmt->execute();
    header("Location: " . $_SERVER['PHP_SELF'] . "?page=$page"); // 更新后重定向
    exit();
}

// 查询 表前缀_term_taxonomy 表中的数据(包含 description 为空的记录)
$stmt = $mysqli->prepare("SELECT term_taxonomy_id, term_id, taxonomy, description FROM 表前缀_term_taxonomy WHERE description = '' LIMIT ?, ?");
$stmt->bind_param('ii', $offset, $limit);
$stmt->execute();
$result = $stmt->get_result();
$taxonomies = $result->fetch_all(MYSQLI_ASSOC);

// 查询总记录数(包含 description 为空的记录)
$total_stmt = $mysqli->query("SELECT COUNT(*) FROM 表前缀_term_taxonomy WHERE description = ''");
$total_taxonomies = $total_stmt->fetch_row()[0];
$total_pages = ceil($total_taxonomies / $limit);

// 获取对应的 term name
$term_names = [];
if (!empty($taxonomies)) {
    $term_ids = implode(',', array_column($taxonomies, 'term_id'));
    $name_stmt = $mysqli->prepare("SELECT term_id, name FROM 表前缀_terms WHERE term_id IN ($term_ids)");
    $name_stmt->execute();
    $result = $name_stmt->get_result();
    $term_names = $result->fetch_all(MYSQLI_ASSOC);
    $term_names = array_column($term_names, 'name', 'term_id'); // term_id => name
}
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>表前缀 Term Taxonomy 可编辑表</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body {
            background-color: #f8f9fa; /* 背景颜色 */
        }
        h1 {
            margin-bottom: 20px; /* 标题底部间距 */
        }
        .table th, .table td {
            vertical-align: middle; /* 垂直居中 */
        }
        .pagination {
            justify-content: center; /* 中心对齐 */
        }
        .form-control {
            width: 80%; /* 输入框宽度 */
            display: inline-block; /* 行内块显示 */
        }
        .btn-primary, .btn-warning {
            margin-left: 10px; /* 按钮左侧间距 */
        }
    </style>
    <script>
        function generateDescription(termId, name) {
            const prompt = `请为【${name}】生成简短且吸引人的描述,字数控制在50到100个字符之间,内容应突出该产品的主要特点和优势。请使用中文。`;
            fetch('description_generator.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ prompt }) // 修改为传递 prompt
            })
            .then(response => response.json())
            .then(data => {
                if (data.description) {
                    document.querySelector(`#description_${termId}`).value = data.description; // 填充到相应的输入框
                } else {
                    alert(data.error || '生成的描述无效,请重试。');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                alert('请求失败,请重试。');
            });
        }
    </script>
</head>
<body>
<div class="container mt-5">
    <h1 class="text-center">表前缀 Term Taxonomy 可编辑表</h1>
    <table class="table table-bordered table-striped">
        <thead class="table-dark">
            <tr>
                <th>Term Taxonomy ID</th>
                <th>Term ID</th>
                <th>Name</th>
                <th>Taxonomy</th>
                <th>Description</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($taxonomies as $taxonomy): ?>
                <tr>
                    <td><?php echo htmlspecialchars($taxonomy['term_taxonomy_id']); ?></td>
                    <td><?php echo htmlspecialchars($taxonomy['term_id']); ?></td>
                    <td><?php echo htmlspecialchars($term_names[$taxonomy['term_id']] ?? '未知'); ?></td>
                    <td><?php echo htmlspecialchars($taxonomy['taxonomy']); ?></td>
                    <td>
                        <form method="POST" action="" class="d-flex">
                            <input type="hidden" name="term_id" value="<?php echo htmlspecialchars($taxonomy['term_id']); ?>">
                            <input type="text" id="description_<?php echo htmlspecialchars($taxonomy['term_id']); ?>" name="description" value="<?php echo htmlspecialchars($taxonomy['description']); ?>" class="form-control" required>
                            <button type="submit" class="btn btn-primary">修改</button>
                            <button type="button" class="btn btn-warning" onclick="generateDescription(<?php echo htmlspecialchars($taxonomy['term_id']); ?>, '<?php echo htmlspecialchars($term_names[$taxonomy['term_id']] ?? '未知'); ?>')">AI生成</button>
                        </form>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

    <!-- 分页 -->
    <nav>
        <ul class="pagination">
            <?php for ($i = 1; $i <= $total_pages; $i++): ?>
                <li class="page-item <?php echo $i === $page ? 'active' : ''; ?>">
                    <a class="page-link" href="?page=<?php echo $i; ?>"><?php echo $i; ?></a>
                </li>
            <?php endfor; ?>
        </ul>
    </nav>
</div>

<script src="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>
<?php
// 关闭连接
$mysqli->close();
?>

description_generator.php 同上述处理slug的api接口,只是换个接受Prompt,跟去掉对英文的过滤。

Comments

Popular posts from this blog

LEGO City Car Wash 60362 Toy Set

GOLOZA Modern Arc-Designed Digital Alarm Clock with Blue LED Display

掌握5W1H公式,让文生图更精准!