wordpress学习第六篇(wp-includes/load.php)

本文介绍了WordPress中关键的24个内置函数,这些函数对于WordPress的正常运行至关重要。其中包括用于安全性设置、错误处理、多语言支持及插件管理等功能的实现。
<?php
/**
 * These functions are needed to load WordPress.
 *
 * @internal This file must be parsable by PHP4.
 *
 * @package WordPress
 */

/**
 * Turn register globals off.
 *
 * @access private
 * @since 2.1.0
 * @return null Will return null if register_globals PHP directive was disabled
 */
function wp_unregister_GLOBALS() {
	if ( !ini_get( 'register_globals' ) )
		return;

	if ( isset( $_REQUEST['GLOBALS'] ) )
		die( /*WP_I18N_GLOBALS_OVERWRITE*/'GLOBALS overwrite attempt detected'/*/WP_I18N_GLOBALS_OVERWRITE*/ );

	// Variables that shouldn't be unset
	$no_unset = array( 'GLOBALS', '_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES', 'table_prefix' );

	$input = array_merge( $_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_FILES, isset( $_SESSION ) && is_array( $_SESSION ) ? $_SESSION : array() );
	foreach ( $input as $k => $v )
		if ( !in_array( $k, $no_unset ) && isset( $GLOBALS[$k] ) ) {
			$GLOBALS[$k] = null;
			unset( $GLOBALS[$k] );
		}
}

/**
 * Fix $_SERVER variables for various setups.
 *
 * @access private
 * @since 3.0.0
 */
function wp_fix_server_vars() {
	global $PHP_SELF;

	$default_server_values = array(
		'SERVER_SOFTWARE' => '',
		'REQUEST_URI' => '',
	);

	$_SERVER = array_merge( $default_server_values, $_SERVER );

	// Fix for IIS when running with PHP ISAPI
	if ( empty( $_SERVER['REQUEST_URI'] ) || ( php_sapi_name() != 'cgi-fcgi' && preg_match( '/^Microsoft-IIS\//', $_SERVER['SERVER_SOFTWARE'] ) ) ) {

		// IIS Mod-Rewrite
		if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) {
			$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
		}
		// IIS Isapi_Rewrite
		else if ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) {
			$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
		} else {
			// Use ORIG_PATH_INFO if there is no PATH_INFO
			if ( !isset( $_SERVER['PATH_INFO'] ) && isset( $_SERVER['ORIG_PATH_INFO'] ) )
				$_SERVER['PATH_INFO'] = $_SERVER['ORIG_PATH_INFO'];

			// Some IIS + PHP configurations puts the script-name in the path-info (No need to append it twice)
			if ( isset( $_SERVER['PATH_INFO'] ) ) {
				if ( $_SERVER['PATH_INFO'] == $_SERVER['SCRIPT_NAME'] )
					$_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO'];
				else
					$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
			}

			// Append the query string if it exists and isn't null
			if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
				$_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
			}
		}
	}

	// Fix for PHP as CGI hosts that set SCRIPT_FILENAME to something ending in php.cgi for all requests
	if ( isset( $_SERVER['SCRIPT_FILENAME'] ) && ( strpos( $_SERVER['SCRIPT_FILENAME'], 'php.cgi' ) == strlen( $_SERVER['SCRIPT_FILENAME'] ) - 7 ) )
		$_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED'];

	// Fix for Dreamhost and other PHP as CGI hosts
	if ( strpos( $_SERVER['SCRIPT_NAME'], 'php.cgi' ) !== false )
		unset( $_SERVER['PATH_INFO'] );

	// Fix empty PHP_SELF
	$PHP_SELF = $_SERVER['PHP_SELF'];
	if ( empty( $PHP_SELF ) )
		$_SERVER['PHP_SELF'] = $PHP_SELF = preg_replace( '/(\?.*)?$/', '', $_SERVER["REQUEST_URI"] );
}

/**
 * Check for the required PHP version, and the MySQL extension or a database drop-in.
 *
 * Dies if requirements are not met.
 *
 * This function must be able to work without a complete environment set up. In wp-load.php, for
 * example, WP_CONTENT_DIR is defined and version.php is included before this function is called.
 *
 * @access private
 * @since 3.0.0
 */
function wp_check_php_mysql_versions() {
	// we can probably extend this function to check if wp_die() exists then use translated strings, and then use it in install.php etc.

	global $required_php_version, $wp_version;
	$php_version = phpversion();
	if ( version_compare( $required_php_version, $php_version, '>' ) )
		die( sprintf( /*WP_I18N_OLD_PHP*/'Your server is running PHP version %1$s but WordPress %2$s requires at least %3$s.'/*/WP_I18N_OLD_PHP*/, $php_version, $wp_version, $required_php_version ) );

	if ( !extension_loaded( 'mysql' ) && !file_exists( WP_CONTENT_DIR . '/db.php' ) )
		die( /*WP_I18N_OLD_MYSQL*/'Your PHP installation appears to be missing the MySQL extension which is required by WordPress.'/*/WP_I18N_OLD_MYSQL*/ );
}

/**
 * Don't load all of WordPress when handling a favicon.ico request.
 * Instead, send the headers for a zero-length favicon and bail.
 *
 * @since 3.0.0
 */
function wp_favicon_request() {
	if ( '/favicon.ico' == $_SERVER['REQUEST_URI'] ) {
		header('Content-Type: image/vnd.microsoft.icon');
		header('Content-Length: 0');
		exit;
	}
}

/**
 * Dies with a maintenance message when conditions are met.
 *
 * Checks for a file in the WordPress root directory named ".maintenance".
 * This file will contain the variable $upgrading, set to the time the file
 * was created. If the file was created less than 10 minutes ago, WordPress
 * enters maintenance mode and displays a message.
 *
 * The default message can be replaced by using a drop-in (maintenance.php in
 * the wp-content directory).
 *
 * @access private
 * @since 3.0.0
 */
function wp_maintenance() {
	if ( !file_exists( ABSPATH . '.maintenance' ) || defined( 'WP_INSTALLING' ) )
		return;

	global $upgrading;

	include( ABSPATH . '.maintenance' );
	// If the $upgrading timestamp is older than 10 minutes, don't die.
	if ( ( time() - $upgrading ) >= 600 )
		return;

	if ( file_exists( WP_CONTENT_DIR . '/maintenance.php' ) ) {
		require_once( WP_CONTENT_DIR . '/maintenance.php' );
		die();
	}

	$protocol = $_SERVER["SERVER_PROTOCOL"];
	if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
		$protocol = 'HTTP/1.0';
	header( "$protocol 503 Service Unavailable", true, 503 );
	header( 'Content-Type: text/html; charset=utf-8' );
	header( 'Retry-After: 600' );
?>
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title><?php echo /*WP_I18N_MAINTENANCE*/'Maintenance'/*/WP_I18N_MAINTENANCE*/; ?></title>

	</head>
	<body>
		<h1><?php echo /*WP_I18N_MAINT_MSG*/'Briefly unavailable for scheduled maintenance. Check back in a minute.'/*/WP_I18N_MAINT_MSG*/; ?></h1>
	</body>
	</html>
<?php
	die();
}

/**
 * PHP 4 standard microtime start capture.
 *
 * @access private
 * @since 0.71
 * @global int $timestart Seconds and Microseconds added together from when function is called.
 * @return bool Always returns true.
 */
function timer_start() {
	global $timestart;
	$mtime = explode( ' ', microtime() );
	$timestart = $mtime[1] + $mtime[0];
	return true;
}

/**
 * Return and/or display the time from the page start to when function is called.
 *
 * You can get the results and print them by doing:
 * <code>
 * $nTimePageTookToExecute = timer_stop();
 * echo $nTimePageTookToExecute;
 * </code>
 *
 * Or instead, you can do:
 * <code>
 * timer_stop(1);
 * </code>
 * which will do what the above does. If you need the result, you can assign it to a variable, but
 * most cases, you only need to echo it.
 *
 * @since 0.71
 * @global int $timestart Seconds and Microseconds added together from when timer_start() is called
 * @global int $timeend  Seconds and Microseconds added together from when function is called
 *
 * @param int $display Use '0' or null to not echo anything and 1 to echo the total time
 * @param int $precision The amount of digits from the right of the decimal to display. Default is 3.
 * @return float The "second.microsecond" finished time calculation
 */
