You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让WordPress插件在草稿文章创建后自动执行标题改写?

实现WordPress草稿自动改写标题并发布

问题概述

我开发了一款WordPress插件,可将草稿文章的标题改写为36-38字符长度,手动点击「Autofill」按钮能正常触发流程:调用ChatGPT改写标题、检查字符长度(不符合则重复调用)、更新标题并发布文章。但现在需要实现新草稿保存时自动启动该流程,尝试过钩子和cron任务但未成功,求可行方案。

解决方案

要实现自动触发,核心是利用WordPress的save_post钩子监听草稿创建事件,并将原前端的ChatGPT调用逻辑重构为PHP后端函数,避免前端依赖。以下是具体实现步骤和修改后的完整代码:

1. 核心修改点

  • 新增PHP版ChatGPT调用函数,替代前端AJAX逻辑
  • 注册save_post钩子,监听新草稿创建事件
  • 添加触发条件判断,仅在新草稿首次保存时执行
  • 保留循环调用逻辑,确保标题长度符合要求
  • 添加错误处理,避免流程中断

2. 修改后的完整代码

<?php
/*
Plugin Name: ChatGPT Dashboard
*/

// Add a custom menu item to the WordPress dashboard
function chatgpt_dashboard_menu() {
    add_menu_page(
        'ChatGPT Dashboard',
        'ChatGPT',
        'manage_options',
        'chatgpt-dashboard',
        'chatgpt_dashboard_page',
        'dashicons-format-chat',
        20
    );
}
add_action('admin_menu', 'chatgpt_dashboard_menu');

// Enqueue jQuery UI library
function chatgpt_enqueue_scripts() {
    wp_enqueue_script('jquery-ui-core');
    wp_enqueue_script('jquery-ui-draggable');
}
add_action('admin_enqueue_scripts', 'chatgpt_enqueue_scripts');

// Register plugin settings
function chatgpt_register_settings() {
    register_setting('chatgpt_options', 'chatgpt_api_key');
}
add_action('admin_init', 'chatgpt_register_settings');

// Callback function to display the ChatGPT dashboard page
function chatgpt_dashboard_page() {
    ?>
    <div class="wrap">
        <h1>ChatGPT Dashboard</h1>

        <!-- API Key settings form -->
        <form method="post" action="options.php">
            <?php settings_fields('chatgpt_options'); ?>
            <?php do_settings_sections('chatgpt_options'); ?>
            <table class="form-table">
                <tr valign="top">
                    <th scope="row">API Key</th>
                    <td><input type="text" name="chatgpt_api_key" value="<?php echo esc_attr(get_option('chatgpt_api_key')); ?>" /></td>
                </tr>
            </table>
            <?php submit_button(); ?>
        </form>

        <!-- Chat interface -->
        <div id="chat-container">
            <div id="chat-log"></div>
            <input type="text" id="user-input" placeholder="Type your message..." />
            <button id="submit-button">Send</button>
            <button id="autofill-button">Autofill</button>
        </div>
    </div>

    <script>
        (function ($) {
            $(document).ready(function () {
                // Function to handle user input and generate ChatGPT responses
                function handleUserInput() {
                    var userInput = $('#user-input').val();

                    // Get the API key from the WordPress options database
                    var apiKey = '<?php echo get_option("chatgpt_api_key"); ?>';

                    // Make sure the API key is provided
                    if (!apiKey) {
                        alert('Please enter an API key in the ChatGPT dashboard settings.');
                        return;
                    }

                    // Make an API call to ChatGPT to get a response
                    function callChatGPT() {
                        $.ajax({
                            url: 'https://api.openai.com/v1/chat/completions',
                            type: 'POST',
                            beforeSend: function (xhr) {
                                xhr.setRequestHeader('Authorization', 'Bearer ' + apiKey);
                                xhr.setRequestHeader('Content-Type', 'application/json');
                            },
                            data: JSON.stringify({
                                model: 'gpt-3.5-turbo',
                                messages: [
                                    { role: 'system', content: 'You are a user' },
                                    { role: 'user', content: userInput },
                                ],
                            }),
                            success: function (response) {
                                var chatLog = $('#chat-log');

                                if (!response.choices || !response.choices.length) {
                                    chatLog.append('<p><strong>Error:</strong> No response received</p>');
                                    return;
                                }

                                var botResponse = response.choices[0].message.content;

                                // Check if botResponse is an array
                                if (Array.isArray(botResponse)) {
                                    botResponse = botResponse.map(msg => msg.content).join('');
                                }

                                // Count the number of characters in the bot response
                                var characterCount = botResponse.length;

                                // Display the user input, bot response, and character count in the chat log
                                chatLog.append('<p><strong>You:</strong> ' + userInput + '</p>');
                                chatLog.append('<p><strong>Bot:</strong> ' + botResponse + '</p>');
                                chatLog.append('<p><strong>Character count:</strong> ' + characterCount + '</p>');

                                // Clear the user input field
                                $('#user-input').val('');

                                // Scroll to the bottom of the chat log
                                chatLog.scrollTop(chatLog.prop('scrollHeight'));

                                // Check if the character count is within the desired range (36, 37, or 38)
                                if (characterCount >= 36 && characterCount <= 38) {
                                    // Print the new title 5 times in a row
                                    for (let i = 0; i < 5; i++) {
                                        chatLog.append('<p><strong>New Title:</strong> ' + botResponse + '</p>');
                                    }
                                    
                                    // Update draft post and publish
                                    $.ajax({
                                        url: '<?php echo admin_url("admin-ajax.php"); ?>',
                                        type: 'POST',
                                        data: {
                                            action: 'create_draft_post',
                                            title: botResponse,
                                        },
                                        success: function (response) {
                                            console.log('Draft post updated:', response);
                                            chatLog.append('<p><strong>New Title:</strong> ' + botResponse + '</p>');
                                        },
                                        error: function (xhr, status, error) {
                                            console.error(error);
                                        },
                                    });

                                    return;
                                }

                                // Repeat the question until the character count is within the desired range
                                callChatGPT();
                            },
                            error: function (xhr, status, error) {
                                var chatLog = $('#chat-log');
                                chatLog.append('<p><strong>Error:</strong> ' + error + '</p>');
                                console.error(error);
                            },
                        });
                    }

                    callChatGPT();
                }

                // Handle user input when the submit button is clicked
                $('#submit-button').on('click', function (e) {
                    e.preventDefault();
                    handleUserInput();
                });

                // Handle user input when the enter key is pressed
                $('#user-input').on('keydown', function (e) {
                    if (e.keyCode === 13) {
                        e.preventDefault();
                        handleUserInput();
                    }
                });

                // Handle autofill button click
                $('#autofill-button').on('click', function (e) {
                    e.preventDefault();

                    // Get the draft posts
                    $.ajax({
                        url: '<?php echo admin_url("admin-ajax.php"); ?>',
                        type: 'POST',
                        data: {
                            action: 'get_draft_posts',
                        },
                        success: function (response) {
                            if (response && response.length) {
                                var draftTitle = response[0].post_title;
                                var autofillText = 'Summarize "' + draftTitle + '" to 38 characters';
                                $('#user-input').val(autofillText);
                                
                                // Automatically start the process of generating the response
                                handleUserInput();
                            }
                        },
                        error: function (xhr, status, error) {
                            console.error(error);
                        },
                    });
                });
            });
        })(jQuery);
    </script>
    <?php
}

