WordPress登录时只能用用户名,用户名可能被忘记,但一般的用户都对自己的电子邮箱比较了解,一个简单的hack就可以允许用户用用户名或者电子邮件登陆。

代码

代码很简单,在functions.php中添加如下代码

function login_with_email_address($username) {
	$user = get_user_by('email',$username);
	if(!empty($user->user_login))
			$username = $user->user_login;

}
add_action('wp_authenticate','login_with_email_address');
function change_username_wps_text($text){
	if(in_array($GLOBALS['pagenow'], array('wp-login.php'))){
	 	if ($text == 'Username'){
			$text = 'Username / Email';
		}
	}
		return $text;
}
add_filter( 'gettext', 'change_username_wps_text' );

代码来自wpsnipp.com,我有疑问的一个地方就是在login_with_email_address function中是否还需要return $username,这里用到的action传递的是引用。

这段代码只能针对英文版本,如果使用其他语言,需要使更改的字符串可翻译,可以这样改一下第二个函数

function change_username_wps_text($translated_text, $untranslated_text, $domain){
	if(in_array($GLOBALS['pagenow'], array('wp-login.php'))){
	 	if ($untranslated_text == 'Username'){
			$translated_text = __( 'Username / Email', 'theme_text_domain' );
		}
	}
		return $translated_text;
}
add_filter( 'gettext', 'change_username_wps_text',20,3 );

theme_text_domain需要替换成自己主题的text-domain

原理

一开始看到这段代码,确实不明白什么意思。所以找了一下wp_authenticate的位置。在wp-includes/user.php的wp_signon function中,调用方式如下所示

do_action_ref_array('wp_authenticate', array(&$credentials['user_login'], &$credentials['user_password']));

在WordPress官网找到了wp_authenticate说明,原来这个action可以用来修改用户认证过程。

This action is located inside of wp_signon. In contrast to the wp_login action, it is executed before the WordPress authentication process.

看了这些资料,大概明白上面那段代码的意思了

WordPress验证时需要使用用户名而不是电子邮箱,所以在验证之前,用get_user_by()函数获取用户名,该函数可以接受一个email地址作为参数,获取该email对应的用户名。如果没有获取到,则不改变$username,用户还可以通过用户名登陆。

现在我唯一不明白的就是这个调用方式,do action ref array与do_action的区别仅在于传递参数的形式,但我还不十分明了,得加强练习啊。

补充:

经过一番思考,发现自己小白了,忘记给action或者filter传参数时,如果参数多于1个需要制定参数的个数,一直傻乎乎的看着这段报错不知所措

Warning: Missing argument 2 for login_with_email_address()

原来忘记指定参数个数了,改成这样就不会出错了。

add_action('wp_authenticate','login_with_email_address',20,2);