各位观众老爷,晚上好! 今晚咱来聊聊 WordPress 多站点网络这事儿。说白了,就是在一个 WordPress 安装基础上,搞出N多个站点,共享核心文件,但各自有各自的地盘(数据库表、上传文件等等)。 听起来是不是有点像“一母生多子,各过各的日子”?
今天咱们要扒的就是 install_network()
这个函数,看看它是怎么把这 “一母多子” 的框架给搭起来的。准备好了吗?发车!
一、入场前的准备:环境检查与变量初始化
在 install_network()
正式开工之前,得先看看周围环境是否允许施工,以及准备好必要的材料。这段代码主要负责检查是否已经安装了WordPress,以及初始化一些重要的变量。
function install_network() {
global $wpdb, $current_site, $wp_rewrite;
if ( ! defined( 'WP_INSTALLING' ) ) {
wp_die( __( 'This file cannot be accessed directly.' ) );
}
if ( is_multisite() ) {
wp_die( __( 'WordPress is already installed as a network.' ) );
}
if ( ! current_user_can( 'setup_network' ) ) {
wp_die( __( 'You do not have permission to use this page.' ) );
}
// 初始化一些变量
$sitename = sanitize_title( get_bloginfo( 'name' ) );
if ( empty( $sitename ) ) {
$sitename = 'wp';
}
$admin_email = get_option( 'admin_email' );
$path = trim( parse_url( get_bloginfo( 'url' ), PHP_URL_PATH ), '/' );
// ... 后续代码
}
这段代码干了这些事:
- 防止直接访问:
if ( ! defined( 'WP_INSTALLING' ) )
这行确保这个文件只能通过 WordPress 安装程序调用,防止有人直接在浏览器里输入地址来搞破坏。 - 检查是否已是多站点:
if ( is_multisite() )
确认是否已经安装了多站点。如果已经安装了,那就没必要再安装了,直接报错退出。 - 权限验证:
if ( ! current_user_can( 'setup_network' ) )
只有拥有setup_network
权限的用户才能安装多站点网络。一般来说,只有超级管理员才有这个权限。 - 初始化变量: 从站点名称 (
get_bloginfo( 'name' )
) 获取一个安全版本 (sanitize_title()
) 作为网络名称的基础。如果站点名称为空,就使用 "wp" 作为默认值。同时,获取管理员邮箱地址 (get_option( 'admin_email' )
) 和站点的路径 (parse_url( get_bloginfo( 'url' ), PHP_URL_PATH )
)。
二、网络配置:域名类型与参数设置
接下来,install_network()
会根据用户选择的域名类型(子域名或子目录)进行一些配置。这是多站点网络的核心设置之一。
if ( isset( $_POST['sitename'] ) ) {
$sitename = sanitize_title( $_POST['sitename'] );
}
if ( ! isset( $_POST['subdomain_install'] ) ) {
echo '<p>' . __( 'Choose whether you want sites to be created with subdomains or subdirectories.' ) . '</p>';
echo '<p><label><input type="radio" name="subdomain_install" value="1" /> ' . sprintf( __( 'Sites in my WordPress network will use subdomains (like “site1.%s”).' ), $current_site->domain ) . '</label></p>';
echo '<p><label><input type="radio" name="subdomain_install" value="0" /> ' . sprintf( __( 'Sites in my WordPress network will use subdirectories (like “%s/site1”).' ), $current_site->domain . $path ) . '</label></p>';
return;
}
$subdomain_install = (bool) $_POST['subdomain_install'];
if ( ! $wp_rewrite->using_mod_rewrite_permalinks() && ! $subdomain_install ) {
echo '<div class="error">';
echo '<p>' . __( 'You have chosen to use subdirectories. The installation will use subdomains if you proceed.' ) . '</p>';
echo '</div>';
$subdomain_install = true;
}
这段代码做了以下工作:
- 接收域名类型选择: 从
$_POST['subdomain_install']
获取用户选择的域名类型。如果用户没有选择,就显示一个表单,让用户选择使用子域名还是子目录。 - 强制使用子域名:
if ( ! $wp_rewrite->using_mod_rewrite_permalinks() && ! $subdomain_install )
这段代码比较关键。它检查是否启用了 WordPress 的伪静态链接 (mod_rewrite
)。如果 没有 启用,并且用户选择了 子目录,那么 WordPress 会强制使用子域名。这是因为子目录需要伪静态链接的支持才能正常工作。
三、数据库操作:表的创建与数据的插入
重头戏来了!install_network()
要开始往数据库里写东西了。它会创建一些新的表,或者修改现有的表,并插入一些必要的初始数据。
// 创建/更新数据库表
install_blog( $wpdb->siteid, $sitename, $admin_email, true );
$site_id = $wpdb->siteid;
$domain = preg_replace( '|^www.|', '', $current_site->domain );
if ( $subdomain_install ) {
$result = add_subdomain_install( $domain, $path );
} else {
$result = add_subdirectory_install( $domain, $path );
}
if ( ! $result ) {
wp_die( __( 'There was an error adding the primary network site to the database.' ) );
}
update_site_option( $site_id, 'site_admins', array( get_userdata( get_current_user_id() )->user_login ) );
// ... 后续代码
这里发生了这些事情:
- 创建/更新站点表:
install_blog( $wpdb->siteid, $sitename, $admin_email, true )
这个函数负责创建或更新站点表。注意这里的$wpdb->siteid
通常是 1,代表主站点。install_blog()
的第四个参数$is_main_site
设置为true
,表明这是主站点。 - 添加主站点到数据库:
add_subdomain_install()
或add_subdirectory_install()
这两个函数根据用户选择的域名类型,将主站点的信息添加到wp_sitemeta
表中。 - 设置站点管理员:
update_site_option( $site_id, 'site_admins', array( get_userdata( get_current_user_id() )->user_login ) )
设置主站点的管理员。这里的get_current_user_id()
获取当前用户的 ID,get_userdata()
获取用户信息,然后提取用户名 (user_login
)。
四、修改 .htaccess 和 wp-config.php:规则调整与配置更新
多站点网络需要对 .htaccess
文件和 wp-config.php
文件进行一些修改,才能正常工作。install_network()
会提示用户手动修改这些文件。
// 显示需要添加到 .htaccess 和 wp-config.php 的代码
$ms_constant = ( $subdomain_install ) ? 'SUBDOMAIN_INSTALL' : 'SUBDIR_INSTALL';
$wp_config_code = "
define( 'WP_ALLOW_MULTISITE', true );
define( '$ms_constant', true );
define( 'MULTISITE', true );
define( 'DOMAIN_CURRENT_SITE', '" . $domain . "' );
define( 'PATH_CURRENT_SITE', '" . $path . "' );
define( 'SITE_ID_CURRENT_SITE', " . $site_id . " );
define( 'BLOG_ID_CURRENT_SITE', " . $wpdb->blogid . " );
";
$subdir_htaccess = "
RewriteEngine On
RewriteBase " . $path . "/
RewriteRule ^index.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(" . $wp_rewrite->rewrite_rules_slug . ".*) wp-includes/ms-files.php?file=$1 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*.php)$ $2 [L]
RewriteRule . index.php [L]
";
$subdomain_htaccess = "
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]
# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(" . $wp_rewrite->rewrite_rules_slug . ".*) wp-includes/ms-files.php?file=$1 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*.php)$ $2 [L]
RewriteRule . index.php [L]
";
echo '<h2>' . __( 'Creating a Network of WordPress Sites' ) . '</h2>';
echo '<p>' . __( 'The following lines go in your <code>wp-config.php</code> file:' ) . '</p>';
echo '<p><code>';
echo str_replace( ' ', ' ', esc_html( $wp_config_code ) );
echo '</code></p>';
if ( $subdomain_install ) {
echo '<p>' . __( 'Add the following code to your <code>.htaccess</code> file in the root directory. Make sure you have a backup of your <code>.htaccess</code> file before you do:' ) . '</p>';
echo '<p><code>';
echo str_replace( ' ', ' ', esc_html( $subdomain_htaccess ) );
echo '</code></p>';
} else {
echo '<p>' . __( 'Add the following code to your <code>.htaccess</code> file in the root directory. Make sure you have a backup of your <code>.htaccess</code> file before you do:' ) . '</p>';
echo '<p><code>';
echo str_replace( ' ', ' ', esc_html( $subdir_htaccess ) );
echo '</code></p>';
}
这段代码主要做了以下事情:
- 定义常量: 根据域名类型,定义
SUBDOMAIN_INSTALL
或SUBDIR_INSTALL
常量。 - 生成
wp-config.php
代码: 生成需要添加到wp-config.php
文件的代码,包括WP_ALLOW_MULTISITE
、MULTISITE
、DOMAIN_CURRENT_SITE
、PATH_CURRENT_SITE
和SITE_ID_CURRENT_SITE
等常量。 - 生成
.htaccess
代码: 根据域名类型,生成需要添加到.htaccess
文件的代码。这些代码主要负责重写 URL,将子域名或子目录的请求转发到相应的站点。 - 显示代码: 将生成的代码显示给用户,让用户手动添加到
wp-config.php
和.htaccess
文件中。
注意:WordPress 并没有自动修改这两个文件,而是让用户手动修改。这是为了安全起见,防止 WordPress 因为权限问题而无法修改这些文件,导致安装失败。
五、收尾工作:提示与重定向
安装完成后,install_network()
会提示用户重新登录,并重定向到网络管理界面。
echo '<p>' . __( 'Once you have completed putting the code into your <code>wp-config.php</code> and <code>.htaccess</code> files, log in again.' ) . '</p>';
echo '<p><a href="' . esc_url( wp_login_url() ) . '">' . __( 'Log In' ) . '</a></p>';
}
这段代码很简单,就是显示一条提示信息,告诉用户需要重新登录,并提供一个登录链接。重新登录后,用户就可以进入网络管理界面,开始管理多站点网络了。
总结:install_network()
的核心流程
为了方便大家理解,我把 install_network()
的核心流程总结成一个表格:
步骤 | 描述 | 主要代码 |
---|---|---|
1. 环境检查与变量初始化 | 检查是否已安装 WordPress,是否已是多站点,以及用户权限。初始化站点名称、管理员邮箱地址和站点路径等变量。 | if ( ! defined( 'WP_INSTALLING' ) ) , if ( is_multisite() ) , if ( ! current_user_can( 'setup_network' ) ) , $sitename = sanitize_title( get_bloginfo( 'name' ) ) |
2. 网络配置 | 根据用户选择的域名类型(子域名或子目录)进行配置。如果未启用伪静态链接且用户选择子目录,则强制使用子域名。 | if ( isset( $_POST['subdomain_install'] ) ) , if ( ! $wp_rewrite->using_mod_rewrite_permalinks() && ! $subdomain_install ) |
3. 数据库操作 | 创建/更新站点表,添加主站点信息到数据库,设置站点管理员。 | install_blog( $wpdb->siteid, $sitename, $admin_email, true ) , add_subdomain_install() , add_subdirectory_install() , update_site_option( $site_id, 'site_admins', array( get_userdata( get_current_user_id() )->user_login ) ) |
4. 修改文件 | 生成需要添加到 wp-config.php 和 .htaccess 文件的代码,并显示给用户,让用户手动修改。 |
$ms_constant = ( $subdomain_install ) ? 'SUBDOMAIN_INSTALL' : 'SUBDIR_INSTALL' , 生成 $wp_config_code 和 $subdir_htaccess 或 $subdomain_htaccess |
5. 收尾工作 | 提示用户重新登录,并重定向到网络管理界面。 | echo '<p>' . __( 'Once you have completed putting the code into your <code>wp-config.php</code> and <code>.htaccess</code> files, log in again.' ) . '</p>' |
一些需要注意的点:
- 伪静态链接 (
mod_rewrite
): 子目录模式依赖于伪静态链接,如果服务器不支持,或者没有正确配置,可能会导致多站点网络无法正常工作。 .htaccess
文件权限: 确保 WordPress 能够读取和写入.htaccess
文件,否则多站点网络的 URL 重写规则可能无法生效。- 数据库表前缀: 多站点网络共享数据库表,但每个站点都有自己的表前缀。确保表前缀设置正确,避免数据冲突。
- 域名解析: 如果是子域名模式,需要确保所有子域名都解析到服务器的 IP 地址。
好了,关于 install_network()
函数的源码剖析就到这里了。希望通过这次讲座,大家对 WordPress 多站点网络的安装流程有了更深入的了解。记住,源码才是最可靠的老师,多看多练,你也能成为 WordPress 大牛!
下次再见!