function timer_stop( $display = 0, $precision = 3 ) { // if called like timer_stop(1), will echo $timetotal
	global $timestart, $timeend;
	$mtime = microtime();
	$mtime = explode( ' ', $mtime );
	$timeend = $mtime[1] + $mtime[0];
	$timetotal = $timeend - $timestart;
	$r = ( function_exists( 'number_format_i18n' ) ) ? number_format_i18n( $timetotal, $precision ) : number_format( $timetotal, $precision );
	if ( $display )
		echo $r;
	return $r;
}

/**
 * Sets PHP error handling and handles WordPress debug mode.
 *
 * Uses three constants: WP_DEBUG, WP_DEBUG_DISPLAY, and WP_DEBUG_LOG. All three can be
 * defined in wp-config.php. Example: <code> define( 'WP_DEBUG', true ); </code>
 *
 * WP_DEBUG_DISPLAY and WP_DEBUG_LOG perform no function unless WP_DEBUG is true.
 * WP_DEBUG defaults to false.
 *
 * When WP_DEBUG is true, all PHP notices are reported. WordPress will also display
 * notices, including one when a deprecated WordPress function, function argument,
 * or file is used. Deprecated code may be removed from a later version.
 *
 * It is strongly recommended that plugin and theme developers use WP_DEBUG in their
 * development environments.
 *
 * When WP_DEBUG_DISPLAY is true, WordPress will force errors to be displayed.
 * WP_DEBUG_DISPLAY defaults to true. Defining it as false prevents WordPress from
 * changing the global configuration setting. (Defining WP_DEBUG_DISPLAY as false
 * will never force errors to be hidden.)
 *
 * When WP_DEBUG_LOG is true, errors will be logged to wp-content/debug.log.
 * WP_DEBUG_LOG defaults to false.
 *
 * @access private
 * @since 3.0.0
 */
function wp_debug_mode() {
	if ( WP_DEBUG ) {
		// E_DEPRECATED is a core PHP constant in PHP 5.3. Don't define this yourself.
		// The two statements are equivalent, just one is for 5.3+ and for less than 5.3.
		if ( defined( 'E_DEPRECATED' ) )
			error_reporting( E_ALL & ~E_DEPRECATED & ~E_STRICT );
		else
			error_reporting( E_ALL );

		if ( WP_DEBUG_DISPLAY )
			ini_set( 'display_errors', 1 );

		if ( WP_DEBUG_LOG ) {
			ini_set( 'log_errors', 1 );
			ini_set( 'error_log', WP_CONTENT_DIR . '/debug.log' );
		}
	} else {
		error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );
	}
}

/**
 * Sets the location of the language directory.
 *
 * To set directory manually, define <code>WP_LANG_DIR</code> in wp-config.php.
 *
 * If the language directory exists within WP_CONTENT_DIR that is used
 * Otherwise if the language directory exists within WPINC, that's used
 * Finally, If neither of the preceeding directories is found,
 * WP_CONTENT_DIR/languages is used.
 *
 * The WP_LANG_DIR constant was introduced in 2.1.0.
 *
 * @access private
 * @since 3.0.0
 */
function wp_set_lang_dir() {
	if ( !defined( 'WP_LANG_DIR' ) ) {
		if ( file_exists( WP_CONTENT_DIR . '/languages' ) && @is_dir( WP_CONTENT_DIR . '/languages' ) || !@is_dir(ABSPATH . WPINC . '/languages') ) {
			define( 'WP_LANG_DIR', WP_CONTENT_DIR . '/languages' ); // no leading slash, no trailing slash, full path, not relative to ABSPATH
			if ( !defined( 'LANGDIR' ) ) {
				// Old static relative path maintained for limited backwards compatibility - won't work in some cases
				define( 'LANGDIR', 'wp-content/languages' );
			}
		} else {
			define( 'WP_LANG_DIR', ABSPATH . WPINC . '/languages' ); // no leading slash, no trailing slash, full path, not relative to ABSPATH
			if ( !defined( 'LANGDIR' ) ) {
				// Old relative path maintained for backwards compatibility
				define( 'LANGDIR', WPINC . '/languages' );
			}
		}
	}
}

/**
 * Load the correct database class file.
 *
 * This function is used to load the database class file either at runtime or by
 * wp-admin/setup-config.php. We must globalize $wpdb to ensure that it is
 * defined globally by the inline code in wp-db.php.
 *
 * @since 2.5.0
 * @global $wpdb WordPress Database Object
 */
function require_wp_db() {
	global $wpdb;

	require_once( ABSPATH . WPINC . '/wp-db.php' );
	if ( file_exists( WP_CONTENT_DIR . '/db.php' ) )
		require_once( WP_CONTENT_DIR . '/db.php' );

	if ( isset( $wpdb ) )
		return;

	$wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
}

/**
 * Sets the database table prefix and the format specifiers for database table columns.
 *
 * Columns not listed here default to %s.
 *
 * @see wpdb::$field_types Since 2.8.0
 * @see wpdb::prepare()
 * @see wpdb::insert()
 * @see wpdb::update()
 * @see wpdb::set_prefix()
 *
 * @access private
 * @since 3.0.0
 */
function wp_set_wpdb_vars() {
	global $wpdb, $table_prefix;
	if ( !empty( $wpdb->error ) )
		dead_db();

	$wpdb->field_types = array( 'post_author' => '%d', 'post_parent' => '%d', 'menu_order' => '%d', 'term_id' => '%d', 'term_group' => '%d', 'term_taxonomy_id' => '%d',
		'parent' => '%d', 'count' => '%d','object_id' => '%d', 'term_order' => '%d', 'ID' => '%d', 'commment_ID' => '%d', 'comment_post_ID' => '%d', 'comment_parent' => '%d',
		'user_id' => '%d', 'link_id' => '%d', 'link_owner' => '%d', 'link_rating' => '%d', 'option_id' => '%d', 'blog_id' => '%d', 'meta_id' => '%d', 'post_id' => '%d',
		'user_status' => '%d', 'umeta_id' => '%d', 'comment_karma' => '%d', 'comment_count' => '%d',
		// multisite:
		'active' => '%d', 'cat_id' => '%d', 'deleted' => '%d', 'lang_id' => '%d', 'mature' => '%d', 'public' => '%d', 'site_id' => '%d', 'spam' => '%d',
	);

	$prefix = $wpdb->set_prefix( $table_prefix );

	if ( is_wp_error( $prefix ) )
		wp_die( /*WP_I18N_BAD_PREFIX*/'<strong>ERROR</strong>: <code>$table_prefix</code> in <code>wp-config.php</code> can only contain numbers, letters, and underscores.'/*/WP_I18N_BAD_PREFIX*/ );
}

/**
 * Starts the WordPress object cache.
 *
 * If an object-cache.php file exists in the wp-content directory,
 * it uses that drop-in as an external object cache.
 *
 * @access private
 * @since 3.0.0
 */
function wp_start_object_cache() {
	global $_wp_using_ext_object_cache;

	$first_init = false;
 	if ( ! function_exists( 'wp_cache_init' ) ) {
		if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
			require_once ( WP_CONTENT_DIR . '/object-cache.php' );
			$_wp_using_ext_object_cache = true;
		} else {
			require_once ( ABSPATH . WPINC . '/cache.php' );
			$_wp_using_ext_object_cache = false;
		}
		$first_init = true;
	} else if ( !$_wp_using_ext_object_cache && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
		// Sometimes advanced-cache.php can load object-cache.php before it is loaded here.
		// This breaks the function_exists check above and can result in $_wp_using_ext_object_cache
		// being set incorrectly.  Double check if an external cache exists.
		$_wp_using_ext_object_cache = true;
	}

	// If cache supports reset, reset instead of init if already initialized.
	// Reset signals to the cache that global IDs have changed and it may need to update keys
	// and cleanup caches.
	if ( !$first_init && function_exists('wp_cache_reset') )
		wp_cache_reset();
	else
		wp_cache_init();

	if ( function_exists( 'wp_cache_add_global_groups' ) ) {
		wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts' ) );
		wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
	}
}

