WordPress在主题中修改用户邮箱的简单方法

2,535次阅读
一条评论

众所周知,大部分WordPress的主题不带修改用户邮箱的功能,想要修改用户绑定的邮箱,需要进入网站后台个人资料中进行修改,而且恕我直言,WordPress修改邮箱有点不人性化的,就像我当开始修改邮箱的时候一脸懵。
后来才发现原来要保存,并不是常规的点击按钮,弹出窗口输出新邮箱,点击提交,然后验证邮箱就行的操作。
但是不是所有的主题都支持常规用户进入后台,那么绑定的邮箱是不是就无法修改了呢?
其实不完全对,我们可以对WordPress主题增加用户修改邮箱的功能,让注册用户在登录后,进入到个人中心进行修改。
当然,如果你说WordPress主题中也没有用户中心,那我真的就只能表示爱莫能助了。
PS:这里建议使用Puock主题,真的很赞。


废话不多说,我们直接进入实现的简单方法,以Puock主题为例:


修改用户中心代码

首先,我们找到用户中心的代码所在位置,编辑代码。
wordpress-theme-puock/inc/classes/PuockUserCenter.php
找到以下代码:

    private static function register_basic_menus()
    {
        self::$menus['profile'] = [
            'title' => __('个人资料', PUOCK),
            'subtitle' => __('您的基本个人资料', PUOCK),
            'call' => array(__CLASS__, 'page_profile'),
        ];
    }

这段代码不用做修改,找到他的目的只是为了找到“page_profile”回调函数,这里意味着,回调函数所属的代码就是用户中心的个人资料页面代码。


根据上面的回调函数"page_profile"找到下面这段代码:

    public static function page_profile()
    {
        $userinfo = get_userdata(get_current_user_id());
        ?>
        <form action="<?php echo pk_ajax_url('pk_user_update_profile') ?>" class="ajax-form" data-no-reset>
            <div class="mb-3 row">
                <label class="col-sm-2 col-form-label">ID</label>
                <div class="col-sm-10">
                    <input type="text" readonly class="form-control" value="<?php echo $userinfo->ID ?>">
                </div>
            </div>
            <div class="mb-3 row">
                <label class="col-sm-2 col-form-label">用户名</label>
                <div class="col-sm-10">
                    <input type="text" readonly class="form-control" value="<?php echo $userinfo->user_nicename ?>">
                    <small class="c-sub">用户名不可更改</small>
                </div>
            </div>
            <div class="mb-3 row">
                <label class="col-sm-2 col-form-label">昵称</label>
                <div class="col-sm-10">
                    <input name="nickname" type="text" class="form-control" value="<?php echo $userinfo->nickname ?>">
                </div>
            </div>
            <div class="mb-3 row">
                <label class="col-sm-2 col-form-label">网站地址</label>
                <div class="col-sm-10">
                    <input name="user_url" type="url" class="form-control" value="<?php echo $userinfo->user_url ?>">
                </div>
            </div>
            <div class="mb-3 row">
                <label class="col-sm-2 col-form-label">个人说明</label>
                <div class="col-sm-10">
                    <textarea name="description" class="form-control"
                              rows="4"><?php echo $userinfo->description ?></textarea>
                </div>
            </div>
            <div class="mb-3 text-center">
                <button class="btn btn-primary btn-sm" type="submit">提交保存</button>
            </div>
        </form>
        <?php
    }

我们要对上面这段代码进行修改。
在用户名或者昵称的下面增加这段代码:

            <div class="mb-3 row">
                <label class="col-sm-2 col-form-label">绑定邮箱</label>
                <div class="col-sm-10">
                    <div class="row align-items-center">
                        <div class="col-6">
                            <input type="text" readonly class="form-control" value="<?php echo $userinfo->user_email ?>">
                        </div>
                        <div class="col-6 d-flex">
                            <button id="change-email-btn" class="btn btn-primary btn-sm" type="button">更换邮箱</button>
                        </div>
                    </div>
                </div>
            </div>
            <div id="change-email" style="display: none;">
                <div class="mb-3 row">
                    <label class="col-sm-2 col-form-label">新邮箱地址</label>
                    <div class="col-sm-10">
                        <div class="row align-items-center">
                            <div class="col-6">
                                <input name="new_email" type="email" class="form-control" placeholder="请输入新邮箱地址">
                            </div>
                            <div class="col-6 d-flex">
                                <button id="submit-email" class="btn btn-primary btn-sm" type="button">提交更改</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

