函数文档

populate_network()

💡 云策文档标注

概述

populate_network() 函数用于在 WordPress 中填充或创建网络设置,特别是在多站点(Multisite)环境中。它处理网络的基本配置,包括域名、管理员邮箱、网络名称等参数,并执行必要的数据库操作和验证。

关键要点

  • 函数用于初始化网络设置,支持从单站点升级到多站点或创建新网络。
  • 接受参数如网络ID、域名、管理员邮箱、网络名称、路径和子域名安装标志,其中域名、邮箱和网络名称为必填项。
  • 执行前会触发 before_populate_network 钩子,进行参数验证(如空值检查、邮箱格式验证和网络冲突检测)。
  • 根据网络ID插入数据到 wpdb->site 表,并调用 populate_network_meta() 设置元数据。
  • 在单站点转多站点时,会创建主站点、更新用户元数据、设置固定链接结构,并触发 after_upgrade_to_multisite 钩子。
  • 对于子域名安装,会检查通配符DNS配置,失败时返回 WP_Error 警告。
  • 函数最后触发 after_populate_network 钩子,并返回 true 表示成功或 WP_Error 表示错误。

代码示例

populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false )

注意事项

  • 函数在 WordPress 3.0.0 版本引入,主要用于多站点环境。
  • 返回类型为 true 或 WP_Error,需检查错误代码以处理警告或失败情况。
  • 在现有多站点环境中使用此函数创建新网络时,不会执行单站点转多站点的额外步骤。
  • 子域名安装需要正确配置通配符DNS,否则可能无法访问子域名。

📄 原文内容

Populate network settings.

Parameters

$network_idintoptional
ID of network to populate.

Default:1

$domainstringrequired
The domain name for the network. Example: “example.com”.
$emailstringrequired
Email address for the network administrator.
$site_namestringrequired
The name of the network.
$pathstringoptional
The path to append to the network’s domain name. Default '/'.
$subdomain_installbooloptional
Whether the network is a subdomain installation or a subdirectory installation.
Default false, meaning the network is a subdirectory installation.

Default:false

Return

true|WP_Error True on success, or WP_Error on warning (with the installation otherwise successful, so the error code must be checked) or failure.

Source

