由于可以通过插件和主题实现几乎无限的可自定义性,因此WordPress从其博客平台的根源起已经走了很长一段路,如今已成为从在线商店到会员网站以及电子书编写平台的各种基于Web的应用程序的骨干。
传统上,只有网站管理员才能登录WordPress仪表板,但许多类似应用程序的新用法会发生以下变化:当需要对用户进行身份验证时,WordPress登录名会扩展到访问者和客户。
WordPress提供了用于管理用户角色和功能的良好工具,可以借助插件进一步扩展它们,但是对于专业人士而言,这还不够—您还需要确保用户体验符合您产品的需求。整个。 毕竟,在登录基于Web的应用程序时看到默认的(或样式简单的)WordPress登录屏幕可能会给人留下深刻的印象。
在这个由三部分组成的教程系列中,我将向您展示如何通过自定义登录和新用户注册功能以适合您的网站外观来解决此问题,而不违反WordPress的最佳做法。
您将在本教程中学到什么
默认情况下,WordPress使用外观漂亮但通用的登录屏幕,我们都非常熟悉:
屏幕可以正常工作,而且看起来一点也不差。 但是,当构建一个严肃的网站时,您没有保留默认主题,那么为什么要保留默认登录名呢?
可以使用CSS以及登录页面本身提供的许多操作和过滤器进行一些样式设置。 但是,尽管这些更改可以带来不错的结果,但我认为该方法仍然存在缺点,最重要的是,登录页面与网站的其余部分完全分开。
因此,今天我们不打算进行简单的外观更改,而是建立自己的登录页面。 感觉像是基于WordPress的网站的一部分,而不是其顶部的内容。
为此,在本教程中,我们将构建一个WordPress插件,以自定义WordPress页面和用于呈现登录表单的简码的组合替换登录页面。 在此过程中,您将了解WordPress登录流程,了解我们可以挂钩并根据需要对其进行修改以及开发WordPress插件的要点。
然后,在本系列的下两个教程中,我们将从那里继续,以相同的方式自定义新的用户注册和密码重置功能。
您可以按照教程实施自己的插件,也可以从链接的GitHub存储库下载完整的示例代码。
让我们开始吧!
创建插件
尽管某些自定义显然取决于所使用的主题,但使登录页面可自定义本身的功能在很大程度上与主题无关,因此最好将其实现为插件。
因此,开始时的第一件事就是创建一个插件,以容纳我们将在本教程中构建的所有自定义项。
首先,创建一个目录来保存插件,将其命名为personalize-login
。 然后,在该目录内,创建另一个目录并将其命名为templates
。 在此目录中,我们将添加用于呈现本系列中创建的不同HTML表单的模板(我们将在本教程的后面部分对此进行介绍)。
然后,在创建目录之后,将一个名为personalize-login.php
的PHP文件放置在插件目录中。 该文件将包含此插件的所有代码,从插件初始化开始:
<?php
/**
* Plugin Name: Personalize Login
* Description: A plugin that replaces the WordPress login flow with a custom page.
* Version: 1.0.0
* Author: Jarkko Laine
* License: GPL-2.0+
* Text Domain: personalize-login
*/
class Personalize_Login_Plugin {
/**
* Initializes the plugin.
*
* To keep the initialization fast, only add filter and action
* hooks in the constructor.
*/
public function __construct() {
}
}
// Initialize the plugin
$personalize_login_pages_plugin = new Personalize_Login_Plugin();
插件的构造函数仍然为空,但时间不长:我们将很快开始以过滤器和动作钩子的形式向其添加内容。
但是首先,让我们创建一些WordPress页面。
创建用于登录的自定义页面
默认情况下,当您尝试访问WordPress管理员或单击WordPress网站上的“ 登录”链接(假设您的主题显示一个)时,WordPress会将您发送到WordPress登录页面的默认版本wp-login.php
。 现在,我们将对其进行更改,并将用户发送到自定义WordPress页面。
为此,首先我们需要创建一个页面。
稍后,添加设置屏幕以选择要用于用户管理流程中每个不同步骤的页面可能是有意义的。 但是,现在,我想让您专注于自定义,而不是让您迷惑创建设置页面,因此,我们将使用简单选项,并在激活插件后自动创建页面。
在WordPress插件中,执行此操作的方法是将静态函数注册到插件激活钩子,以便在通过“ 插件”菜单激活插件时调用该函数。
请注意,通过插件更新来更新插件时,不会调用激活挂钩。 因此,如果您对激活挂钩中的代码进行更改并希望使它们采取措施,请确保手动停用并激活插件。
要注册激活钩,请在插件文件末尾添加以下代码:
// Create the custom pages at plugin activation
register_activation_hook( __FILE__, array( 'Personalize_Login_Plugin', 'plugin_activated' ) );
然后,在插件类内部,添加静态函数plugin_activated
:
/**
* Plugin activation hook.
*
* Creates all WordPress pages needed by the plugin.
*/
public static function plugin_activated() {
// Information needed for creating the plugin's pages
$page_definitions = array(
'member-login' => array(
'title' => __( 'Sign In', 'personalize-login' ),
'content' => '[custom-login-form]'
),
'member-account' => array(
'title' => __( 'Your Account', 'personalize-login' ),
'content' => '[account-info]'
),
);
foreach ( $page_definitions as $slug => $page ) {
// Check that the page doesn't exist already
$query = new WP_Query( 'pagename=' . $slug );
if ( ! $query->have_posts() ) {
// Add the page using the data from the array above
wp_insert_post(
array(
'post_content' => $page['content'],
'post_name' => $slug,
'post_title' => $page['title'],
'post_status' => 'publish',
'post_type' => 'page',
'ping_status' => 'closed',
'comment_status' => 'closed',
)
);
}
}
}
插件激活功能使用第8-17行中定义的$page_definitions
数组中的数据创建一组页面。 使用此数组,我们可以轻松添加更多页面(就像我们在系列的下一部分中所做的那样),而无需复制和粘贴页面创建代码。 我们需要做的就是使用页面slug(永久链接)作为键并将包含页面标题和初始内容的数组作为值添加到数组中的新项目。
在上面的代码段中,我添加了两个页面:一个用于登录页面( member-login
)和一个用于帐户页面,我们将在其中引导已登录的非管理员用户( member-account
)。
在第19-36行 ,您将找到实际的页面创建代码。 该函数循环遍历页面定义数组,以检查是否存在具有给定子句的页面,如果不存在则创建页面。
使用WordPress函数wp_insert_post
创建页面。 有关其参数的更多信息,您可以检查WordPress Codex 。
现在,让我们激活插件,看看页面是按应有的方式创建的。 转到WordPress管理仪表板并激活插件。然后,当您访问`` 页面''菜单时,您应该在适当的位置看到两个新页面:
如果单击以查看“ 登录”页面,则会发现几乎空白的页面,除了标题和简码外什么都没有。
但这不会长期空白。
将内容添加到登录页面
有了前两页之后,我们就可以开始向它们添加内容了。
在第一个教程中,我们将构建“登录”或“登录”(请参阅有关登录最佳实践的这篇文章 ,以讨论使用哪些单词)页面。 然后,在接下来的两个教程中,我们将从那里继续,构建“注册”和“忘记密码”页面。
在登录屏幕上拥有自己的页面可为您提供许多用于自定义其外观和内容的选项。 在较容易的方面,您可以使用WordPress页面编辑器添加文本和图形(例如,针对用户的说明,或者可能是有关注册帐户的好处的广告)。 在另一个极端,您甚至可以创建自己的页面模板,并从头开始编写页面HTML。
在本教程中,我们将从中间做一些事情,并构建一个简短的代码,该代码将在登录页面上显示登录表单。 如果以后决定创建自己的页面模板,则始终可以从主题代码中调用此短代码。
步骤1:建立简码
您在页面创建步骤中还记得,在插件激活挂钩中创建登录页面时,我们已经在登录页面的主体中添加了一个短代码( custom-login-form
)。 但是,由于我们尚未为该短代码构建处理程序,因此WordPress现在将其呈现为常规文本。
现在创建处理程序。 在您的插件类的构造函数中,添加以下短代码定义:
add_shortcode( 'custom-login-form', array( $this, 'render_login_form' ) );
该行在插件类render_login_form
注册了一个函数,用于呈现简码custom-login-form
。
要使其工作,请添加以下功能:
/**
* A shortcode for rendering the login form.
*
* @param array $attributes Shortcode attributes.
* @param string $content The text content for shortcode. Not used.
*
* @return string The shortcode output
*/
public function render_login_form( $attributes, $content = null ) {
// Parse shortcode attributes
$default_attributes = array( 'show_title' => false );
$attributes = shortcode_atts( $default_attributes, $attributes );
$show_title = $attributes['show_title'];
if ( is_user_logged_in() ) {
return __( 'You are already signed in.', 'personalize-login' );
}
// Pass the redirect parameter to the WordPress login functionality: by default,
// don't specify a redirect, but if a valid redirect URL has been passed as
// request parameter, use it.
$attributes['redirect'] = '';
if ( isset( $_REQUEST['redirect_to'] ) ) {
$attributes['redirect'] = wp_validate_redirect( $_REQUEST['redirect_to'], $attributes['redirect'] );
}
// Render the login form using an external template
return $this->get_template_html( 'login_form', $attributes );
}
首先,在第10-13行中 ,该函数读取shortcode参数-当前只有show_title
一个,它采用布尔值。 如果省略该参数,则默认情况下将其设置为false。
然后,简码功能将检查用户是否已登录,仅为尚未登录的用户呈现表单。
在第19-25行 ,该函数检查是否将redirect_to
请求变量传递到登录页面。 登录后,此参数将带您进入正确的WordPress管理页面,因此在我们自定义登录流程时,请不要忘记它。 如果未设置redirect_to
或URL无效,则该函数将使用当前页面的永久链接。
为了使演示文稿与功能区分开,渲染使用放置在本教程开始时创建的templates
目录中的templates
完成。
正如我们已经知道的那样,我们将在本系列的后面部分添加更多模板(例如新的用户注册表单),我们将为此做准备,并将模板呈现分离为自己的功能,以避免重复代码( 第27-28行 )。 呈现模板所需的变量作为关联数组$attributes
传递。
将功能get_template_html
添加到插件类:
/**
* Renders the contents of the given template to a string and returns it.
*
* @param string $template_name The name of the template to render (without .php)
* @param array $attributes The PHP variables for the template
*
* @return string The contents of the template.
*/
private function get_template_html( $template_name, $attributes = null ) {
if ( ! $attributes ) {
$attributes = array();
}
ob_start();
do_action( 'personalize_login_before_' . $template_name );
require( 'templates/' . $template_name . '.php');
do_action( 'personalize_login_after_' . $template_name );
$html = ob_get_contents();
ob_end_clean();
return $html;
}
该函数在模板目录中查找给定的模板,并使用输出缓冲区将其呈现为字符串( 第14-23行 )。 输出缓冲区收集在ob_start
和ob_end_clean
之间打印的所有内容,以便随后可以使用ob_get_contents
将其作为字符串检索。
在该函数的末尾,将返回简码输出以在页面上进行渲染(如您在上一片段中所见,该简码函数随后将其返回给WordPress以进行渲染)。
围绕require
的do_action
函数调用是可选的,但显示了一种方便的方法,使其他开发人员有机会在呈现模板之前和之后添加更多自定义项。
要完成简码,您仍然需要创建HTML模板:在templates
目录中创建一个PHP文件,命名为login_form.php
。 要测试模板,只需添加文本Sign In
。 现在,当您导航到自定义登录页面时,您会看到类似以下内容(使用当前的WordPress默认主题: 二十十五 ):
您的简码可以使用,但是仍然缺少登录表单。 让我们现在添加。
步骤2:将内容添加到HTML模板
继续进行login_form.php
的工作,删除占位符文本,并将其替换为以下内容,这些内容将显示功能齐全的WordPress登录表单:
<div class="login-form-container">
<?php if ( $attributes['show_title'] ) : ?>
<h2><?php _e( 'Sign In', 'personalize-login' ); ?></h2>
<?php endif; ?>
<?php
wp_login_form(
array(
'label_username' => __( 'Email', 'personalize-login' ),
'label_log_in' => __( 'Sign In', 'personalize-login' ),
'redirect' => $attributes['redirect'],
)
);
?>
<a class="forgot-password" href="<?php echo wp_lostpassword_url(); ?>">
<?php _e( 'Forgot your password?', 'personalize-login' ); ?>
</a>
</div>
首先,模板以可选标题开头,该标题由show_title
参数show_title
控制,如前所述。
然后,在6-14行中 ,您会注意到大多数登录表单的呈现仍由WordPress使用wp_login_form
函数wp_login_form
。 该函数带有一个可选参数数组,可用于自定义登录表单的内容。
这是我在示例代码中进行的自定义:
- 首先,我想使用“登录”一词,而不是默认的“登录”。
- 其次,我想使用使用电子邮件地址作为用户名,因此我将用户名的标签更改为“电子邮件”。
- 第三,有一个重定向URL,它是通过上面的shortcode handler函数转发的。
对于进一步的自定义,这是可以在传递给wp_login_form
的参数数组中使用的参数的完整列表:
参数 | 描述 | 默认值 |
---|---|---|
echo | 是否应显示登录表单。 如果为false,则将输出作为字符串返回。 | true |
redirect | 成功登录后重定向到的URL。 | 重定向回到当前页面。 |
form_id | 登录表单HTML ID。 | loginform |
label_username | 用户名字段的文本标签。 | __( 'Username' ) |
label_password | 密码字段的文本标签。 | __( 'Password' ) |
label_remember | “记住我”复选框的文本标签。 | __( 'Remember Me' ) |
label_log_in | “登录”按钮的文本标签。 | __( 'Log In' ) |
id_username | 用户名字段HTML ID。 | user_login |
id_password | 密码字段HTML ID。 | user_pass |
id_remember | “记住我”复选框HTML ID。 | rememberme |
id_submit | 提交按钮HTML ID。 | wp-submit |
remember | 是否应显示“记住我”复选框。 | true |
value_username | 用户名的默认值。 | 空的 |
value_remember | 最初是否应选中“记住我”复选框。 | false |
最后,在第16-18行上 ,有一个指向WordPress丢失密码功能的链接-我们将在教程系列的第3部分中用我们自己的版本替换它。
现在,登录页面如下所示:
对于大多数用途而言,这将是足够的自定义,但是如果您想更深入一点,没有什么可以阻止您从头开始创建登录表单。
在这种情况下,您只需创建一个HTML表单并将其内容发布到wp-login.php
当前站点的完整登录URL由WordPress函数wp_login_url
返回。 表单需要分别具有log
和pwd
字段作为登录名和密码。
这是您如何创建外观(和功能)类似于上面的登录表单的方法,而无需使用wp_login_form
:
<div class="login-form-container">
<form method="post" action="<?php echo wp_login_url(); ?>">
<p class="login-username">
<label for="user_login"><?php _e( 'Email', 'personalize-login' ); ?></label>
<input type="text" name="log" id="user_login">
</p>
<p class="login-password">
<label for="user_pass"><?php _e( 'Password', 'personalize-login' ); ?></label>
<input type="password" name="pwd" id="user_pass">
</p>
<p class="login-submit">
<input type="submit" value="<?php _e( 'Sign In', 'personalize-login' ); ?>">
</p>
</form>
</div>
WordPress处理登录功能,因此登录表单已完全可用:输入有效的用户名和密码,然后单击“ 登录” ,您将可以正常登录。
当您输入无效数据时,您会注意到一切还没有准备就绪:您将看到常规的WordPress登录页面,而不是重定向回到我们刚刚创建的登录页面。 另外,除非用户将浏览器直接指向这个新创建的登录页面,否则她仍然会看到默认的WordPress登录名。
我们需要通过将用户重定向到新登录页面来使用它。
将访问者重定向到登录页面
首先让我们将用户带到登录页面。
步骤1:将用户重定向到我们的登录页面
当用户尝试访问WordPress管理员内部的任何页面或单击Meta小部件中的“ 登录”链接时,他将被发送到wp-login.php
。 接下来,我们要更改此功能并将用户指向我们自己的member-login
页面。
从登录到重置密码,我们在本系列中自定义的所有WordPress功能都在wp-login.php
处理,该功能的不同部分由一个名为action
的参数标识。
如果查看PHP文件中的代码,您会注意到,在实际登录功能开始之前,将触发两个操作: login_init
和login_form_{action}
,其中{action}
是正在执行的操作的名称(例如login
, postpass
或logout
)。
第二个是更具体的,因此通过使用它,我们不必做太多的自我检查:仅通过将函数挂钩到login_form_login
,我们就可以将重定向功能精确地定位到用户进入登录页面的那一刻。
将以下操作添加到插件类的构造函数中:
add_action( 'login_form_login', array( $this, 'redirect_to_custom_login' ) );
然后,添加动作函数:
/**
* Redirect the user to the custom login page instead of wp-login.php.
*/
function redirect_to_custom_login() {
if ( $_SERVER['REQUEST_METHOD'] == 'GET' ) {
$redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : null;
if ( is_user_logged_in() ) {
$this->redirect_logged_in_user( $redirect_to );
exit;
}
// The rest are redirected to the login page
$login_url = home_url( 'member-login' );
if ( ! empty( $redirect_to ) ) {
$login_url = add_query_arg( 'redirect_to', $redirect_to, $login_url );
}
wp_redirect( $login_url );
exit;
}
}
在两种情况下redirect_to_custom_login
调用redirect_to_custom_login
函数:第一,当用户进入登录页面时,第二,当用户提交登录表单时。 为了区分两者,我们看一下request方法:使用POST
提交表单,而使用GET
加载页面。
因此,为了让wp-login.php
处理实际的登录和身份验证,在第5行中 ,我们确保仅对GET
请求进行重定向。
在第6行 ,如果传入了请求变量redirect_to
,我们会将其存储在临时变量$redirect_to
。
已经登录的用户不需要通过登录表单,因此我们会将其重定向到WordPress仪表板或之前创建的成员帐户页面( 第8-11行 )。 为了在本系列教程的其余部分中为类似的重定向做准备,我们将重定向分离到它自己的函数redirect_logged_in_user
,我们将在不久后添加它。
值得注意的一件事是,我们在指定将用户重定向到的页面时依赖页面标记(漂亮的永久链接)。 如果要改进此示例并使插件更加灵活,则可以使用slug查找页面,然后使用该数据创建永久链接。 现在,只需在“ 永久链接”设置页面上打开漂亮的永久链接(除默认设置外,其他任何选项即可),一切都将正常进行。
在第15-17行 ,如果存在新请求,我们会将redirect_to
参数添加到新请求中,以使该重定向不会丢失任何信息。
在第20行 ,您会注意到我们使用exit
命令突然终止了执行。 这很重要,因为否则,执行将继续wp-login.php
的其余操作,这可能会导致我们的自定义问题。 在本教程其余部分中进行的其他重定向中,也请注意这一点。
现在,添加上面提到的函数redirect_logged_in_user
:
/**
* Redirects the user to the correct page depending on whether he / she
* is an admin or not.
*
* @param string $redirect_to An optional redirect_to URL for admin users
*/
private function redirect_logged_in_user( $redirect_to = null ) {
$user = wp_get_current_user();
if ( user_can( $user, 'manage_options' ) ) {
if ( $redirect_to ) {
wp_safe_redirect( $redirect_to );
} else {
wp_redirect( admin_url() );
}
} else {
wp_redirect( home_url( 'member-account' ) );
}
}
该函数根据用户的访问级别将用户重定向到其他URL。 对于管理员用户,我们还将检查$redirect_to
参数:如果设置了该参数,则将用户定向到此URL,而不是默认的admin_url
。
步骤2:出现错误时重定向
现在,我们已经涵盖了第一个重定向,因此,每当用户第一次单击wp-login.php
的链接或尝试访问管理仪表板时,他或她就会被发送到我们的新登录页面。 但是我们还没有完成:当登录中出现错误(无效的用户名或密码,空表格等)时,用户仍会看到默认的登录页面。
在WordPress中,用户身份验证通过名为wp_authenticate
的函数wp_authenticate
-如果您想看一下,该函数位于pluggable.php
。
该函数对参数进行一些基本的清理,然后调用连接到过滤器挂钩的过滤器authenticate
。 这是为了允许插件使用其自身的功能替换身份验证流程,但对我们而言最重要的是, 即使WordPress默认身份验证也通过此过滤器完成 。
在这一点上,我们对替换身份验证不感兴趣,但是过滤器挂钩仍然很有用,因为它使我们有机会从其他过滤器中收集错误并进行相应的处理:
- 使用足够高的优先级将新函数挂接到
authenticate
过滤器中(在WordPress过滤器和操作中,priority参数中的数字较大意味着该函数将在过滤器处理顺序中稍后被调用)。 - 过滤器函数将从过滤器链中以前的过滤器中接收结果作为参数。 使用此数据来检查登录中是否有任何错误。
- 如果未发现错误,请让一切正常进行,以便WordPress可以完成登录。
- 如果存在错误,请重定向到我们的自定义登录页面,而不是让WordPress进行常规错误处理。
在当前的WordPress版本(撰写本文时为4.2)中,WordPress具有以下两个用于进行authenticate
筛选器:
add_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
add_filter( 'authenticate', 'wp_authenticate_spam_check', 99 );
基本身份验证的优先级为20
, wp_authenticate_spam_check
的优先级为99
,因此,如果我们将我们的优先级设置为高于99
(我选择101
),它将在这两个之后运行。 当然,您使用的另一个插件可能会添加一个具有更高优先级的过滤器,在这种情况下,您需要增加数量以考虑该插件的错误。
首先,在我们的插件类的构造函数中添加新的过滤器定义:
add_filter( 'authenticate', array( $this, 'maybe_redirect_at_authenticate' ), 101, 3 );
然后,在插件类的末尾添加函数maybe_redirect_at_authenticate
:
/**
* Redirect the user after authentication if there were any errors.
*
* @param Wp_User|Wp_Error $user The signed in user, or the errors that have occurred during login.
* @param string $username The user name used to log in.
* @param string $password The password used to log in.
*
* @return Wp_User|Wp_Error The logged in user, or error information if there were errors.
*/
function maybe_redirect_at_authenticate( $user, $username, $password ) {
// Check if the earlier authenticate filter (most likely,
// the default WordPress authentication) functions have found errors
if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
if ( is_wp_error( $user ) ) {
$error_codes = join( ',', $user->get_error_codes() );
$login_url = home_url( 'member-login' );
$login_url = add_query_arg( 'login', $error_codes, $login_url );
wp_redirect( $login_url );
exit;
}
}
return $user;
}
authenticate
过滤器功能采用三个参数:
-
$user
是已登录用户的用户对象,如果到目前为止过滤器链中有错误,Wp_Error
类的实例。 -
$username
是用户尝试登录时输入的用户名。 -
$password
是用户输入的密码。
对于我们来说,第一个参数是一个有趣的参数:如果$user
是一个错误,则意味着较早的authenticate
过滤器功能之一在登录中发现错误。 那是我们的函数跳入( 第13行 )以收集所有错误代码并将它们附加到第15-18行的重定向URL上的时候。 最后,功能 将用户重定向到我们的自定义登录页面以显示错误。
步骤3:呈现错误消息
插件现在可以捕获错误,并在发现错误时将用户重定向到我们的自定义登录页面。 为了使体验对用户有用,我们仍然需要打印出错误消息。
首先,在我们的shortcode函数中,我们将使用在上一步中创建的重定向发送的login
参数来查看发生了什么错误,并将错误代码替换为可读的错误消息。 这是一个发挥您的想象力并创建一些有趣且个性化(但希望不会令人讨厌)的错误消息的好地方。
创建一个函数,使用简单的switch...case
结构将错误代码转换为错误消息。 错误代码是WordPress登录功能所使用的代码。
/**
* Finds and returns a matching error message for the given error code.
*
* @param string $error_code The error code to look up.
*
* @return string An error message.
*/
private function get_error_message( $error_code ) {
switch ( $error_code ) {
case 'empty_username':
return __( 'You do have an email address, right?', 'personalize-login' );
case 'empty_password':
return __( 'You need to enter a password to login.', 'personalize-login' );
case 'invalid_username':
return __(
"We don't have any users with that email address. Maybe you used a different one when signing up?",
'personalize-login'
);
case 'incorrect_password':
$err = __(
"The password you entered wasn't quite right. <a href='%s'>Did you forget your password</a>?",
'personalize-login'
);
return sprintf( $err, wp_lostpassword_url() );
default:
break;
}
return __( 'An unknown error occurred. Please try again later.', 'personalize-login' );
}
然后,要使用错误消息,请在呈现登录表单模板之前,将以下代码添加到render_login_form
。 它将遍历错误代码列表,并将匹配的错误消息收集到数组$errors
:
// Error messages
$errors = array();
if ( isset( $_REQUEST['login'] ) ) {
$error_codes = explode( ',', $_REQUEST['login'] );
foreach ( $error_codes as $code ) {
$errors []= $this->get_error_message( $code );
}
}
$attributes['errors'] = $errors;
错误消息的实际呈现是在login_form.php
模板中完成的。 在登录表单的标题之后和登录表单之前添加以下内容:
<!-- Show errors if there are any -->
<?php if ( count( $attributes['errors'] ) > 0 ) : ?>
<?php foreach ( $attributes['errors'] as $error ) : ?>
<p class="login-error">
<?php echo $error; ?>
</p>
<?php endforeach; ?>
<?php endif; ?>
现在,错误消息已经到位,我们可以对其进行测试。 尝试使用不正确的信息登录,您将被重定向到我们的自定义页面,并带有我们自己的自定义错误消息:
步骤4:在注销时显示正确的消息
我们差不多完成了,但还不完全。 在一天之内,我们还需要做两件事,说我们已经用自己的版本替换了所有的WordPress登录流程:用户注销时呈现正确的消息,以及将用户重定向到正确的页面成功登录后。
让我们从注销开始。
一旦用户从您的站点注销,则在功能wp_logout
,WordPress会触发操作wp_logout
。 在WordPress将用户重定向回wp-login.php
之前,这是一个挂钩并进行我们自己的重定向的好地方。
在插件类的构造函数中,添加以下行:
add_action( 'wp_logout', array( $this, 'redirect_after_logout' ) );
然后添加匹配功能:
/**
* Redirect to custom login page after the user has been logged out.
*/
public function redirect_after_logout() {
$redirect_url = home_url( 'member-login?logged_out=true' );
wp_safe_redirect( $redirect_url );
exit;
}
该函数将用户重定向到我们的member-login
页面,并在请求后附加参数logged_out
,然后停止执行。
接下来,修改登录表单简码功能以将此参数考虑在内。 上面我们创建的错误消息处理之后,此代码的合适位置是:
// Check if user just logged out
$attributes['logged_out'] = isset( $_REQUEST['logged_out'] ) && $_REQUEST['logged_out'] == true;
最后,我们需要在模板中打印一个通知。 再次,在打印出潜在错误后添加此权限:
<!-- Show logged out message if user just logged out -->
<?php if ( $attributes['logged_out'] ) : ?>
<p class="login-info">
<?php _e( 'You have signed out. Would you like to sign in again?', 'personalize-login' ); ?>
</p>
<?php endif; ?>
而已。 现在,当您登录然后退出时,您会看到类似以下内容:
登录后将用户重定向到帐户页面
现在,我们已经实现了自定义登录并处理了所有错误情况。 最后,为使一切正常,让我们添加最后一个重定向。 这将确保用户始终最终到达他(或被允许)去的地方。
对于管理员来说,这是管理控制台,对于普通非管理员用户,这是(当前为空) member-account
页面。
由于WordPress提供了一个用于在成功登录后返回重定向URL的过滤器,因此这很简单:我们需要做的就是创建一个函数来检查当前用户的功能并相应地返回正确的重定向URL。
为此,请在插件的构造函数中再次添加最后一个过滤器:
add_filter( 'login_redirect', array( $this, 'redirect_after_login' ), 10, 3 );
然后添加匹配的过滤器功能:
/**
* Returns the URL to which the user should be redirected after the (successful) login.
*
* @param string $redirect_to The redirect destination URL.
* @param string $requested_redirect_to The requested redirect destination URL passed as a parameter.
* @param WP_User|WP_Error $user WP_User object if login was successful, WP_Error object otherwise.
*
* @return string Redirect URL
*/
public function redirect_after_login( $redirect_to, $requested_redirect_to, $user ) {
$redirect_url = home_url();
if ( ! isset( $user->ID ) ) {
return $redirect_url;
}
if ( user_can( $user, 'manage_options' ) ) {
// Use the redirect_to parameter if one is set, otherwise redirect to admin dashboard.
if ( $requested_redirect_to == '' ) {
$redirect_url = admin_url();
} else {
$redirect_url = $requested_redirect_to;
}
} else {
// Non-admin users always go to their account page after login
$redirect_url = home_url( 'member-account' );
}
return wp_validate_redirect( $redirect_url, home_url() );
}
首先,该功能检查用户是否确实已登录( 第13行 ),如果找不到用户,则重定向回站点的主页。
然后,它根据当前用户的能力选择正确的重定向:
- 除非在请求中传递了
redirect_to
参数,否则管理员(使用user_can函数在第17行选中)将被重定向到WordPress管理仪表板( 第20行 )。 - 普通用户总是被重定向到
member-account
页面,以防止他们访问WordPress仪表板。 这当然取决于您:如果需要,您可以例如将其指向WordPress管理员中的用户页面。
如果愿意,还可以根据用户的角色和功能添加更多细粒度的重定向。
下一步是什么?
而已。 现在,您已经构建了一个插件,可以用自定义页面替换WordPress登录屏幕,您可以对该页面进行自定义以使其适合您的主题,或者您要在WordPress之上构建的产品。
在本系列的下一个教程中,我们将以此为基础并创建一个新的用户注册流程,添加一些新字段和一个验证码以防止机器人注册。
在此之前,请尽情调整您的登录页面!