然后在代码尾部的</form><?php中间,增加下面这段代码:

        <script>
        jQuery(function($) {
            $('#change-email-btn').on('click', function() {
                $('#change-email').toggle();
            });

            $('#submit-email').on('click', function() {
                var newEmail = $('input[name="new_email"]').val();
                if (newEmail) {
                    $.ajax({
                        url: '<?php echo pk_ajax_url('pk_user_update_email') ?>',
                        type: 'POST',
                        data: {
                            new_email: newEmail,
                            action: 'pk_user_update_email',
                            security: '<?php echo wp_create_nonce('pk-update-email-nonce'); ?>'
                        },
                        success: function(response) {
                            if (response.success) {
                                // alert(response.data.message);
                                window.Puock.toast(response.data.message, TYPE_SUCCESS);
                            } else {
                                // alert(response.data.message);
                                window.Puock.toast(response.data.message, TYPE_DANGER);
                            }
                        },
                        error: function(xhr, status, error) {
                            console.error(xhr.responseText);
                        }
                    });
                } else {
                    window.Puock.toast('请输入新邮箱地址', TYPE_DANGER);
                }
            });
        });
        </script>

上面这段JS的意思简单解释:
1、$('#change-email-btn').on('click', function() { ... }) :绑定点击事件,点击“更换邮箱”按钮时,打开“新邮箱地址”输入框。
2、$('#submit-email').on('click', function() { ... }) :绑定点击事件,点击“提交更改”按钮时,执行内部函数。
3、var newEmail = $('input[name="new_email"]').val(); :获取表单中名为new_email框的值,就是新邮箱地址。
4、通过$.ajax({ ... })发起了一个 AJAX 请求,其中,url: '<?php echo pk_ajax_url('pk_user_update_email') ?>'指定了 AJAX 请求的目标 URL,这里是一个 PHP 函数 pk_ajax_url() 的返回值,用于处理用户更新邮箱的请求。
5、type: 'POST' :指定了请求的 HTTP 方法为 POST。
6、data: { ... } :设置了要发送到服务器的数据。其中包括了新邮箱地址 new_email、动作标识 action、以及一个安全性验证参数 security。
7、success: function(response) { ... } :定义了请求成功时的回调函数。
8、error: function(xhr, status, error) { ... } :定义了请求失败时的回调函数。
9、window.Puock.toast() :为了适配Puock主题的提示方式。


增加AJAX处理回调函数

将下面这段代码添加到主题的functions.php文件尾部,如果有子主题,可以添加到子主题的functions.php文件中。

//更换邮箱
add_action('wp_ajax_pk_user_update_email', 'pk_user_update_email_callback');