function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) {
	global $wpdb, $current_site, $wp_rewrite;

	$network_id = (int) $network_id;

	/**
	 * Fires before a network is populated.
	 *
	 * @since 6.9.0
	 *
	 * @param int    $network_id        ID of network to populate.
	 * @param string $domain            The domain name for the network.
	 * @param string $email             Email address for the network administrator.
	 * @param string $site_name         The name of the network.
	 * @param string $path              The path to append to the network's domain name.
	 * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
	 */
	do_action( 'before_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );

	$errors = new WP_Error();
	if ( '' === $domain ) {
		$errors->add( 'empty_domain', __( 'You must provide a domain name.' ) );
	}
	if ( '' === $site_name ) {
		$errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) );
	}

	// Check for network collision.
	$network_exists = false;
	if ( is_multisite() ) {
		if ( get_network( $network_id ) ) {
			$errors->add( 'siteid_exists', __( 'The network already exists.' ) );
		}
	} else {
		if ( $network_id === (int) $wpdb->get_var(
			$wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id )
		) ) {
			$errors->add( 'siteid_exists', __( 'The network already exists.' ) );
		}
	}

	if ( ! is_email( $email ) ) {
		$errors->add( 'invalid_email', __( 'You must provide a valid email address.' ) );
	}

	if ( $errors->has_errors() ) {
		return $errors;
	}

	if ( 1 === $network_id ) {
		$wpdb->insert(
			$wpdb->site,
			array(
				'domain' => $domain,
				'path'   => $path,
			)
		);
		$network_id = $wpdb->insert_id;
	} else {
		$wpdb->insert(
			$wpdb->site,
			array(
				'domain' => $domain,
				'path'   => $path,
				'id'     => $network_id,
			)
		);
	}

	populate_network_meta(
		$network_id,
		array(
			'admin_email'       => $email,
			'site_name'         => $site_name,
			'subdomain_install' => $subdomain_install,
		)
	);

	// Remove the cron event since Recovery Mode is not used in Multisite.
	if ( wp_next_scheduled( 'recovery_mode_clean_expired_keys' ) ) {
		wp_clear_scheduled_hook( 'recovery_mode_clean_expired_keys' );
	}

	/*
	 * When upgrading from single to multisite, assume the current site will
	 * become the main site of the network. When using populate_network()
	 * to create another network in an existing multisite environment, skip
	 * these steps since the main site of the new network has not yet been
	 * created.
	 */
	if ( ! is_multisite() ) {
		$current_site            = new stdClass();
		$current_site->domain    = $domain;
		$current_site->path      = $path;
		$current_site->site_name = ucfirst( $domain );
		$wpdb->insert(
			$wpdb->blogs,
			array(
				'site_id'    => $network_id,
				'blog_id'    => 1,
				'domain'     => $domain,
				'path'       => $path,
				'registered' => current_time( 'mysql' ),
			)
		);
		$current_site->blog_id = $wpdb->insert_id;

		$site_user_id = (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT meta_value
				FROM $wpdb->sitemeta
				WHERE meta_key = %s AND site_id = %d",
				'admin_user_id',
				$network_id
			)
		);

		update_user_meta( $site_user_id, 'source_domain', $domain );
		update_user_meta( $site_user_id, 'primary_blog', $current_site->blog_id );

		// Unable to use update_network_option() while populating the network.
		$wpdb->insert(
			$wpdb->sitemeta,
			array(
				'site_id'    => $network_id,
				'meta_key'   => 'main_site',
				'meta_value' => $current_site->blog_id,
			)
		);

		if ( $subdomain_install ) {
			$wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
		} else {
			$wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' );
		}

		flush_rewrite_rules();

		/**
		 * Fires after a network is created when converting a single site to multisite.
		 *
		 * @since 6.9.0
		 *
		 * @param int    $network_id        ID of network created.
		 * @param string $domain            The domain name for the network.
		 * @param string $email             Email address for the network administrator.
		 * @param string $site_name         The name of the network.
		 * @param string $path              The path to append to the network's domain name.
		 * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
		 */
		do_action( 'after_upgrade_to_multisite', $network_id, $domain, $email, $site_name, $path, $subdomain_install );

		if ( ! $subdomain_install ) {
			return true;
		}

		$vhost_ok = false;
		$errstr   = '';
		$hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname!
		$page     = wp_remote_get(
			'http://' . $hostname,
			array(
				'timeout'     => 5,
				'httpversion' => '1.1',
			)
		);
		if ( is_wp_error( $page ) ) {
			$errstr = $page->get_error_message();
		} elseif ( 200 === wp_remote_retrieve_response_code( $page ) ) {
				$vhost_ok = true;
		}

		if ( ! $vhost_ok ) {
			$msg = '<p><strong>' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '</strong></p>';

			$msg .= '<p>' . sprintf(
				/* translators: %s: Host name. */
				__( 'The installer attempted to contact a random hostname (%s) on your domain.' ),
				'<code>' . $hostname . '</code>'
			);
			if ( ! empty( $errstr ) ) {
				/* translators: %s: Error message. */
				$msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '<code>' . $errstr . '</code>' );
			}
			$msg .= '</p>';

			$msg .= '<p>' . sprintf(
				/* translators: %s: Asterisk symbol (*). */
				__( 'To use a subdomain configuration, you must have a wildcard entry in your DNS. This usually means adding a %s hostname record pointing at your web server in your DNS configuration tool.' ),
				'<code>*</code>'
			) . '</p>';

			$msg .= '<p>' . __( 'You can still use your site but any subdomain you create may not be accessible. If you know your DNS is correct, ignore this message.' ) . '</p>';

			return new WP_Error( 'no_wildcard_dns', $msg );
		}
	}

	/**
	 * Fires after a network is fully populated.
	 *
	 * @since 6.9.0
	 *
	 * @param int    $network_id        ID of network created.
	 * @param string $domain            The domain name for the network.
	 * @param string $email             Email address for the network administrator.
	 * @param string $site_name         The name of the network.
	 * @param string $path              The path to append to the network's domain name.
	 * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
	 */
	do_action( 'after_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );

	return true;
}

Hooks

do_action( ‘after_populate_network’, int $network_id, string $domain, string $email, string $site_name, string $path, bool $subdomain_install )

Fires after a network is fully populated.

do_action( ‘after_upgrade_to_multisite’, int $network_id, string $domain, string $email, string $site_name, string $path, bool $subdomain_install )

Fires after a network is created when converting a single site to multisite.

do_action( ‘before_populate_network’, int $network_id, string $domain, string $email, string $site_name, string $path, bool $subdomain_install )

Fires before a network is populated.

Changelog

Version Description
3.0.0 Introduced.