嘿,各位代码界的大佬、小萌新们,欢迎来到今天的 WordPress 源码剖析小课堂! 今天咱们要聊的是 WordPress 多站点模式下,新站点注册时至关重要的一个函数 —— wpmu_validate_blog_signup()
。 别看名字长,其实它就是个“守门员”,负责把守新站点注册的大门,确保提交的数据符合规范,防止垃圾站点横行霸道。 准备好了吗? 咱们这就开扒!
一、wpmu_validate_blog_signup()
是个什么角色?
简单来说,wpmu_validate_blog_signup()
函数是 WordPress 多站点 (WordPress Multisite) 环境下,用户注册新站点时,服务器端用来验证用户输入数据的核心函数。 它的主要职责包括:
- 检查站点地址 (domain) 是否合法: 比如是否符合域名格式、是否已被占用、是否是保留字等。
- 检查站点标题 (title) 是否为空: 总不能让站点没名字就出生吧?
- 检查用户邮箱 (user_email) 是否合法: 邮箱格式是否正确、是否已被注册等。
- 返回验证结果: 告诉 WordPress 系统,这次注册是 "成功" 还是 "失败",如果失败,还要给出具体的原因。
二、 源码解读:一步一个脚印
wpmu_validate_blog_signup()
函数的源码位于 wp-includes/ms-functions.php
文件中。 咱们一点点地把它拆解开来,看看这位 "守门员" 到底是怎么工作的。
function wpmu_validate_blog_signup( $domain, $path, $title, $user_email, $errors = null ) {
global $wpdb;
$orig_domain = $domain;
$filtered_domain = preg_replace( '/[^-a-z0-9]/', '', strtolower( $domain ) );
if ( $filtered_domain != $domain ) {
$errors->add( 'domain_invalid', __( 'Only lowercase letters, numbers, and hyphens allowed.' ) );
}
if ( strlen( $domain ) > 60 ) {
$errors->add( 'domain_long', __( 'Site domain is too long, limit is 60 characters.' ) );
}
if ( ! is_subdomain_install() && strpos( $domain, '.' ) ) {
$errors->add( 'domain_invalid', __( 'The domain may not contain periods.' ) );
}
if ( empty( $path ) ) {
$errors->add( 'path_empty', __( 'Missing path.' ) );
}
if ( substr( $path, 0, 1 ) != '/' )
$path = '/' . $path;
if ( substr( $path, -1 ) != '/' )
$path .= '/';
$check_path = preg_replace( '/[^a-z0-9]/', '', strtolower( $path ) );
if ( $check_path != substr( $path, 1, strlen( $path ) - 2 ) ) {
$errors->add( 'path_invalid', __( 'Only lowercase letters and numbers allowed.' ) );
}
if ( strlen( $path ) > 60 ) {
$errors->add( 'path_long', __( 'Site path is too long, limit is 60 characters.' ) );
}
$title = trim( $title );
if ( empty( $title ) ) {
$errors->add( 'title_empty', __( 'Missing title.' ) );
}
if ( empty( $user_email ) ) {
$errors->add( 'email_empty', __( 'Missing email address.' ) );
} elseif ( ! is_email( $user_email ) ) {
$errors->add( 'email_invalid', __( 'Invalid email address.' ) );
} else {
if ( email_exists( $user_email ) ) {
$errors->add( 'email_exists', __( 'This email is already registered, please choose another one.' ) );
}
}
/**
* Fires before site signup validation.
*
* @since 3.0.0
*
* @param string $domain The requested domain.
* @param string $path The requested path.
* @param string $title The requested site title.
* @param string $user_email The user email address.
* @param WP_Error $errors A WP_Error object containing any errors.
*/
do_action( 'signup_blogform_validate', $domain, $path, $title, $user_email, $errors );
$domain = $filtered_domain;
return compact( 'domain', 'path', 'title', 'user_email', 'errors', 'orig_domain' );
}
2.1 函数签名和参数
首先,我们来看一下函数的签名:
function wpmu_validate_blog_signup( $domain, $path, $title, $user_email, $errors = null )
$domain
: 用户希望的站点域名 (例如:mysite
)。$path
: 用户希望的站点路径 (例如:/blog/
)。$title
: 用户希望的站点标题 (例如:我的小博客
)。$user_email
: 用户的邮箱地址。$errors
: 一个WP_Error
对象,用于存储验证过程中发现的错误。 如果没有传入,函数会创建一个新的WP_Error
对象。
2.2 域名 (Domain) 验证
$orig_domain = $domain;
$filtered_domain = preg_replace( '/[^-a-z0-9]/', '', strtolower( $domain ) );
if ( $filtered_domain != $domain ) {
$errors->add( 'domain_invalid', __( 'Only lowercase letters, numbers, and hyphens allowed.' ) );
}
if ( strlen( $domain ) > 60 ) {
$errors->add( 'domain_long', __( 'Site domain is too long, limit is 60 characters.' ) );
}
if ( ! is_subdomain_install() && strpos( $domain, '.' ) ) {
$errors->add( 'domain_invalid', __( 'The domain may not contain periods.' ) );
}
这段代码主要做了以下几件事:
- 保存原始域名: 先把
$domain
的原始值存到$orig_domain
中,后面可能会用到。 - 过滤非法字符: 使用正则表达式
/[^-a-z0-9]/
移除域名中所有非小写字母、数字和连字符的字符。 并将域名转化为小写。 - 检查是否包含非法字符: 如果过滤后的域名
$filtered_domain
和原始域名$domain
不一致,说明原始域名包含非法字符,就往$errors
对象里添加一个错误信息。 - 检查域名长度: 限制域名长度不能超过 60 个字符,超过了就报错。
- 检查是否包含句点: 如果不是子域名安装模式 (
is_subdomain_install()
返回false
),则域名中不能包含句点 (.
),否则报错。 这种情况通常是子目录安装模式。
2.3 路径 (Path) 验证
if ( empty( $path ) ) {
$errors->add( 'path_empty', __( 'Missing path.' ) );
}
if ( substr( $path, 0, 1 ) != '/' )
$path = '/' . $path;
if ( substr( $path, -1 ) != '/' )
$path .= '/';
$check_path = preg_replace( '/[^a-z0-9]/', '', strtolower( $path ) );
if ( $check_path != substr( $path, 1, strlen( $path ) - 2 ) ) {
$errors->add( 'path_invalid', __( 'Only lowercase letters and numbers allowed.' ) );
}
if ( strlen( $path ) > 60 ) {
$errors->add( 'path_long', __( 'Site path is too long, limit is 60 characters.' ) );
}
路径验证的代码逻辑如下:
- 检查路径是否为空: 如果
$path
为空,说明用户没有填写路径,报错。 - 确保路径以
/
开头和结尾: 如果$path
不是以/
开头,就在前面加上/
。 如果$path
不是以/
结尾,就在后面加上/
。 这样做的目的是为了保证路径的格式统一。 - 过滤非法字符: 使用正则表达式
/[^a-z0-9]/
移除路径中所有非小写字母和数字的字符。 - 检查是否包含非法字符: 这里比较巧妙,先用
substr( $path, 1, strlen( $path ) - 2 )
去掉了路径首尾的/
, 然后再和过滤后的路径$check_path
进行比较。 如果不一致,说明路径中包含非法字符,报错。 - 检查路径长度: 限制路径长度不能超过 60 个字符,超过了就报错。
2.4 标题 (Title) 验证
$title = trim( $title );
if ( empty( $title ) ) {
$errors->add( 'title_empty', __( 'Missing title.' ) );
}
标题验证的代码非常简单:
- 去除首尾空格: 使用
trim()
函数去除标题$title
首尾的空格。 - 检查标题是否为空: 如果
$title
为空,说明用户没有填写标题,报错。
2.5 邮箱 (Email) 验证
if ( empty( $user_email ) ) {
$errors->add( 'email_empty', __( 'Missing email address.' ) );
} elseif ( ! is_email( $user_email ) ) {
$errors->add( 'email_invalid', __( 'Invalid email address.' ) );
} else {
if ( email_exists( $user_email ) ) {
$errors->add( 'email_exists', __( 'This email is already registered, please choose another one.' ) );
}
}
邮箱验证的代码稍微复杂一些:
- 检查邮箱是否为空: 如果
$user_email
为空,说明用户没有填写邮箱,报错。 - 检查邮箱格式是否正确: 使用
is_email()
函数检查邮箱格式是否正确。 如果不正确,报错。 - 检查邮箱是否已被注册: 使用
email_exists()
函数检查邮箱是否已经被注册。 如果已被注册,报错。
2.6 do_action( 'signup_blogform_validate' )
/**
* Fires before site signup validation.
*
* @since 3.0.0
*
* @param string $domain The requested domain.
* @param string $path The requested path.
* @param string $title The requested site title.
* @param string $user_email The user email address.
* @param WP_Error $errors A WP_Error object containing any errors.
*/
do_action( 'signup_blogform_validate', $domain, $path, $title, $user_email, $errors );
这行代码是一个 WordPress 的 Action Hook。 它的作用是:允许开发者在站点注册验证过程中的这个点,插入自定义的验证逻辑。 比如,你可以使用这个 Hook 来添加额外的安全验证,或者检查用户是否满足某些特殊条件。
2.7 返回值
$domain = $filtered_domain;
return compact( 'domain', 'path', 'title', 'user_email', 'errors', 'orig_domain' );
函数最后返回一个数组,包含了以下信息:
domain
: 经过过滤后的域名。path
: 路径。title
: 标题。user_email
: 用户的邮箱地址。errors
:WP_Error
对象,包含了所有的错误信息。orig_domain
: 原始域名。
使用了 compact()
函数,它会创建一个关联数组,键名为变量名,值为变量的值。 这样方便调用者获取验证结果。
三、 WP_Error
对象:错误信息的容器
在 wpmu_validate_blog_signup()
函数中,我们看到了 WP_Error
对象的身影。 它是 WordPress 用来管理错误信息的工具。 我们可以使用它来:
- 添加错误信息: 使用
$errors->add( $code, $message )
方法,其中$code
是错误代码 (例如:domain_invalid
),$message
是错误信息 (例如:域名无效
)。 - 检查是否有错误: 使用
$errors->has_errors()
方法,如果返回true
,说明有错误。 - 获取错误信息: 使用
$errors->get_error_messages()
方法,可以获取所有错误信息的数组。
四、 实例演示:模拟一次注册验证
为了更好地理解 wpmu_validate_blog_signup()
函数的工作流程,我们来模拟一次新站点注册,并手动调用这个函数进行验证。
<?php
// 引入 WordPress 的核心文件
require_once( 'wp-load.php' );
// 模拟用户输入的数据
$domain = 'My-Site.com'; // 故意包含大写字母和句点
$path = '/my_blog'; // 故意不以 / 结尾
$title = 'My Awesome Blog';
$user_email = '[email protected]';
// 创建一个 WP_Error 对象
$errors = new WP_Error();
// 调用 wpmu_validate_blog_signup 函数进行验证
$result = wpmu_validate_blog_signup( $domain, $path, $title, $user_email, $errors );
// 检查是否有错误
if ( $result['errors']->has_errors() ) {
// 输出错误信息
echo "注册失败:n";
foreach ( $result['errors']->get_error_messages() as $message ) {
echo "- " . $message . "n";
}
} else {
// 输出验证结果
echo "注册成功!n";
echo "域名:" . $result['domain'] . "n";
echo "路径:" . $result['path'] . "n";
echo "标题:" . $result['title'] . "n";
echo "邮箱:" . $result['user_email'] . "n";
}
?>
运行这段代码,你会看到类似以下的输出:
注册失败:
- Only lowercase letters, numbers, and hyphens allowed.
- Missing path.
可以看到,wpmu_validate_blog_signup()
函数成功地检测到了域名和路径中的错误。
五、 总结与思考
wpmu_validate_blog_signup()
函数是 WordPress 多站点模式下,新站点注册流程中的重要一环。 它通过一系列的验证规则,确保用户输入的数据符合规范,从而保证整个系统的安全性和稳定性。
验证项 | 验证内容 | 失败时错误代码 |
---|---|---|
域名 | 是否只包含小写字母、数字和连字符,长度是否超过 60,是否包含句点 (取决于安装模式) | domain_invalid , domain_long |
路径 | 是否为空,是否以 / 开头和结尾,是否只包含小写字母和数字,长度是否超过 60 |
path_empty , path_invalid , path_long |
标题 | 是否为空 | title_empty |
邮箱 | 是否为空,格式是否正确,是否已被注册 | email_empty , email_invalid , email_exists |
通过对 wpmu_validate_blog_signup()
函数源码的剖析,我们不仅了解了它的工作原理,还学习了如何使用 WP_Error
对象来管理错误信息。 掌握了这些知识,你就能更好地理解 WordPress 多站点的工作机制,也能在实际开发中更加得心应手。
好了,今天的 WordPress 源码剖析小课堂就到这里了。 希望这次的讲解对你有所帮助。 咱们下次再见!