// AJAX handler to retrieve draft posts
function chatgpt_get_draft_posts() {
    $draftPosts = get_posts(array(
        'post_status' => 'draft',
        'numberposts' => 1,
    ));
    wp_send_json($draftPosts);
}
add_action('wp_ajax_get_draft_posts', 'chatgpt_get_draft_posts');
add_action('wp_ajax_nopriv_get_draft_posts', 'chatgpt_get_draft_posts');

// AJAX handler to update the existing draft post with the new title and publish it
function chatgpt_create_draft_post() {
    $title = sanitize_text_field($_POST['title']);

    $draftPosts = get_posts(array(
        'post_status' => 'draft',
        'numberposts' => 1,
    ));

    if (empty($draftPosts)) {
        wp_send_json_error('No draft post found.');
        return;
    }

    $draftPost = $draftPosts[0];
    $draftPostID = $draftPost->ID;

    // Update the title of the draft post
    wp_update_post(array(
        'ID'         => $draftPostID,
        'post_title' => $title,
        'post_status' => 'publish',
    ));

    wp_send_json_success($draftPostID);
}
add_action('wp_ajax_create_draft_post', 'chatgpt_create_draft_post');
add_action('wp_ajax_nopriv_create_draft_post', 'chatgpt_create_draft_post');

// -------------------------- 新增自动处理逻辑 --------------------------
// PHP版ChatGPT调用函数
function chatgpt_call_api($prompt) {
    $api_key = get_option('chatgpt_api_key');
    if (!$api_key) return false;

    $url = 'https://api.openai.com/v1/chat/completions';
    $headers = array(
        'Authorization' => 'Bearer ' . $api_key,
        'Content-Type' => 'application/json'
    );
    $body = json_encode(array(
        'model' => 'gpt-3.5-turbo',
        'messages' => array(
            array('role' => 'system', 'content' => 'You are a professional title editor.'),
            array('role' => 'user', 'content' => $prompt)
        )
    ));

    $response = wp_remote_post($url, array(
        'headers' => $headers,
        'body' => $body,
        'timeout' => 30
    ));

    if (is_wp_error($response)) return false;
    
    $data = json_decode(wp_remote_retrieve_body($response), true);
    if (empty($data['choices'][0]['message']['content'])) return false;

    return trim($data['choices'][0]['message']['content']);
}

// 自动处理新草稿标题
function chatgpt_auto_process_draft($post_id, $post, $update) {
    // 跳过自动保存、修订版,仅处理新创建的草稿
    if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return;
    if ($update || $post->post_status !== 'draft') return;

    $original_title = $post->post_title;
    $prompt = "Summarize \"{$original_title}\" to a title with exactly 36-38 characters.";
    $new_title = '';
    $max_attempts = 5; // 限制最大尝试次数,避免无限循环
    $attempts = 0;

    // 循环调用直到符合长度要求或达到最大尝试次数
    while ($attempts < $max_attempts) {
        $new_title = chatgpt_call_api($prompt);
        if (!$new_title) break;

        $char_count = mb_strlen($new_title);
        if ($char_count >= 36 && $char_count <= 38) {
            // 更新标题并发布
            wp_update_post(array(
                'ID' => $post_id,
                'post_title' => $new_title,
                'post_status' => 'publish'
            ));
            break;
        }
        $attempts++;
        // 调整提示词,告知当前长度不符合要求
        $prompt = "Summarize \"{$original_title}\" to a title with exactly 36-38 characters. Current title is {$char_count} characters: {$new_title}";
    }
}
add_action('save_post', 'chatgpt_auto_process_draft', 10, 3);

3. 关键说明

  • save_post钩子触发条件:仅在新草稿首次创建时执行(排除自动保存、修订版和已发布文章更新)
  • ChatGPT调用限制:添加了max_attempts限制,避免因API返回始终不符合要求导致无限循环
  • 安全处理:对用户输入的标题进行sanitize_text_field过滤,确保数据安全
  • 错误处理:检测API调用失败情况,避免流程中断

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:49:52