/**
 * Redirects to the installer if WordPress is not installed.
 *
 * Dies with an error message when multisite is enabled.
 *
 * @access private
 * @since 3.0.0
 */
function wp_not_installed() {
	if ( is_multisite() ) {
		if ( ! is_blog_installed() && ! defined( 'WP_INSTALLING' ) )
			wp_die( __( 'The site you have requested is not installed properly. Please contact the system administrator.' ) );
	} elseif ( ! is_blog_installed() && false === strpos( $_SERVER['PHP_SELF'], 'install.php' ) && !defined( 'WP_INSTALLING' ) ) {

		$link = wp_guess_url() . '/wp-admin/install.php';

		require( ABSPATH . WPINC . '/kses.php' );
		require( ABSPATH . WPINC . '/pluggable.php' );
		require( ABSPATH . WPINC . '/formatting.php' );
		wp_redirect( $link );
		die();
	}
}

/**
 * Returns array of must-use plugin files to be included in global scope.
 *
 * The default directory is wp-content/mu-plugins. To change the default directory
 * manually, define <code>WPMU_PLUGIN_DIR</code> and <code>WPMU_PLUGIN_URL</code>
 * in wp-config.php.
 *
 * @access private
 * @since 3.0.0
 * @return array Files to include
 */
function wp_get_mu_plugins() {
	$mu_plugins = array();
	if ( !is_dir( WPMU_PLUGIN_DIR ) )
		return $mu_plugins;
	if ( ! $dh = opendir( WPMU_PLUGIN_DIR ) )
		return $mu_plugins;
	while ( ( $plugin = readdir( $dh ) ) !== false ) {
		if ( substr( $plugin, -4 ) == '.php' )
			$mu_plugins[] = WPMU_PLUGIN_DIR . '/' . $plugin;
	}
	closedir( $dh );
	sort( $mu_plugins );

	return $mu_plugins;
}

/**
 * Returns array of plugin files to be included in global scope.
 *
 * The default directory is wp-content/plugins. To change the default directory
 * manually, define <code>WP_PLUGIN_DIR</code> and <code>WP_PLUGIN_URL</code>
 * in wp-config.php.
 *
 * @access private
 * @since 3.0.0
 * @return array Files to include
 */
function wp_get_active_and_valid_plugins() {
	$plugins = array();
	$active_plugins = (array) get_option( 'active_plugins', array() );

	// Check for hacks file if the option is enabled
	if ( get_option( 'hack_file' ) && file_exists( ABSPATH . 'my-hacks.php' ) ) {
		_deprecated_file( 'my-hacks.php', '1.5' );
		array_unshift( $plugins, ABSPATH . 'my-hacks.php' );
	}

	if ( empty( $active_plugins ) || defined( 'WP_INSTALLING' ) )
		return $plugins;

	$network_plugins = is_multisite() ? wp_get_active_network_plugins() : false;

	foreach ( $active_plugins as $plugin ) {
		if ( ! validate_file( $plugin ) // $plugin must validate as file
			&& '.php' == substr( $plugin, -4 ) // $plugin must end with '.php'
			&& file_exists( WP_PLUGIN_DIR . '/' . $plugin ) // $plugin must exist
			// not already included as a network plugin
			&& ( ! $network_plugins || ! in_array( WP_PLUGIN_DIR . '/' . $plugin, $network_plugins ) )
			)
		$plugins[] = WP_PLUGIN_DIR . '/' . $plugin;
	}
	return $plugins;
}

/**
 * Sets internal encoding using mb_internal_encoding().
 *
 * In most cases the default internal encoding is latin1, which is of no use,
 * since we want to use the mb_ functions for utf-8 strings.
 *
 * @access private
 * @since 3.0.0
 */
function wp_set_internal_encoding() {
	if ( function_exists( 'mb_internal_encoding' ) ) {
		if ( !@mb_internal_encoding( get_option( 'blog_charset' ) ) )
			mb_internal_encoding( 'UTF-8' );
	}
}

/**
 * Add magic quotes to $_GET, $_POST, $_COOKIE, and $_SERVER.
 *
 * Also forces $_REQUEST to be $_GET + $_POST. If $_SERVER, $_COOKIE,
 * or $_ENV are needed, use those superglobals directly.
 *
 * @access private
 * @since 3.0.0
 */
function wp_magic_quotes() {
	// If already slashed, strip.
	if ( get_magic_quotes_gpc() ) {
		$_GET    = stripslashes_deep( $_GET    );
		$_POST   = stripslashes_deep( $_POST   );
		$_COOKIE = stripslashes_deep( $_COOKIE );
	}

	// Escape with wpdb.
	$_GET    = add_magic_quotes( $_GET    );
	$_POST   = add_magic_quotes( $_POST   );
	$_COOKIE = add_magic_quotes( $_COOKIE );
	$_SERVER = add_magic_quotes( $_SERVER );

	// Force REQUEST to be GET + POST.
	$_REQUEST = array_merge( $_GET, $_POST );
}

/**
 * Runs just before PHP shuts down execution.
 *
 * @access private
 * @since 1.2.0
 */
function shutdown_action_hook() {
	do_action( 'shutdown' );
	wp_cache_close();
}

/**
 * Copy an object.
 *
 * @since 2.7.0
 * @deprecated 3.2
 *
 * @param object $object The object to clone
 * @return object The cloned object
 */

function wp_clone( $object ) {
	// Use parens for clone to accommodate PHP 4.  See #17880
	return clone( $object );
}

/**
 * Whether the current request is for a network or blog admin page
 *
 * Does not inform on whether the user is an admin! Use capability checks to
 * tell if the user should be accessing a section or not.
 *
 * @since 1.5.1
 *
 * @return bool True if inside WordPress administration pages.
 */
function is_admin() {
	if ( defined( 'WP_ADMIN' ) )
		return WP_ADMIN;
	return false;
}

/**
 * Whether the current request is for a blog admin screen /wp-admin/
 *
 * Does not inform on whether the user is a blog admin! Use capability checks to
 * tell if the user should be accessing a section or not.
 *
 * @since 3.1.0
 *
 * @return bool True if inside WordPress network administration pages.
 */
function is_blog_admin() {
	if ( defined( 'WP_BLOG_ADMIN' ) )
		return WP_BLOG_ADMIN;
	return false;
}

/**
 * Whether the current request is for a network admin screen /wp-admin/network/
 *
 * Does not inform on whether the user is a network admin! Use capability checks to
 * tell if the user should be accessing a section or not.
 *
 * @since 3.1.0
 *
 * @return bool True if inside WordPress network administration pages.
 */
function is_network_admin() {
	if ( defined( 'WP_NETWORK_ADMIN' ) )
		return WP_NETWORK_ADMIN;
	return false;
}

/**
 * Whether the current request is for a user admin screen /wp-admin/user/
 *
 * Does not inform on whether the user is an admin! Use capability checks to
 * tell if the user should be accessing a section or not.
 *
 * @since 3.1.0
 *
 * @return bool True if inside WordPress user administration pages.
 */
function is_user_admin() {
	if ( defined( 'WP_USER_ADMIN' ) )
		return WP_USER_ADMIN;
	return false;
}

/**
 * Whether Multisite support is enabled
 *
 * @since 3.0.0
 *
 * @return bool True if multisite is enabled, false otherwise.
 */
function is_multisite() {
	if ( defined( 'MULTISITE' ) )
		return MULTISITE;

	if ( defined( 'SUBDOMAIN_INSTALL' ) || defined( 'VHOST' ) || defined( 'SUNRISE' ) )
		return true;

	return false;
}