function pk_user_update_email_callback() {
    check_ajax_referer('pk-update-email-nonce', 'security');

    // 验证用户是否已登录
    if (!is_user_logged_in()) {
        wp_send_json_error(array('message' => '请先登录'));
    }

    $newEmail = isset($_POST['new_email']) ? sanitize_email($_POST['new_email']) : '';

    if (!is_email($newEmail)) {
        wp_send_json_error(array('message' => '请输入有效的邮箱地址'));
    }

    $userinfo = wp_get_current_user();
    $userId = $userinfo->ID;
    $oldEmail = $userinfo->user_email;

    if ($newEmail === $oldEmail) {
        wp_send_json_error(array('message' => '邮箱与原邮箱相同'));
    }

    $site_title = get_bloginfo('name'); // 获取网站标题
    $site_url = get_site_url(); // 获取网站URL
    $username = wp_get_current_user()->user_login; // 获取用户名

    // 检查邮箱是否已被其他用户绑定
    $users_with_email = get_user_by('email', $newEmail);

    if ($users_with_email && $users_with_email->ID !== $userId) {
        // 如果其他用户已经绑定了该邮箱,则返回拒绝信息
        wp_send_json_error(array('message' => '邮箱已被其他用户绑定'));
    }

    // 生成确认密钥
    $confirmation_key = wp_generate_password(50, false);

    // 设置到期时间(例如,5分钟后)
    $expiry_timestamp = time() + (5 * 60); // 有效期为5分钟

    // 将到期时间存储到用户的元数据中
    update_user_meta($userId, 'email_confirmation_expiry', $expiry_timestamp);
    update_user_meta($userId, 'email_confirmation_key', $confirmation_key);    // 将确认密钥存储到用户的元数据中
    update_user_meta($userId, 'email_confirmation_newmail', $newEmail);    // 将新邮箱存储到用户的元数据中
    update_user_meta($userId, 'email_confirmation_userid', $userId);    // 将用户ID存储到用户的元数据中

    // 发送确认邮件
    $subject = '['.$site_title.'] 电子邮箱地址变更请求';
    $confirmation_link = add_query_arg(array('u'=>$userId,'key' => $confirmation_key), get_permalink(get_page_by_path('email-confirmation')));
    $message = "<div style=\"font-size: 14px; font-family: Arial, sans-serif;\">
            <p>您好, $username</p>
            <p>您最近请求修改您账户的电子邮箱地址。</p>
            <p>如果您确实要修改,请点击以下链接:<br />
            <a href=\"$confirmation_link\">$confirmation_link</a></p>
            <p>注意:链接有效期为:5分钟,超时请重新提交请求。</p>
            <p>如果您并未请求修改,则可安全的忽视并删除此邮件。</p>
            <p>此邮件被发送至 $newEmail</p>
            <p>祝好,<br>$site_title 全体成员敬上</p>
            <p><a href=\"$site_url\">$site_title</a></p>
            </div>";
    $headers[] = 'Content-Type: text/html; charset=UTF-8';
    $send_email = wp_mail($newEmail, $subject, $message, $headers);

    if ($send_email) {
        wp_send_json_success(array('message' => '邮件发送成功,请注意查收', 'expiry_timestamp' => $expiry_timestamp));
    } else {
        wp_send_json_error(array('message' => '邮件发送失败,请稍后重试'));
    }

    wp_die();
}

上面这段PHP的意思简单解释:
1、add_action('wp_ajax_pk_user_update_email', 'pk_user_update_email_callback'); :这行代码将函数pk_user_update_email_callback注册为一个 AJAX 动作处理器。当 AJAX 请求中的动作参数为pk_user_update_email时,WordPress 将调用此函数处理请求。
2、function pk_user_update_email_callback() { ... } :这是处理 AJAX 请求的函数的定义。
3、check_ajax_referer('pk-update-email-nonce', 'security'); :这行代码检查AJAX请求中的安全性验证参数,以确保请求是合法的。pk-update-email-nonce是用于验证的 nonce(一次性令牌),用于防止 CSRF(跨站请求伪造)攻击。
4、if (!is_user_logged_in()) { ... } :这段代码检查用户是否已登录。
5、$newEmail = isset($_POST['new_email']) ? sanitize_email($_POST['new_email']) : ''; :这行代码获取并清理 AJAX 请求中的新邮箱地址,并将其存储在 $newEmail 变量中。
6、if (!is_email($newEmail)) { ... } :这段代码检查新邮箱地址的格式是否有效。
7、$userinfo = wp_get_current_user(); :这行代码获取当前用户的信息,包括用户ID和当前邮箱地址。
8、if ($newEmail === $oldEmail) { ... } :这段代码检查新邮箱地址是否与当前邮箱地址相同。
9、$users_with_email = get_user_by('email', $newEmail); :这行代码检查新邮箱地址是否已被其他用户绑定。
10、wp_generate_password(50, false) :生成一个长度为 50 个字符的随机密码作为确认密钥。
11、time() + (5 * 60) :计算出到期时间,这里设置为当前时间加上 5 分钟。
12、update_user_meta();存储到用户的元数据中,以便后续验证和处理。
13、后面的一段是用来构建确认邮件内容,包括确认链接、提示信息等。
14、wp_mail() :发送确认邮件到用户提供的新邮箱地址。
15、if ($send_email) { ... } :根据发送邮件的结果,返回相应的成功或失败消息。
16、wp_die(); :这行代码确保在处理完 AJAX 请求后结束脚本的执行,以防止额外的输出。


验证用户邮箱地址

在主题pages目录下新建名为email-confirmation-template.php的文件并复制以下代码粘贴到其中,如果有子主题,可以在子主题的pages目录下新建。

<?php
/*
Template Name: 邮箱更换模板
*/

// 获取确认链接中的参数
$confirmation_key = isset($_GET['key']) ? $_GET['key'] : '';
$user_id = isset($_GET['u']) ? $_GET['u'] : '';

// 确认链接参数存在时执行以下操作
if ($confirmation_key) {
    // 获取用户的邮箱确认信息
    $stored_key = get_user_meta($user_id, 'email_confirmation_key', true);
    $expiry_timestamp = get_user_meta($user_id, 'email_confirmation_expiry', true);
    $new_email = get_user_meta($user_id, 'email_confirmation_newmail', true);
    $stored_user_id = get_user_meta($user_id, 'email_confirmation_userid', true);

    // 验证确认链接的有效性
    if ($confirmation_key === $stored_key && $expiry_timestamp && $expiry_timestamp > time() && $stored_user_id == $user_id) {
        // 更新用户邮箱地址
        $update_email = wp_update_user(array('ID' => $stored_user_id, 'user_email' => $new_email));

        // 邮箱地址更新成功
        if (!is_wp_error($update_email)) {
            // 删除确认密钥和到期时间
            delete_user_meta($stored_user_id, 'email_confirmation_key');
            delete_user_meta($stored_user_id, 'email_confirmation_expiry');
            delete_user_meta($stored_user_id, 'email_confirmation_newmail');
            delete_user_meta($stored_user_id, 'email_confirmation_userid');

            // 显示确认成功消息
            $success_message = '邮箱地址已成功更改为' . $new_email;
            echo '<div class="confirmation-message">' . $success_message . '</div>';
        } else {
            // 显示确认失败消息
            $error_message = '邮箱地址更改失败,请联系管理员';
            echo '<div class="error-message">' . $error_message . '</div>';
        }
    } elseif ($stored_user_id != $user_id) {
        // 显示用户ID不匹配消息
        $invalid_id_message = '用户ID不匹配,禁止修改他人账户。';
        echo '<div class="error-message">' . $invalid_id_message . '</div>';
    } elseif ($expiry_timestamp <= time()) {
        // 显示确认链接已过期消息
        $expired_message = '链接已过期,请重新发起请求。';
        echo '<div class="error-message">' . $expired_message . '</div>';

        // 清除过期的元数据
        delete_user_meta($user_id, 'email_confirmation_key');
        delete_user_meta($user_id, 'email_confirmation_expiry');
        delete_user_meta($user_id, 'email_confirmation_newmail');
        delete_user_meta($user_id, 'email_confirmation_userid');
    } else {
        // 显示确认链接无效消息
        $invalid_message = '链接无效,请确认您的请求。';
        echo '<div class="error-message">' . $invalid_message . '</div>';
    }
} else {
    // 显示无效请求消息
    $invalid_request_message = '无效的请求,请提供确认密钥。';
    echo '<div class="error-message">' . $invalid_request_message . '</div>';
}
?>

上面这段PHP的意思简单解释:
1、$confirmation_key = isset($_GET['key']) ? $_GET['key'] : '';$user_id = isset($_GET['u']) ? $_GET['u'] : ''; :这两行代码分别获取 URL 参数中的确认密钥和用户ID。
2、$confirmation_key :存在时,表示有确认链接参数传递过来,执行以下操作。
3、get_user_meta() :函数获取用户的元数据,包括确认密钥、到期时间、新邮箱地址和用户 ID。
4、然后是一系列的判断,检查确认密钥是否与存储的密钥匹配,并且确认链接是否过期,验证存储的用户 ID 是否与传递的用户 ID 匹配。
5、如果确认链接有效且都成功匹配,则执行wp_update_user()函数更新用户的邮箱地址。
6、如果邮箱地址更新成功,删除确认密钥和到期时间的元数据,并返回成功消息,否则返回失败消息。
7、如果确认链接无效,根据不同的情况显示相应的错误消息,如链接过期、ID不匹配等。


WordPress增加页面

进入WordPress后台,在页面中增加一个页面,模板选择“邮箱更换模板”,别名改为email-confirmation然后保存模板。


到此,应该就可以在用户中心修改用户绑定邮箱了!

以上代码可能会存在错误,如有,请在留言区域反馈,我们一起进行改进、

沛霖主页 mp_wx_6a98a928c4

共计15人点赞,其中2人来自小程序

正文完
微信扫码打开小程序体验更多功能
post-qrcode
 15
沛霖主页
版权声明:本站原创文章,由 沛霖主页 2023-03-18发表,共计11366字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(一条评论)
小二blog 评论达人 LV.1
2024-05-01 15:10:48 回复

赞赞赞,非常实用的功能,谢谢站长的分享! :loveyou:

 Windows  Chrome  中国吉林省松原市联通