?>
这个文件都是一些函数。
wp_unregister_GLOBALS(),wp_fix_server_vars(),wp_check_php_mysql_versions(),wp_favicon_request(),wp_maintenance(),timer_start(),timer_stop(),wp_debug_mode(),wp_set_lang_dir(),require_wp_db(),wp_set_wpdb_vars(),wp_start_object_cache(),wp_not_installed(), wp_get_mu_plugins(), wp_get_active_and_valid_plugins(), wp_set_internal_encoding(), wp_magic_quotes(), shutdown_action_hook(), wp_clone( $object ), is_admin(), is_blog_admin(),is_network_admin(), is_user_admin(), is_multisite(), 一共24个函数。其中有几个常用的函数,比如is_admin()。
<think>我们正在处理一个MySQL数据库连接错误:mysqli_sql_exception: Access denied for user &#39;username_here&#39;@&#39;localhost&#39; (using password: YES) 错误发生在文件`/usr/local/nginx/html/wp-includes/wp-db.php`的第1531行。 根据错误信息,问题在于数据库访问被拒绝,可能是由于用户名、密码不正确,或者用户没有权限从localhost访问。 步骤: 1. 确认数据库凭据:检查WordPress的配置文件`wp-config.php`,确认其中的`DB_USER`和`DB_PASSWORD`是否正确。 2. 检查用户权限:确保该数据库用户被授予了从localhost访问数据库的权限。 3. 检查数据库服务状态:确保MySQL/MariaDB服务正在运行。 4. 检查主机名:有时可能是主机名的问题,例如使用了&#39;localhost&#39;还是IP地址。 详细步骤: a) 打开WordPress的配置文件wp-config.php(通常位于网站根目录,例如`/usr/local/nginx/html/`)。 查找以下定义: define(&#39;DB_NAME&#39;, &#39;database_name_here&#39;); define(&#39;DB_USER&#39;, &#39;username_here&#39;); define(&#39;DB_PASSWORD&#39;, &#39;password_here&#39;); define(&#39;DB_HOST&#39;, &#39;localhost&#39;); 确保这些值与MySQL中设置的一致。 b) 使用MySQL命令行客户端登录,验证凭据: mysql -u username_here -p 然后输入密码,看是否能登录。 c) 如果无法登录,可能是密码错误或者用户不存在。需要重置密码或创建用户。 以root用户登录MySQL: mysql -u root -p 然后检查用户是否存在: SELECT User, Host FROM mysql.user; 创建用户或修改密码: -- 如果用户不存在,创建用户并授权 CREATE USER &#39;username_here&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;your_password&#39;; GRANT ALL PRIVILEGES ON database_name_here.* TO &#39;username_here&#39;@&#39;localhost&#39;; FLUSH PRIVILEGES; -- 如果用户存在,修改密码 ALTER USER &#39;username_here&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;new_password&#39;; FLUSH PRIVILEGES; d) 检查数据库主机:有时可能需要使用127.0.0.1而不是localhost(取决于MySQL配置)。 在wp-config.php中,尝试将DB_HOST改为&#39;127.0.0.1&#39;。 e) 检查MySQL服务是否监听:确保MySQL服务正在运行,并且监听在正确的地址(localhost或127.0.0.1)。 另外,注意错误是由WordPress的核心文件`wp-db.php`触发的,这意味着是WordPress尝试连接数据库时失败。因此,问题主要集中在数据库连接配置上。 完成更改后,重新加载网页查看是否解决。 如果问题仍然存在,可以检查MySQL错误日志(通常在/var/log/mysql/error.log或/var/log/mariadb/mariadb.log)以获取更多信息。 安全提示:确保在数据库和配置文件中使用安全的密码,并且配置文件wp-config.php的权限设置正确(例如,644权限,并且属于正确的用户,避免Web服务器用户以外的其他用户有写权限)。 生成相关问题: 用户可能会在解决过程中遇到其他相关的问题,因此我们可以生成一些相关问题以便进一步帮助。 </think> ### 解决数据库连接错误:Access denied for user 您遇到的错误是MySQL连接认证失败,表明WordPress无法使用提供的凭据连接到数据库。以下是系统性的解决方案: --- ### 诊断与解决步骤 1. **检查`wp-config.php`文件** - 路径:`/usr/local/nginx/html/wp-config.php` - 确认以下参数与MySQL实际设置一致: ```php define(&#39;DB_NAME&#39;, &#39;database_name&#39;); // 数据库名 define(&#39;DB_USER&#39;, &#39;username_here&#39;); // 用户名 define(&#39;DB_PASSWORD&#39;, &#39;password_here&#39;); // 密码 define(&#39;DB_HOST&#39;, &#39;localhost&#39;); // 主机地址 ``` - **注意**:密码特殊字符需正确转义[^1] 2. **验证MySQL用户权限** - 登录MySQL命令行(需root权限): ```bash mysql -u root -p ``` - 执行权限检查: ```sql SHOW GRANTS FOR &#39;username_here&#39;@&#39;localhost&#39;; ``` - 若权限缺失,授予权限: ```sql GRANT ALL PRIVILEGES ON database_name.* TO &#39;username_here&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;your_password&#39;; FLUSH PRIVILEGES; ``` 3. **测试密码有效性** - 手动测试连接: ```bash mysql -u username_here -p -h localhost ``` 输入密码后若登录失败,需重置密码: ```sql ALTER USER &#39;username_here&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;new_password&#39;; ``` 4. **检查主机绑定问题** - 尝试将`DB_HOST`替换为`127.0.0.1`(避免localhost解析问题) - 核实MySQL是否监听本地连接: ```bash netstat -tulpn | grep mysql ``` 确保存在 `127.0.0.1:3306` 条目 5. **检查MySQL用户存在性** ```sql SELECT User, Host FROM mysql.user; ``` 若无结果,需重建用户: ```sql CREATE USER &#39;username_here&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;password&#39;; ``` 6. **配置文件权限修复** ```bash chmod 640 /usr/local/nginx/html/wp-config.php chown www-data:www-data /usr/local/nginx/html/wp-config.php # 用户组依环境调整 ``` --- ### 高级排查 - **MySQL错误日志分析** 查看日志定位深层原因(路径参考): ```bash /var/log/mysql/error.log # 常见路径 ``` - **SELinux/Firewall干扰** 临时禁用测试: ```bash setenforce 0 # 禁用SELinux systemctl stop firewalld # 停止防火墙 ``` --- ### 故障树 ```mermaid graph TD A[Access Denied错误] --> B{检查wp-config.php} A --> C{测试MySQL登录} B -->|配置错误| D[修正数据库凭据] C -->|登录失败| E[重置密码/创建用户] A --> F{主机绑定问题} F -->|localhost解析异常| G[改用127.0.0.1] A --> H{权限缺失} H --> I[GRANT授权] ``` ---
PHP中出现 `Fatal error: Uncaught mysqli_sql_exception` 显示 `Unknown column &#39;option_name&#39; in &#39;field list&#39;` 错误,通常意味着在SQL查询语句里引用了数据库表中不存在的列。下面给出一些可能的解决办法: ### 1. 核查数据库表结构 要保证数据库表中确实存在 `option_name` 列。可以借助数据库管理工具(像phpMyAdmin)查看表结构。例如,在MySQL命令行里使用以下命令查看表结构: ```sql SHOW COLUMNS FROM your_table_name; ``` 要把 `your_table_name` 替换成实际的表名。 ### 2. 检查SQL查询语句 仔细检查PHP代码里的SQL查询语句,保证没有拼写错误。例如,有如下代码: ```php <?php $mysqli = new mysqli("localhost", "username", "password", "database_name"); if ($mysqli->connect_error) { die("Connection failed: " . $mysqli->connect_error); } $sql = "SELECT option_name, option_value FROM your_table_name"; $result = $mysqli->query($sql); if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo "Option Name: " . $row["option_name"]. " - Option Value: " . $row["option_value"]. "<br>"; } } else { echo "0 results"; } $mysqli->close(); ?> ``` 要确保 `option_name` 在表中存在,并且查询语句没有拼写错误。 ### 3. 检查wp - db文件 如果涉及到 `wp - db` 文件(通常在WordPress项目里)报错,要检查该文件里的SQL查询语句。WordPress有自己的数据库抽象层,可能在某些函数调用时传入了错误的列名。检查相关函数调用,保证传入的列名正确。 ### 4. 缓存问题 有时候,数据库的缓存可能会造成问题。可以尝试清除数据库缓存或者重启数据库服务。 ### 5. 数据库版本兼容性 要确保PHP和数据库版本兼容。某些数据库版本可能对SQL语法有不同的支持。
<think>我们正在讨论的是如何通过渗透测试访问目标服务器上的MySQL.php文件内容。根据之前的对话,我们知道这个文件确实存在(返回500错误),但无法直接访问到内容。引用[1]中提到了一种通过包含.frm文件来执行代码的方法,但未成功,因为该服务器上/var/lib/mysql下没有存储.frm文件。然而,这给我们提供了一种思路:如果能够利用文件包含漏洞,就可能读取到目标文件的内容。目标:读取https://www.asds.com/wp-includes/SimplePie/Cache/MySQL.php的内容可能的渗透测试方法:1. **直接文件包含漏洞利用**:如果目标网站存在文件包含漏洞(LFI或RFI),我们可以尝试包含该PHP文件。但是,由于该文件是PHP脚本,直接包含会导致其执行(我们之前看到执行会报500错误),而我们想要的是源代码。因此,需要结合其他技巧来避免执行,例如:-使用PHP伪协议:`php://filter`来读取源代码示例:`https://www.asds.com/vulnerable_page.php?file=php://filter/convert.base64-encode/resource=wp-includes/SimplePie/Cache/MySQL.php`这样会返回Base64编码的源代码,解码即可。2.**路径遍历漏洞**:如果目标网站有任意文件读取漏洞(比如通过参数传递文件路径),我们可以尝试直接读取该文件。例如:`https://www.asds.com/download.php?file=../../../../wp-includes/SimplePie/Cache/MySQL.php`但这种方式需要找到有文件读取功能的页面,并且该页面没有对路径进行严格过滤。3.**利用已知的WordPress漏洞**:由于目标路径是WordPresswp-includes目录,我们可以查找该版本WordPress(结合PHP5.6.40,可能WordPress版本较老)是否存在已知漏洞。例如:- WordPress核心文件中的任意文件读取漏洞(如CVE-2018-20148)-插件或主题中的漏洞4. **日志文件注入**:如果我们可以控制服务器日志(如访问日志、错误日志)的内容,就可以尝试将PHP代码写入日志,然后通过文件包含来执行。但这里我们的目的是读取源代码,而不是执行代码。不过,如果我们能够包含目标文件并使其以文本形式输出(比如通过Base64编码),那么也可以实现读取。但这个方法需要文件包含漏洞。5.**MySQL注入与文件读取**:如果我们能够找到SQL注入点,并且数据库用户有文件读写权限,我们可以尝试用`LOAD_FILE()`函数读取文件内容。但是,我们需要知道文件的绝对路径。示例注入语句:`SELECTLOAD_FILE(&#39;/var/www/html/wp-includes/SimplePie/Cache/MySQL.php&#39;)`然后通过注入点将文件内容输出。但是,这里有两个问题:-需要知道文件的绝对路径(我们可以通过错误信息、常见路径猜测、或利用其他漏洞获取)-需要有一个能够输出查询结果的注入点(如联合查询注入)6. **利用PHP的报错信息**:如果我们能够触发目标文件中的某些错误,并且服务器配置了显示错误,那么错误信息中可能会泄露部分源代码。但是,这通常只能看到片段,不是完整文件。7.**利用备份文件或临时文件**:尝试访问该文件的备份(如MySQL.php.bak,MySQL.php~,.MySQL.php.swp等)来获取源代码。但这种方法需要猜测备份文件名。8.**利用.htaccess配置错误**:如果目标目录的.htaccess配置不当,可能导致PHP文件被当作文本文件返回。我们可以尝试直接访问该文件,但通常服务器会解析PHP文件,所以我们需要想办法让服务器不解析该文件。例如,如果服务器配置了`AddType text/plain.php`,那么我们可以直接读取。但这通常不会发生。9. **利用文件包含漏洞包含自身**:如果存在文件包含漏洞,且我们可以包含目标文件,但为了避免执行,我们可以使用Base64编码输出(如前所述)。步骤建议:1.**寻找文件包含漏洞**:在目标网站中寻找可能存在文件包含的功能点,如:-页面参数中包含文件路径(如index.php?page=about.php-模板加载功能2.**尝试使用PHP伪协议**:如果存在文件包含,尝试使用`php://filter`来读取目标文件。3.**寻找任意文件下载漏洞**:检查网站是否有文件下载功能,并尝试路径遍历。4. **扫描备份文件**:使用工具(如DirBuster,GoBuster)扫描备份文件,或者手动尝试:-https://www.asds.com/wp-includes/SimplePie/Cache/MySQL.php.bak- https://www.asds.com/wp-includes/SimplePie/Cache/MySQL.php~-https://www.asds.com/wp-includes/SimplePie/Cache/MySQL.php.swp5. **利用SQL注入**:寻找SQL注入点,并尝试读取文件(需要知道绝对路径)。6.**利用已知漏洞**:使用漏洞扫描器(如WPScan)扫描目标WordPress,查找已知漏洞。关于文件绝对路径的获取方法:-通过错误信息(如包含文件时的错误会显示路径)-通过PHP配置文件(php.ini)中的路径(如果能够读取)-常见路径(如Linux下:/var/www/html/,/usr/local/apache2/htdocs/;Windows下:C:\xampp\htdocs\,C:\inetpub\wwwroot\)-通过数据库(如MySQL的@@datadir,可以推测出Web目录,因为通常Web目录和数据库目录在同一层级,如/var/lib/mysql/对应Web目录可能是/var/www/html/)[^2]注意:渗透测试必须在授权的情况下进行,未经授权进行渗透测试是非法的。由于我们之前已经知道目标文件存在(返回500错误),所以我们可以尝试直接访问该文件,但会返回500错误(且不会显示源代码)。因此,我们需要绕过执行,获取源代码。总结:最直接有效的方法是利用文件包含漏洞配合PHP伪协议。如果存在文件包含,那么读取源代码就很简单。如果以上方法都不可行,可能需要结合其他漏洞(如目录遍历、备份文件等)。相关问题:1.如何检测网站是否存在本地文件包含漏洞?2.如何利用SQL注入读取服务器上的文件?3.WordPress渗透测试中,有哪些常见的敏感文件路径?</think>### 通过渗透测试访问 MySQL.php 文件内容的可行方法 根据目标环境特征(Apache/PHP 5.6.40)和引用信息,以下是可尝试的渗透测试方法: --- #### 1. **利用文件包含漏洞(LFI)** **原理**:通过路径遍历包含目标文件,结合PHP伪协议获取源码 **步骤**: ```url https://www.asds.com/vulnerable_page.php?file=php://filter/convert.base64-encode/resource=wp-includes/SimplePie/Cache/MySQL.php ``` - 需要找到存在文件包含漏洞的页面(如主题/插件中的参数) - `convert.base64-encode` 可避免PHP执行,直接输出Base64编码的源码 - 解码命令:`base64 -d file.txt` **关键点**: - 尝试常见包含参数:`?page=`, `?file=`, `?include=` 等 - Windows路径尝试:`../../../../ProgramData/MySQL/MySQL Server 5.6/Data/[dbname]/[table].frm` [^2] --- #### 2. **MySQL注入读取文件** **原理**:利用SQL注入点通过`LOAD_FILE()`函数读取文件 **前提**: - 存在SQL注入漏洞 - MySQL用户需有`FILE`权限 - 知晓文件绝对路径(可通过`@@datadir`获取数据库路径推测)[^2] **注入示例**: ```sql UNION SELECT LOAD_FILE(&#39;/var/www/html/wp-includes/SimplePie/Cache/MySQL.php&#39;), NULL, NULL-- ``` **路径猜测**: - Linux:`/var/www/html/...`、`/usr/local/apache2/htdocs/...` - Windows:`C:\xampp\htdocs\...`、`D:\phpstudy_pro\WWW\...` [^3] --- #### 3. **备份文件泄露** **原理**:访问编辑器/系统生成的备份文件 **常见备份路径**: ```url https://www.asds.com/wp-includes/SimplePie/Cache/MySQL.php.bak https://www.asds.com/wp-includes/SimplePie/Cache/.MySQL.php.swp https://www.asds.com/wp-includes/SimplePie/Cache/MySQL.php~ ``` **利用工具**: ```bash gobuster dir -u https://www.asds.com -w /path/to/wordlist.txt -x php,bak,swp,old ``` --- #### 4. **日志文件包含** **原理**:通过访问日志/错误日志包含PHP文件 **步骤**: 1. 确定日志路径(默认路径或通过错误信息推测) - Apache日志:`/var/log/httpd/access_log` - 错误日志:`/var/log/httpd/error_log` 2. 发送包含PHP标签的请求: ```http GET /<?php system(&#39;id&#39;);?> HTTP/1.1 Host: www.asds.com ``` 3. 包含日志文件: ```url https://www.asds.com/lfi.php?file=/var/log/httpd/access_log ``` --- #### 5. **跨库攻击(需满足条件)** **原理**:当多个站点共享数据库用户时[^3] **利用步骤**: 1. 通过站点A获取数据库凭据 2. 连接MySQL后执行: ```sql SELECT LOAD_FILE(&#39;C:\\path\\to\\siteB\\wp-includes\\SimplePie\\Cache\\MySQL.php&#39;) ``` --- ### 防御措施分析(供渗透参考) 1. **文件权限**: - PHP文件应设置为644权限 - Web目录不可写:`chmod -R 755 /var/www/html` 2. **路径隔离**: ```nginx location ~ ^/wp-includes/ { deny all; # 禁止直接访问 } ``` 3. **数据库加固**: ```sql REVOKE FILE ON *.* FROM &#39;webuser&#39;@&#39;localhost&#39;; ``` ---
WordPress 6.7.0版本中,若`load_textdomain`函数调用不正确,且`astra - sites`域名翻译加载过早,可尝试以下解决办法。 ### 1. 检查`load_textdomain`调用位置 `load_textdomain`函数通常在主题或插件的初始化阶段调用。确保该函数是在`plugins_loaded`或`after_setup_theme`钩子中调用,以保证WordPress环境已完全加载。 ```php add_action( &#39;plugins_loaded&#39;, &#39;your_plugin_load_textdomain&#39; ); function your_plugin_load_textdomain() { load_plugin_textdomain( &#39;astra-sites&#39;, false, basename( dirname( __FILE__ ) ) . &#39;/languages&#39; ); } ``` 上述代码将`load_textdomain`的调用放在`plugins_loaded`钩子中,这样可以避免过早加载翻译文件。 ### 2. 延迟加载翻译文件 若`astra - sites`域名翻译加载过早,可使用`defer_load_textdomain`函数来延迟加载。 ```php add_filter( &#39;defer_load_textdomain&#39;, &#39;your_defer_astra_sites_textdomain&#39;, 10, 3 ); function your_defer_astra_sites_textdomain( $defer, $domain, $mofile ) { if ( &#39;astra-sites&#39; === $domain ) { return true; } return $defer; } ``` 该代码通过`defer_load_textdomain`过滤器,将`astra - sites`域名的翻译文件加载延迟。 ### 3. 检查插件和主题冲突 有时,其他插件或主题可能会干扰`load_textdomain`的正常调用。可通过停用其他插件,逐个排查是否存在冲突。同时,确保使用的主题和插件是最新版本,以避免已知的兼容性问题。 ### 4. 检查翻译文件路径和命名 确保翻译文件(`.mo`和`.po`文件)的路径和命名正确。翻译文件应存放在主题或插件的`languages`目录下,且文件名遵循`{domain}-{locale}.mo`的格式,例如`astra-sites-en_US.mo`。
### 检查插件和主题更新 确保 Astra Sites 插件以及其他相关插件和主题是最新版本。有时候,此类问题是由于旧版本中的 bug 引起的,更新到最新版本可能会修复这些问题。可以在 WordPress 后台的“插件”和“主题”页面中检查更新并进行安装。 ### 停用不必要的插件 一些插件可能会与 Astra Sites 插件或 `_load_textdomain_just_in_time` 函数产生冲突,导致翻译加载过早。可以逐个停用不必要的插件,然后检查问题是否仍然存在。在 WordPress 后台的“插件”页面中停用插件,每次停用一个插件后刷新网站,查看问题是否解决。 ### 代码调试与修改 可以通过添加调试代码来查看 `_load_textdomain_just_in_time` 函数的调用情况。在主题的 `functions.php` 文件中添加以下代码: ```php add_action(&#39;debug_textdomain_loading&#39;, function ($domain, $mofile, $locale) { if ($domain === &#39;astra-sites&#39;) { error_log("Astra Sites translation loading: Domain: $domain, MO file: $mofile, Locale: $locale"); } }, 10, 3); ``` 这段代码会在翻译加载时记录相关信息到错误日志中,通过查看错误日志可以了解翻译加载的具体情况。 如果发现是代码逻辑问题,可以尝试修改相关代码。例如,可以使用 `remove_action` 和 `add_action` 来调整 `_load_textdomain_just_in_time` 函数的调用时机。以下是一个示例: ```php // 移除原有的加载动作 remove_action(&#39;init&#39;, &#39;astra_sites_load_textdomain&#39;, 0); // 重新添加加载动作,调整优先级 add_action(&#39;init&#39;, &#39;astra_sites_load_textdomain&#39;, 10); ``` ### 联系插件开发者 如果以上方法都无法解决问题,可以联系 Astra Sites 插件的开发者。提供详细的问题描述、网站环境信息(如 WordPress 版本、PHP 版本等)以及错误日志,以便开发者更好地定位和解决问题。
<think>我们正在解决WordPress中`_load_textdomain_just_in_time`函数被错误调用的问题,具体是关于redux-framework的翻译加载过早,在initaction之前的问题。根据引用[2]:load_theme_textdomain()函数用于载入主题的本地化语言文件。这通常是在主题初始化时进行的。错误提示通常意味着有代码尝试在WordPress初始化完成之前加载文本域(textdomain),而WordPress期望在特定的钩子(如&#39;init&#39;)之后加载。解决思路:1.确保redux-framework的文本域加载代码在正确的钩子上执行,通常是&#39;init&#39;钩子或之后。2.检查是否有插件或主题代码在过早的时机(比如在&#39;init&#39;之前)调用了加载文本域的函数。步骤:首先,我们需要定位到加载redux-framework翻译的代码。通常,在主题或插件中,我们会使用load_theme_textdomain()load_plugin_textdomain()来加载翻译。根据错误信息,问题可能出在redux-framework的翻译被加载得太早。因此,我们需要将加载翻译的代码移动到适当的时机。例如,在主题中,我们通常这样加载翻译:functionmytheme_load_theme_textdomain(){load_theme_textdomain(&#39;mytheme&#39;,get_template_directory().&#39;/languages&#39;);}add_action(&#39;after_setup_theme&#39;,&#39;mytheme_load_theme_textdomain&#39;);但是,对于redux-framework,它可能是一个插件或集成在主题中的框架。如果是插件,应该使用load_plugin_textdomain,并且应该挂在&#39;plugins_loaded&#39;钩子上。然而,如果错误提示明确提到`_load_textdomain_just_in_time`,这通常是WordPress核心在尝试按需加载翻译,但发现时机不对。这可能是由于在WordPress加载翻译系统的过程中,有代码过早地调用了翻译函数(如__()或_e()),导致WordPress尝试加载翻译文件但此时还没有准备好。因此,解决方案是确保所有使用翻译字符串的代码都在文本域加载之后执行,并且文本域加载的代码要在正确的钩子上。具体到redux-framework,如果你在主题中集成了redux,那么你可能需要检查redux初始化代码的时机。常见的修复方法:1.将加载文本域的代码挂到&#39;init&#39;钩子上(如果是在插件中,也可以使用&#39;plugins_loaded&#39;,但&#39;init&#39;更安全,因为此时所有插件都已经加载)。2.如果问题是由第三方插件(redux-framework)引起的,你可能需要联系插件作者,或者自己修改插件的代码(如果允许的话)。但是,由于我们可能无法直接修改redux-framework插件的代码,我们可以尝试在主题中调整加载顺序。另一种方法是:如果错误是来自redux-framework,我们可以尝试在主题的functions.php中移除原有的redux加载翻译的代码(如果有的话),然后自己重新挂载到正确的钩子上。例如,如果redux-framework在主题中是这样加载翻译的:load_theme_textdomain(&#39;redux-framework&#39;,get_template_directory().&#39;/languages&#39;);那么我们可以将它包裹在一个函数中,并挂到&#39;init&#39;钩子上:functionfix_redux_textdomain(){load_theme_textdomain(&#39;redux-framework&#39;,get_template_directory().&#39;/languages&#39;);}add_action(&#39;init&#39;,&#39;fix_redux_textdomain&#39;,10);注意:使用load_theme_textdomain()时,通常是在主题中,并且挂在&#39;after_setup_theme&#39;钩子上,但这里因为redux-framework加载过早,所以我们尝试改到&#39;init&#39;钩子上。如果redux-framework是作为插件,那么我们应该使用load_plugin_textdomain,并且挂在&#39;plugins_loaded&#39;上。但如果是集成在主题中,则使用load_theme_textdomain。另外,引用[1]中提到了一个关于函数被弃用的通知,但我们当前的问题不是弃用,而是调用时机不正确。引用[3]提到了链接错误,可能和翻译库有关,但我们这里的问题不是链接错误,所以暂时不考虑。因此,针对你的问题,建议的解决步骤是:1.在主题的functions.php中找到加载redux-framework翻译的代码(可能是load_theme_textdomain(&#39;redux-framework&#39;,...))。2.如果这段代码直接写在functions.php中(没有放在任何钩子函数里),那么这就是问题所在,因为它执行得太早。3.将这段代码移动到一个函数中,并挂载到&#39;init&#39;钩子上(或者如果主题支持,也可以挂在&#39;after_setup_theme&#39;上,但&#39;after_setup_theme&#39;在&#39;init&#39;之前,所以如果&#39;after_setup_theme&#39;仍然太早,就使用&#39;init&#39;)。示例代码:修改前(错误的)://直接写在functions.phpload_theme_textdomain(&#39;redux-framework&#39;,get_template_directory().&#39;/path/to/languages&#39;);修改后:functioncustom_load_redux_textdomain(){load_theme_textdomain(&#39;redux-framework&#39;,get_template_directory().&#39;/path/to/languages&#39;);}add_action(&#39;init&#39;,&#39;custom_load_redux_textdomain&#39;);注意:如果redux-framework的翻译文件路径不同,请根据实际情况调整。4.如果问题仍然存在,可能是其他代码在init之前调用了翻译函数,需要检查并确保所有使用翻译的代码都在文本域加载之后执行。5.如果以上方法无效,可以尝试增加优先级,比如将优先级设为1(数字越小优先级越高,但通常默认是10),确保尽早加载翻译。但这里我们是要延迟加载,所以用默认优先级即可。6.如果问题是由redux-framework插件本身引起的,你可能需要更新插件或寻找插件的更新版本,因为可能插件作者已经修复了这个问题。最后,清除缓存并重新测试。如果问题解决了,那么错误提示就会消失。注意:在修改代码前备份文件。相关问题:1.如何调试WordPress中的钩子执行顺序?2.如何为WordPress主题或插件添加多语言支持?3.WordPress翻译系统的工作原理是什么?</think>### 解决 WordPress `_load_textdomain_just_in_time` 错误调用问题 此错误表明 Redux Framework 在过早的时机加载翻译文件(在 `init` 动作前),导致 WordPress 的按需翻译机制被错误触发。以下是逐步解决方案: #### 修复步骤 1. **定位翻译加载代码** 在主题的 `functions.php` 或 Redux 配置文件中,找到类似以下代码: ```php load_theme_textdomain(&#39;redux-framework&#39;, get_template_directory() . &#39;/languages&#39;); // 或 load_plugin_textdomain(&#39;redux-framework&#39;, false, dirname(plugin_basename(__FILE__)) . &#39;/languages&#39;); ``` 2. **延迟翻译加载时机** 将翻译加载代码包裹到 `init` 钩子中(优先级建议 `10`): ```php function fix_redux_translation() { load_theme_textdomain(&#39;redux-framework&#39;, get_template_directory() . &#39;/languages&#39;); // 如果是插件: // load_plugin_textdomain(&#39;redux-framework&#39;, false, dirname(plugin_basename(__FILE__)) . &#39;/languages&#39;); } add_action(&#39;init&#39;, &#39;fix_redux_translation&#39;, 10); // ✅ 确保在 init 后执行 ``` 3. **检查 Redux 初始化** 确保 Redux 实例化代码同样延迟到 `init` 之后: ```php function init_redux_framework() { // Redux 配置实例化代码 } add_action(&#39;init&#39;, &#39;init_redux_framework&#39;, 10); // ⚠️ 必须晚于翻译加载 ``` 4. **验证翻译文件路径** 检查语言文件是否位于正确路径: - 主题:`/wp-content/themes/your-theme/languages/redux-framework-zh_CN.mo` - 插件:`/wp-content/plugins/redux-framework/languages/redux-framework-zh_CN.mo` 5. **清除缓存** 删除以下缓存文件(若存在): - `/wp-content/languages/themes/redux-framework-zh_CN.mo` - `/wp-content/languages/plugins/redux-framework-zh_CN.mo` #### 原理说明 - WordPress 的按需翻译机制 (`_load_textdomain_just_in_time`) 要求文本域在首次翻译调用前注册[^2]。 - Redux 在 `init` 前加载翻译会导致 WordPress 误判翻译未注册,从而触发错误。 - `init` 钩子是 WordPress 完成核心加载的标准时机,适合处理扩展功能[^1]。 #### 验证修复 在 `wp-config.php` 中开启调试模式: ```php define(&#39;WP_DEBUG&#39;, true); define(&#39;WP_DEBUG_LOG&#39;, true); // 日志输出到 /wp-content/debug.log ``` 修复后,`debug.log` 中不应再出现以下错误: > `_load_textdomain_just_in_time was called incorrectly...` --- ### 相关问题 1. 如何为 WordPress 插件创建多语言支持? 2. 除了 `init` 钩子,WordPress 还有哪些关键动作钩子适合加载资源? 3. 如何调试 WordPress 的翻译文件加载路径? 4. Redux Framework 常见兼容性问题有哪些? [^1]: WordPress 钩子执行顺序文档 [^2]: WordPress 翻译加载机制官方指南 [^3]: Redux Framework 最佳实践文档
[root@yfw ~]# cd /www/wwwroot/yfw_szrengjing_com [root@yfw yfw_szrengjing_com]# ls -la total 276 drwxr-xr-x 5 www www 4096 Nov 13 17:55 . drwxr-xr-x 12 www www 4096 Nov 13 13:43 .. -rwxr-xr-x 1 www www 138 Nov 13 13:43 404.html -rwxr-xr-x 1 www www 341 Nov 13 13:43 auto_install.json -rwxr-xr-x 1 www www 10760 Nov 13 17:04 deploy-im.sh -rwxr-xr-x 1 www www 1 Nov 13 13:43 .htaccess -rwxr-xr-x 1 www www 405 Nov 13 13:43 index.php -rwxr-xr-x 1 www www 19903 Nov 13 14:46 license.txt -rwxr-xr-x 1 www www 7425 Nov 13 14:46 readme.html -rw-r--r-- 1 www www 2039 Nov 13 17:55 websocket-test.html -rwxr-xr-x 1 www www 7387 Nov 13 13:43 wp-activate.php drwxr-xr-- 9 www www 4096 Aug 21 2024 wp-admin -rwxr-xr-x 1 www www 351 Nov 13 13:43 wp-blog-header.php -rwxr-xr-x 1 www www 2323 Nov 13 13:43 wp-comments-post.php -rw-rw-rw- 1 www www 3330 Nov 13 13:44 wp-config.php -rwxr-xr-x 1 www www 3336 Nov 13 14:46 wp-config-sample.php drwxr-xr-x 7 www www 4096 Nov 13 16:33 wp-content -rwxr-xr-x 1 www www 5617 Nov 13 14:46 wp-cron.php drwx------ 30 www www 16384 Nov 13 14:46 wp-includes -rwxr-xr-x 1 www www 2502 Nov 13 13:43 wp-links-opml.php -rwxr-xr-x 1 www www 3937 Nov 13 13:43 wp-load.php -rwxr-xr-x 1 www www 51414 Nov 13 14:46 wp-login.php -rwxr-xr-x 1 www www 8727 Nov 13 14:46 wp-mail.php -rwxr-xr-x 1 www www 30081 Nov 13 14:46 wp-settings.php -rwxr-xr-x 1 www www 34516 Nov 13 14:46 wp-signup.php -rwxr-xr-x 1 www www 5102 Nov 13 14:46 wp-trackback.php -rwxr-xr-x 1 www www 3205 Nov 13 14:46 xmlrpc.php [root@yfw yfw_szrengjing_com]# 看下 是哪个地方
11-14
你已经进入了网站根目录: ``` /www/wwwroot/yfw_szrengjing_com ``` 并执行了 `ls -la`,我们来分析当前文件结构。 --- ## ✅ 当前目录内容说明 | 文件/目录 | 用途 | |----------|------| | `index.php`, `wp-config.php`, `wp-content/`, `wp-admin/`, `wp-includes/` | 明确表明这是一个 **WordPress 站点** | | `websocket-test.html` | 你自己创建的 WebSocket 测试页面 ✅ 已存在 | | `deploy-im.sh` | 部署脚本(可能是你用来启动 Workerman 的) | | 其他 `.html`, `.php` 文件 | WordPress 标准文件 | --- ## 🔍 你现在最关心的问题是: > “看下是哪个地方” —— 我理解你想确认: ### ❓ 1. `websocket-test.html` 是否已正确部署? ✅ **是的!** ```bash -rw-r--r-- 1 www www 2039 Nov 13 17:55 websocket-test.html ``` - 权限:644(可读) - 所属用户:www(Web 服务运行者) - 修改时间:17:55(最新) 👉 表示这个文件已经在 Web 可访问路径中。 你可以通过浏览器访问: ``` https://yfw.szrengjing.com/websocket-test.html ``` ✔️ 能打开页面,说明静态资源没问题。 --- ### ❓ 2. 为什么页面卡在“状态:正在连接...”? 我们之前已经诊断过: 🔴 **HTTPS 页面不能使用 `ws://` 协议连接 WebSocket 服务** 你现在用的是 HTTPS,但 JS 中很可能还是: ```js const WS_URL = "ws://yfw.szrengjing.com:2121"; ``` 这会触发浏览器的 **混合内容拦截(Mixed Content)**,导致连接失败! --- ## 🛠️ 必须检查和修改的内容 ### ✅ 第一步:查看 `websocket-test.html` 内容 运行命令查看当前 HTML 内容: ```bash cat /www/wwwroot/yfw_szrengjing_com/websocket-test.html ``` 你应该看到类似如下代码片段: ```js const WS_URL = "ws://your-domain.com:2121"; ``` 或者 ```js const WS_URL = "ws://yfw.szrengjing.com:2121"; ``` ⚠️ 这就是问题所在! --- ## ✅ 解决方案:立即修改为 WSS 或走 Nginx 代理 ### 方案一:【推荐】使用 Nginx 反向代理 + WSS(统一域名、无需开新端口) #### ✅ 好处: - 不暴露额外端口(如 2121- 使用现有 HTTPS 证书 - 外部访问 `wss://yfw.szrengjing.com/im-ws` 即可 --- ### 🔧 步骤 1:确保你的 Workerman 在监听本地 `2121` 端口 运行: ```bash ss -tulnp | grep :2121 ``` 正确输出应包含: ``` tcp LISTEN 0 1024 *:2121 users:(("php",pid=xxx,fd=6)) ``` 如果你的服务没启动,请先启动它: ```bash # 示例:假设你的启动脚本在这里 php /www/wwwroot/yfw_szrengjing_com/workerman/start.php start -d ``` > 如果没有这个目录,请先创建 Workerman 服务脚本(后续我会教你写) --- ### 🔧 步骤 2:配置 Nginx 反向代理 `/im-ws` 到 `ws://127.0.0.1:2121` 进入宝塔面板 → 网站 → 找到 `yfw.szrengjing.com` → 设置 → 配置文件 在 `server { ... }` 块中添加以下 location: ```nginx location /im-ws { proxy_pass http://127.0.0.1:2121; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } ``` 📌 保存后点击「重启 Nginx」。 --- ### 🔧 步骤 3:修改前端 JS 使用 `wss://` + `/im-ws` 路径 编辑文件: ```bash nano /www/wwwroot/yfw_szrengjing_com/websocket-test.html ``` 将原来的: ```js const WS_URL = "ws://yfw.szrengjing.com:2121"; ``` 改为: ```js const WS_URL = "wss://" + window.location.host + "/im-ws"; ``` ✅ 这样无论你是访问 `https://yfw.szrengjing.com` 还是其他子域名,都能自动匹配。 --- ### 🔧 步骤 4:刷新页面测试 打开: ``` https://yfw.szrengjing.com/websocket-test.html ``` 你应该看到: ``` 状态:正在连接... ✅ 连接成功! 📩 收到消息: {"type":"welcome","msg":"欢迎进入IM系统"} ``` 如果没有,请按 F12 查看 Console 和 Network → WS 请求是否成功建立。 --- ## 🧪 如何验证 Workerman 是否正常工作? ### 查看进程: ```bash ps aux | grep worker ``` 应该看到类似: ``` www 1234 0.0 0.5 200789 54321 ? S 17:30 0:00 php /www/.../start.php ``` ### 查看日志(建议你在服务中加日志): ```php echo "新连接\n"; file_put_contents(&#39;/tmp/im.log&#39;, "新连接\n", FILE_APPEND); ``` 或使用 Workerman 自带的日志: ```php Worker::log("用户 {$connection->user_id} 上线"); ``` 查看日志: ```bash tail -f /tmp/workerman.log ``` --- ## ✅ 总结你现在要做的事(命令汇总) ```bash # 1. 编辑测试页面 nano /www/wwwroot/yfw_szrengjing_com/websocket-test.html ``` 找到这一行: ```js const WS_URL = "ws://..."; ``` 替换为: ```js const WS_URL = "wss://" + window.location.host + "/im-ws"; ``` 保存退出(Ctrl+O → Enter → Ctrl+X) ```bash # 2. 确认 Workerman 正在运行 ps aux | grep worker # 如果没有,启动它(根据实际路径调整) php /www/wwwroot/yfw_szrengjing_com/workerman/start.php start -d ``` ```bash # 3. 检查端口监听 ss -tulnp | grep :2121 ``` ```bash # 4. 宝塔配置 Nginx 反向代理(必须加上 /im-ws) ``` 然后刷新页面即可! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值