分类: PHP

  • Elementor 教程:WordPress 外贸建站利器

    搭建外贸网站对于不懂代码的人来说曾经是件难事,但 Elementor 的出现改变了这一切。这款可视化页面编辑器插件,让建站变得像搭积木一样简单,即使是零基础也能轻松上手。

    Elementor 是什么?

    Elementor 是一款 WordPress 可视化页面编辑器插件,它最大的特点是拖放式操作,无需代码知识,就能设计出精美的网站页面。

    Elementor 版本选择:

    • 免费版: 包含基础模块,适合大多数用户。
    • Pro 版: 提供更多高级功能,如表单、幻灯片、模板等。
    • 主机版: 整合了主机服务,但限制较多。
    • 破解版: 存在安全风险,不建议使用。

    Elementor 安装步骤:

    1. 登录 WordPress 后台,搜索并安装 Elementor 插件。
    2. 创建账号(可选)。
    3. 安装主题(可选,推荐 Astra 主题)。
    4. 添加网站名称和 Logo(可选)。
    5. 了解 Elementor 基本操作。

    Elementor 创建页面:

    1. 新建页面,点击“使用 Elementor 编辑”。
    2. 选择页面结构,拖放模块到区块中。
    3. 修改模块内容、布局和样式。
    4. 预览并发布页面。

    Elementor Pro 高级功能:

    • 模板库: 提供大量精美模板,一键导入,快速建站。
    • 主题生成器: 自定义页眉、页脚等网站元素。

    Elementor 自定义设计:

    • 更改布局和结构
    • 修改文字、图片和颜色
    • 删除模块
    • 响应式设计
    • 站点设置

    Elementor 扩展:

    • 主题扩展: 推荐 Astra 主题,提供完整网站模板。
    • 插件扩展: Essential Addons 和 Astra UAE 等插件提供更多模块和功能。

    Elementor 常见问题:

    • Elementor 免费吗? 有免费版和付费 Pro 版。
    • Elementor 速度快吗? 速度很快,但需要搭配好用的主机。
    • Elementor 好用吗? 操作直观,适合新手和中小企业。
    • Elementor 适合谷歌优化吗? 代码简洁,对 SEO 友好。

    总结:

    Elementor 是 WordPress 外贸建站的最佳选择之一,它简单易用,功能强大,能够帮助你轻松搭建出精美的外贸网站。

  • 坚持使用 PHP 的感悟:老骥伏枥,志在千里

    在移动互联网、前后端分离、新语言层出不穷的今天,PHP 依然坚挺,甚至在 TIOBE 排行榜前十的位置徘徊。作为一名坚持使用 PHP 的开发者,我有一些感悟想与大家分享。

    PHP 的生命力:

    • 厚实的底子: PHP 积累了大量的开发者和应用,生态系统庞大,这是它能够经受住各种挑战的重要原因。
    • 简单易用: PHP 入门门槛低,易于学习和使用,尤其适合快速搭建 Web 应用。
    • 资源占用少: 在服务器资源有限的情况下,PHP 比其他语言更省资源,适合部署访问量不大的网站。
    • 丰富的开源资源: 基于 PHP 的开源建站系统和框架非常丰富,满足各种需求。

    PHP 的不足:

    • 规范性: PHP 的函数命名等方面缺乏统一标准,例如 str_replace 和 strlen 这种不一致的命名。
    • 使用愉悦性: PHP 的语法有些繁琐,例如变量前的 $ 符号,以及 .php 文件开头的 <?php 标记。

    对 PHP 的期望:

    • 提升规范性: 希望 PHP 能在语言规范方面进行改进,提高代码的可读性和可维护性。
    • 提高使用愉悦性: 希望 PHP 能简化语法,例如去掉变量前的 $ 符号,以及省略 .php 文件开头的 <?php 标记。

    PHP 的未来:

    我相信 PHP 依然有着广阔的应用前景,尤其是在中小企业和个人开发者中。随着 PHP 7 及其后续版本的推出,PHP 的性能和安全性得到了显著提升,也更加现代化。

    总结:

    PHP 是一门充满活力的语言,它简单易用,资源占用少,拥有丰富的开源资源。虽然存在一些不足,但 PHP 依然是 Web 开发的重要选择之一。我相信,在开发者们的共同努力下,PHP 会越来越好,继续在 Web 开发领域发挥重要作用。

  • /**
    	 * Parses the request to find the correct WordPress query.
    	 *
    	 * Sets up the query variables based on the request. There are also many
    	 * filters and actions that can be used to further manipulate the result.
    	 *
    	 * @since 2.0.0
    	 * @since 6.0.0 A return value was added.
    	 *
    	 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
    	 *
    	 * @param array|string $extra_query_vars Set the extra query variables.
    	 * @return bool Whether the request was parsed.
    	 */
    	public function parse_request( $extra_query_vars = '' ) {
    		global $wp_rewrite;
    
    		/**
    		 * Filters whether to parse the request.
    		 *
    		 * @since 3.5.0
    		 *
    		 * @param bool         $bool             Whether or not to parse the request. Default true.
    		 * @param WP           $wp               Current WordPress environment instance.
    		 * @param array|string $extra_query_vars Extra passed query variables.
    		 */
    		if ( ! apply_filters( 'do_parse_request', true, $this, $extra_query_vars ) ) {
    			return false;
    		}
    
    		$this->query_vars     = array();
    		$post_type_query_vars = array();
    
    		if ( is_array( $extra_query_vars ) ) {
    			$this->extra_query_vars = & $extra_query_vars;
    		} elseif ( ! empty( $extra_query_vars ) ) {
    			parse_str( $extra_query_vars, $this->extra_query_vars );
    		}
    		// Process PATH_INFO, REQUEST_URI, and 404 for permalinks.
    
    		// Fetch the rewrite rules.
    		$rewrite = $wp_rewrite->wp_rewrite_rules();
    
    		if ( ! empty( $rewrite ) ) {
    			// If we match a rewrite rule, this will be cleared.
    			$error               = '404';
    			$this->did_permalink = true;
    
    			$pathinfo         = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : '';
    			list( $pathinfo ) = explode( '?', $pathinfo );
    			$pathinfo         = str_replace( '%', '%25', $pathinfo );
    
    			list( $req_uri ) = explode( '?', $_SERVER['REQUEST_URI'] );
    			$self            = $_SERVER['PHP_SELF'];
    
    			$home_path       = parse_url( home_url(), PHP_URL_PATH );
    			$home_path_regex = '';
    			if ( is_string( $home_path ) && '' !== $home_path ) {
    				$home_path       = trim( $home_path, '/' );
    				$home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) );
    			}
    
    			/*
    			 * Trim path info from the end and the leading home path from the front.
    			 * For path info requests, this leaves us with the requesting filename, if any.
    			 * For 404 requests, this leaves us with the requested permalink.
    			 */
    			$req_uri  = str_replace( $pathinfo, '', $req_uri );
    			$req_uri  = trim( $req_uri, '/' );
    			$pathinfo = trim( $pathinfo, '/' );
    			$self     = trim( $self, '/' );
    
    			if ( ! empty( $home_path_regex ) ) {
    				$req_uri  = preg_replace( $home_path_regex, '', $req_uri );
    				$req_uri  = trim( $req_uri, '/' );
    				$pathinfo = preg_replace( $home_path_regex, '', $pathinfo );
    				$pathinfo = trim( $pathinfo, '/' );
    				$self     = preg_replace( $home_path_regex, '', $self );
    				$self     = trim( $self, '/' );
    			}
    
    			// The requested permalink is in $pathinfo for path info requests and $req_uri for other requests.
    			if ( ! empty( $pathinfo ) && ! preg_match( '|^.*' . $wp_rewrite->index . '$|', $pathinfo ) ) {
    				$requested_path = $pathinfo;
    			} else {
    				// If the request uri is the index, blank it out so that we don't try to match it against a rule.
    				if ( $req_uri === $wp_rewrite->index ) {
    					$req_uri = '';
    				}
    
    				$requested_path = $req_uri;
    			}
    
    			$requested_file = $req_uri;
    
    			$this->request = $requested_path;
    
    			// Look for matches.
    			$request_match = $requested_path;
    			if ( empty( $request_match ) ) {
    				// An empty request could only match against ^$ regex.
    				if ( isset( $rewrite['$'] ) ) {
    					$this->matched_rule = '$';
    					$query              = $rewrite['$'];
    					$matches            = array( '' );
    				}
    			} else {
    				foreach ( (array) $rewrite as $match => $query ) {
    					// If the requested file is the anchor of the match, prepend it to the path info.
    					if ( ! empty( $requested_file )
    						&& str_starts_with( $match, $requested_file )
    						&& $requested_file !== $requested_path
    					) {
    						$request_match = $requested_file . '/' . $requested_path;
    					}
    
    					if ( preg_match( "#^$match#", $request_match, $matches )
    						|| preg_match( "#^$match#", urldecode( $request_match ), $matches )
    					) {
    
    						if ( $wp_rewrite->use_verbose_page_rules
    							&& preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch )
    						) {
    							// This is a verbose page match, let's check to be sure about it.
    							$page = get_page_by_path( $matches[ $varmatch[1] ] );
    
    							if ( ! $page ) {
    								continue;
    							}
    
    							$post_status_obj = get_post_status_object( $page->post_status );
    
    							if ( ! $post_status_obj->public && ! $post_status_obj->protected
    								&& ! $post_status_obj->private && $post_status_obj->exclude_from_search
    							) {
    								continue;
    							}
    						}
    
    						// Got a match.
    						$this->matched_rule = $match;
    						break;
    					}
    				}
    			}
    
    			if ( ! empty( $this->matched_rule ) ) {
    				// Trim the query of everything up to the '?'.
    				$query = preg_replace( '!^.+\?!', '', $query );
    
    				// Substitute the substring matches into the query.
    				$query = addslashes( WP_MatchesMapRegex::apply( $query, $matches ) );
    
    				$this->matched_query = $query;
    
    				// Parse the query.
    				parse_str( $query, $perma_query_vars );
    
    				// If we're processing a 404 request, clear the error var since we found something.
    				if ( '404' === $error ) {
    					unset( $error, $_GET['error'] );
    				}
    			}
    
    			// If req_uri is empty or if it is a request for ourself, unset error.
    			if ( empty( $requested_path ) || $requested_file === $self
    				|| str_contains( $_SERVER['PHP_SELF'], 'wp-admin/' )
    			) {
    				unset( $error, $_GET['error'] );
    
    				if ( isset( $perma_query_vars ) && str_contains( $_SERVER['PHP_SELF'], 'wp-admin/' ) ) {
    					unset( $perma_query_vars );
    				}
    
    				$this->did_permalink = false;
    			}
    		}
    
    		/**
    		 * Filters the query variables allowed before processing.
    		 *
    		 * Allows (publicly allowed) query vars to be added, removed, or changed prior
    		 * to executing the query. Needed to allow custom rewrite rules using your own arguments
    		 * to work, or any other custom query variables you want to be publicly available.
    		 *
    		 * @since 1.5.0
    		 *
    		 * @param string[] $public_query_vars The array of allowed query variable names.
    		 */
    		$this->public_query_vars = apply_filters( 'query_vars', $this->public_query_vars );
    
    		foreach ( get_post_types( array(), 'objects' ) as $post_type => $t ) {
    			if ( is_post_type_viewable( $t ) && $t->query_var ) {
    				$post_type_query_vars[ $t->query_var ] = $post_type;
    			}
    		}
    
    		foreach ( $this->public_query_vars as $wpvar ) {
    			if ( isset( $this->extra_query_vars[ $wpvar ] ) ) {
    				$this->query_vars[ $wpvar ] = $this->extra_query_vars[ $wpvar ];
    			} elseif ( isset( $_GET[ $wpvar ] ) && isset( $_POST[ $wpvar ] )
    				&& $_GET[ $wpvar ] !== $_POST[ $wpvar ]
    			) {
    				wp_die(
    					__( 'A variable mismatch has been detected.' ),
    					__( 'Sorry, you are not allowed to view this item.' ),
    					400
    				);
    			} elseif ( isset( $_POST[ $wpvar ] ) ) {
    				$this->query_vars[ $wpvar ] = $_POST[ $wpvar ];
    			} elseif ( isset( $_GET[ $wpvar ] ) ) {
    				$this->query_vars[ $wpvar ] = $_GET[ $wpvar ];
    			} elseif ( isset( $perma_query_vars[ $wpvar ] ) ) {
    				$this->query_vars[ $wpvar ] = $perma_query_vars[ $wpvar ];
    			}
    
    			if ( ! empty( $this->query_vars[ $wpvar ] ) ) {
    				if ( ! is_array( $this->query_vars[ $wpvar ] ) ) {
    					$this->query_vars[ $wpvar ] = (string) $this->query_vars[ $wpvar ];
    				} else {
    					foreach ( $this->query_vars[ $wpvar ] as $vkey => $v ) {
    						if ( is_scalar( $v ) ) {
    							$this->query_vars[ $wpvar ][ $vkey ] = (string) $v;
    						}
    					}
    				}
    
    				if ( isset( $post_type_query_vars[ $wpvar ] ) ) {
    					$this->query_vars['post_type'] = $post_type_query_vars[ $wpvar ];
    					$this->query_vars['name']      = $this->query_vars[ $wpvar ];
    				}
    			}
    		}
    
    		// Convert urldecoded spaces back into '+'.
    		foreach ( get_taxonomies( array(), 'objects' ) as $taxonomy => $t ) {
    			if ( $t->query_var && isset( $this->query_vars[ $t->query_var ] ) ) {
    				$this->query_vars[ $t->query_var ] = str_replace( ' ', '+', $this->query_vars[ $t->query_var ] );
    			}
    		}
    
    		// Don't allow non-publicly queryable taxonomies to be queried from the front end.
    		if ( ! is_admin() ) {
    			foreach ( get_taxonomies( array( 'publicly_queryable' => false ), 'objects' ) as $taxonomy => $t ) {
    				/*
    				 * Disallow when set to the 'taxonomy' query var.
    				 * Non-publicly queryable taxonomies cannot register custom query vars. See register_taxonomy().
    				 */
    				if ( isset( $this->query_vars['taxonomy'] ) && $taxonomy === $this->query_vars['taxonomy'] ) {
    					unset( $this->query_vars['taxonomy'], $this->query_vars['term'] );
    				}
    			}
    		}
    
    		// Limit publicly queried post_types to those that are 'publicly_queryable'.
    		if ( isset( $this->query_vars['post_type'] ) ) {
    			$queryable_post_types = get_post_types( array( 'publicly_queryable' => true ) );
    
    			if ( ! is_array( $this->query_vars['post_type'] ) ) {
    				if ( ! in_array( $this->query_vars['post_type'], $queryable_post_types, true ) ) {
    					unset( $this->query_vars['post_type'] );
    				}
    			} else {
    				$this->query_vars['post_type'] = array_intersect( $this->query_vars['post_type'], $queryable_post_types );
    			}
    		}
    
    		// Resolve conflicts between posts with numeric slugs and date archive queries.
    		$this->query_vars = wp_resolve_numeric_slug_conflicts( $this->query_vars );
    
    		foreach ( (array) $this->private_query_vars as $var ) {
    			if ( isset( $this->extra_query_vars[ $var ] ) ) {
    				$this->query_vars[ $var ] = $this->extra_query_vars[ $var ];
    			}
    		}
    
    		if ( isset( $error ) ) {
    			$this->query_vars['error'] = $error;
    		}
    
    		/**
    		 * Filters the array of parsed query variables.
    		 *
    		 * @since 2.1.0
    		 *
    		 * @param array $query_vars The array of requested query variables.
    		 */
    		$this->query_vars = apply_filters( 'request', $this->query_vars );
    
    		/**
    		 * Fires once all query variables for the current request have been parsed.
    		 *
    		 * @since 2.1.0
    		 *
    		 * @param WP $wp Current WordPress environment instance (passed by reference).
    		 */
    		do_action_ref_array( 'parse_request', array( &$this ) );
    
    		return true;
    	}
    

    上述代码是WordPress核心类WPparse_request方法的详细实现。这个方法负责解析传入的URL或请求,以确定应执行哪个WordPress查询。以下是对此方法的作用和工作方式的解释,分解为其关键组件:

    parse_request的目的

    parse_request方法旨在根据传入请求设置查询变量。它确定请求应如何处理——无论是渲染文章、页面、类别列表还是处理404错误。

    关键步骤和操作

    1. 过滤提前退出:方法首先检查是否应继续解析请求,使用do_parse_request过滤器。插件可以使用此过滤器来跳过解析过程。
    2. 初始化
    • 清除任何之前的查询变量。
    • 初始化本地变量以处理URL的不同组件。
    1. 处理额外的查询变量:如果提供了任何额外的查询变量,它们将被整合到查询处理中。
    2. 应用重写规则
    • $wp_rewrite检索WordPress重写规则。
    • 处理请求URI和路径信息,去除家庭URL路径,留下将与重写规则匹配的相对路径或查询字符串。
    1. 与重写规则匹配
    • 迭代重写规则以找到与处理后的请求路径的匹配项。
    • 如果找到匹配,相应的WordPress查询变量将根据重写规则设置。
    1. 文章类型和分类法处理
    • 将与文章类型或分类法相关的任何查询变量映射到其相应的查询。
    • 确保只能查询公开可查询的文章类型和分类法。
    1. 安全和清洁
    • 处理GET和POST请求之间潜在的变量冲突。
    • 过滤查询变量以确保最终查询中只包含允许的键。
    1. 最终查询变量准备
    • 应用过滤器以修改或验证查询变量列表。
    • 解决URL中的数字slug冲突。
    1. 动作钩子
    • 执行操作,允许插件在解析查询变量后执行操作。

    结论

    parse_request函数是WordPress解释和响应URL的能力的核心部分。它使用重写规则将URL映射到查询变量,处理来自GET和POST请求的传入变量,并确保只执行允许的查询。这个方法对于确保WordPress可以为不同的URL提供正确的内容至关重要,无论这些URL指向文章、页面、存档还是自定义文章类型和分类法。

    开发中的使用

    开发人员可以使用提供的钩子(do_parse_requestquery_varsrequestparse_request)来扩展或修改这种行为,以定制WordPress对不同请求的响应,这对于需要专门路由的自定义插件或主题特别有用。

  • 【WordPress】function wp_validate_auth_cookie( $cookie = ”, $scheme = ” )

    function wp_validate_auth_cookie( $cookie = '', $scheme = '' ) {
    		$cookie_elements = wp_parse_auth_cookie( $cookie, $scheme );
    		if ( ! $cookie_elements ) {
    			/**
    			 * Fires if an authentication cookie is malformed.
    			 *
    			 * @since 2.7.0
    			 *
    			 * @param string $cookie Malformed auth cookie.
    			 * @param string $scheme Authentication scheme. Values include 'auth', 'secure_auth',
    			 *                       or 'logged_in'.
    			 */
    			do_action( 'auth_cookie_malformed', $cookie, $scheme );
    			return false;
    		}
    
    		$scheme     = $cookie_elements['scheme'];
    		$username   = $cookie_elements['username'];
    		$hmac       = $cookie_elements['hmac'];
    		$token      = $cookie_elements['token'];
    		$expired    = $cookie_elements['expiration'];
    		$expiration = $cookie_elements['expiration'];
    
    		// Allow a grace period for POST and Ajax requests.
    		if ( wp_doing_ajax() || 'POST' === $_SERVER['REQUEST_METHOD'] ) {
    			$expired += HOUR_IN_SECONDS;
    		}
    
    		// Quick check to see if an honest cookie has expired.
    		if ( $expired < time() ) {
    			/**
    			 * Fires once an authentication cookie has expired.
    			 *
    			 * @since 2.7.0
    			 *
    			 * @param string[] $cookie_elements {
    			 *     Authentication cookie components. None of the components should be assumed
    			 *     to be valid as they come directly from a client-provided cookie value.
    			 *
    			 *     @type string $username   User's username.
    			 *     @type string $expiration The time the cookie expires as a UNIX timestamp.
    			 *     @type string $token      User's session token used.
    			 *     @type string $hmac       The security hash for the cookie.
    			 *     @type string $scheme     The cookie scheme to use.
    			 * }
    			 */
    			do_action( 'auth_cookie_expired', $cookie_elements );
    			return false;
    		}
    
    		$user = get_user_by( 'login', $username );
    		if ( ! $user ) {
    			/**
    			 * Fires if a bad username is entered in the user authentication process.
    			 *
    			 * @since 2.7.0
    			 *
    			 * @param string[] $cookie_elements {
    			 *     Authentication cookie components. None of the components should be assumed
    			 *     to be valid as they come directly from a client-provided cookie value.
    			 *
    			 *     @type string $username   User's username.
    			 *     @type string $expiration The time the cookie expires as a UNIX timestamp.
    			 *     @type string $token      User's session token used.
    			 *     @type string $hmac       The security hash for the cookie.
    			 *     @type string $scheme     The cookie scheme to use.
    			 * }
    			 */
    			do_action( 'auth_cookie_bad_username', $cookie_elements );
    			return false;
    		}
    
    		$pass_frag = substr( $user->user_pass, 8, 4 );
    
    		$key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
    
    		// If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
    		$algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
    		$hash = hash_hmac( $algo, $username . '|' . $expiration . '|' . $token, $key );
    
    		if ( ! hash_equals( $hash, $hmac ) ) {
    			/**
    			 * Fires if a bad authentication cookie hash is encountered.
    			 *
    			 * @since 2.7.0
    			 *
    			 * @param string[] $cookie_elements {
    			 *     Authentication cookie components. None of the components should be assumed
    			 *     to be valid as they come directly from a client-provided cookie value.
    			 *
    			 *     @type string $username   User's username.
    			 *     @type string $expiration The time the cookie expires as a UNIX timestamp.
    			 *     @type string $token      User's session token used.
    			 *     @type string $hmac       The security hash for the cookie.
    			 *     @type string $scheme     The cookie scheme to use.
    			 * }
    			 */
    			do_action( 'auth_cookie_bad_hash', $cookie_elements );
    			return false;
    		}
    
    		$manager = WP_Session_Tokens::get_instance( $user->ID );
    		if ( ! $manager->verify( $token ) ) {
    			/**
    			 * Fires if a bad session token is encountered.
    			 *
    			 * @since 4.0.0
    			 *
    			 * @param string[] $cookie_elements {
    			 *     Authentication cookie components. None of the components should be assumed
    			 *     to be valid as they come directly from a client-provided cookie value.
    			 *
    			 *     @type string $username   User's username.
    			 *     @type string $expiration The time the cookie expires as a UNIX timestamp.
    			 *     @type string $token      User's session token used.
    			 *     @type string $hmac       The security hash for the cookie.
    			 *     @type string $scheme     The cookie scheme to use.
    			 * }
    			 */
    			do_action( 'auth_cookie_bad_session_token', $cookie_elements );
    			return false;
    		}
    
    		// Ajax/POST grace period set above.
    		if ( $expiration < time() ) {
    			$GLOBALS['login_grace_period'] = 1;
    		}
    
    		/**
    		 * Fires once an authentication cookie has been validated.
    		 *
    		 * @since 2.7.0
    		 *
    		 * @param string[] $cookie_elements {
    		 *     Authentication cookie components.
    		 *
    		 *     @type string $username   User's username.
    		 *     @type string $expiration The time the cookie expires as a UNIX timestamp.
    		 *     @type string $token      User's session token used.
    		 *     @type string $hmac       The security hash for the cookie.
    		 *     @type string $scheme     The cookie scheme to use.
    		 * }
    		 * @param WP_User  $user            User object.
    		 */
    		do_action( 'auth_cookie_valid', $cookie_elements, $user );
    
    		return $user->ID;
    	}

    这个PHP函数 wp_validate_auth_cookie() 是WordPress的身份验证系统的一部分。它用于验证用户登录时每个请求发送的身份验证cookie。该函数有两个可选参数:$cookie$scheme

    函数首先使用 wp_parse_auth_cookie() 函数解析身份验证cookie。如果cookie格式错误或不存在,函数会触发 auth_cookie_malformed 动作并返回 false

    接下来,它从解析的cookie中提取各种元素,包括方案、用户名、HMAC(用于数据完整性的一种加密哈希)、令牌和过期时间。

    然后,函数检查请求是否为AJAX或POST请求。如果是,它会将cookie的过期时间延长一小时。这是一个宽限期,用于允许长时间运行的操作。

    接着,函数检查cookie是否已过期。如果已过期,它会触发 auth_cookie_expired 动作并返回 false

    接下来,它检索与cookie中的用户名关联的用户。如果不存在这样的用户,它会触发 auth_cookie_bad_username 动作并返回 false

    然后,函数通过哈希cookie和用户密码的各种元素来生成一个密钥。它使用这个密钥来生成用户名、过期时间和令牌的哈希。如果生成的哈希与cookie中的HMAC不匹配,它会触发 auth_cookie_bad_hash 动作并返回 false

    接下来,它使用 WP_Session_Tokens::get_instance() 方法验证会话令牌。如果令牌无效,它会触发 auth_cookie_bad_session_token 动作并返回 false

    如果此时cookie的过期时间已过(只有在请求是AJAX或POST请求并且已应用宽限期的情况下才可能发生),它会将全局 login_grace_period 变量设置为 1

    最后,如果所有检查都通过,函数会触发 auth_cookie_valid 动作并返回用户的ID,表示身份验证cookie有效。

  • 【WordPress】wp-load.php

    <?php
    /**
     * Bootstrap file for setting the ABSPATH constant
     * and loading the wp-config.php file. The wp-config.php
     * file will then load the wp-settings.php file, which
     * will then set up the WordPress environment.
     *
     * If the wp-config.php file is not found then an error
     * will be displayed asking the visitor to set up the
     * wp-config.php file.
     *
     * Will also search for wp-config.php in WordPress' parent
     * directory to allow the WordPress directory to remain
     * untouched.
     *
     * @package WordPress
     */
    
    /** Define ABSPATH as this file's directory */
    if ( ! defined( 'ABSPATH' ) ) {
    	define( 'ABSPATH', __DIR__ . '/' );
    }
    
    /*
     * The error_reporting() function can be disabled in php.ini. On systems where that is the case,
     * it's best to add a dummy function to the wp-config.php file, but as this call to the function
     * is run prior to wp-config.php loading, it is wrapped in a function_exists() check.
     */
    if ( function_exists( 'error_reporting' ) ) {
    	/*
    	 * Initialize error reporting to a known set of levels.
    	 *
    	 * This will be adapted in wp_debug_mode() located in wp-includes/load.php based on WP_DEBUG.
    	 * @see https://www.php.net/manual/en/errorfunc.constants.php List of known error levels.
    	 */
    	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 );
    }
    
    /*
     * If wp-config.php exists in the WordPress root, or if it exists in the root and wp-settings.php
     * doesn't, load wp-config.php. The secondary check for wp-settings.php has the added benefit
     * of avoiding cases where the current directory is a nested installation, e.g. / is WordPress(a)
     * and /blog/ is WordPress(b).
     *
     * If neither set of conditions is true, initiate loading the setup process.
     */
    if ( file_exists( ABSPATH . 'wp-config.php' ) ) {
    
    	/** The config file resides in ABSPATH */
    	require_once ABSPATH . 'wp-config.php';
    
    } elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {
    
    	/** The config file resides one level above ABSPATH but is not part of another installation */
    	require_once dirname( ABSPATH ) . '/wp-config.php';
    
    } else {
    
    	// A config file doesn't exist.
    
    	define( 'WPINC', 'wp-includes' );
    	require_once ABSPATH . WPINC . '/version.php';
    	require_once ABSPATH . WPINC . '/compat.php';
    	require_once ABSPATH . WPINC . '/load.php';
    
    	// Check for the required PHP version and for the MySQL extension or a database drop-in.
    	wp_check_php_mysql_versions();
    
    	// Standardize $_SERVER variables across setups.
    	wp_fix_server_vars();
    
    	define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
    	require_once ABSPATH . WPINC . '/functions.php';
    
    	$path = wp_guess_url() . '/wp-admin/setup-config.php';
    
    	// Redirect to setup-config.php.
    	if ( ! str_contains( $_SERVER['REQUEST_URI'], 'setup-config' ) ) {
    		header( 'Location: ' . $path );
    		exit;
    	}
    
    	wp_load_translations_early();
    
    	// Die with an error message.
    	$die = '<p>' . sprintf(
    		/* translators: %s: wp-config.php */
    		__( "There doesn't seem to be a %s file. It is needed before the installation can continue." ),
    		'<code>wp-config.php</code>'
    	) . '</p>';
    	$die .= '<p>' . sprintf(
    		/* translators: 1: Documentation URL, 2: wp-config.php */
    		__( 'Need more help? <a href="%1$s">Read the support article on %2$s</a>.' ),
    		__( 'https://wordpress.org/documentation/article/editing-wp-config-php/' ),
    		'<code>wp-config.php</code>'
    	) . '</p>';
    	$die .= '<p>' . sprintf(
    		/* translators: %s: wp-config.php */
    		__( "You can create a %s file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file." ),
    		'<code>wp-config.php</code>'
    	) . '</p>';
    	$die .= '<p><a href="' . $path . '" class="button button-large">' . __( 'Create a Configuration File' ) . '</a></p>';
    
    	wp_die( $die, __( 'WordPress &rsaquo; Error' ) );
    }
    

    这段PHP脚本是WordPress应用的一部分,它的主要目的是加载一些必要的文件,并进行一些基本的环境检查。

    首先,它加载了一些核心的WordPress文件,包括版本信息(version.php)、兼容性函数(compat.php)和加载函数(load.php)。

    然后,它调用wp_check_php_mysql_versions()函数来检查当前环境的PHP版本以及是否安装了MySQL扩展或者数据库插件。

    接着,它调用wp_fix_server_vars()函数来标准化$_SERVER变量,以确保在不同的环境下这些变量的行为是一致的。

    然后,它定义了WP_CONTENT_DIR常量,这个常量指向WordPress的内容目录,然后加载了一些基本的WordPress函数(functions.php)。

    接下来,它构造了一个指向setup-config.php的URL,并检查当前的请求URL是否包含setup-config,如果不包含,那么就会重定向到setup-config.php

    然后,它调用wp_load_translations_early()函数来加载早期的翻译。

    最后,如果wp-config.php文件不存在,它会显示一个错误信息,告诉用户需要wp-config.php文件才能继续安装,并提供了一个链接到编辑wp-config.php文件的支持文章,以及一个创建配置文件的按钮。如果用户点击这个按钮,就会被重定向到setup-config.php

    如果所有的检查都通过,那么WordPress的安装过程就可以开始了。

  • 【WordPress】wp-blog-header.php

    <?php
    /**
     * Loads the WordPress environment and template.
     *
     * @package WordPress
     */
    
    if ( ! isset( $wp_did_header ) ) {
    
    	$wp_did_header = true;
    
    	// Load the WordPress library.
    	require_once __DIR__ . '/wp-load.php';
    
    	// Set up the WordPress query.
    	wp();
    
    	// Load the theme template.
    	require_once ABSPATH . WPINC . '/template-loader.php';
    
    }
    
    

    这段 PHP 代码是 WordPress 应用的一部分,特别是 wp-blog-header.php 文件。这个文件负责加载 WordPress 环境和当前主题的模板。

    代码开始于一个条件语句,检查 $wp_did_header 变量是否已设置。这个变量作为一个标志,确保 WordPress 环境和模板只加载一次。如果 $wp_did_header 未设置,条件块内的代码将会运行。

    在条件块内,$wp_did_header 被设置为 true。这防止了如果在执行过程中再次需要 wp-blog-header.php,代码块会再次运行。

    接下来,require_once 语句包含了 wp-load.php 文件。这个文件是 WordPress 库的加载器。它设置了 WordPress 环境,包括加载配置文件、设置错误处理和加载活动插件。

    然后调用了 wp() 函数。这个函数负责设置 WordPress 查询,根据请求的 URL 确定要显示的内容。例如,如果 URL 对应一个特定的博客文章,查询将从数据库中检索该文章的内容。

    最后,require_once 语句包含了 template-loader.php 文件。这个文件确定应该使用活动主题的哪个模板文件来显示页面。例如,如果查询是针对单个博客文章,它将加载 single.php 模板。如果查询是针对页面,它将加载 page.php 模板。

    这段代码加载了 WordPress 环境,根据请求的 URL 设置了内容查询,并从活动主题中加载了适当的模板文件。

  • 【WordPress】define( ‘WP_USE_THEMES’, true );

    <?php
    /**
     * Front to the WordPress application. This file doesn't do anything, but loads
     * wp-blog-header.php which does and tells WordPress to load the theme.
     *
     * @package WordPress
     */
    
    /**
     * Tells WordPress to load the WordPress theme and output it.
     *
     * @var bool
     */
    define( 'WP_USE_THEMES', true );
    
    /** Loads the WordPress Environment and Template */
    require __DIR__ . '/wp-blog-header.php';

    这段 PHP 代码是 WordPress 应用的入口点。它通常位于 WordPress 安装根目录的 index.php 文件中。

    代码的第一部分是一个注释块,描述了文件的用途。它指出这个文件本身并不做什么,但它加载了 wp-blog-header.php,这个文件做了大量的工作,并指示 WordPress 加载主题。

    接下来,定义了一个名为 WP_USE_THEMES 的常量,并设置为 true。这个常量告诉 WordPress 加载活动主题。当设置为 true 时,WordPress 将加载主题的 index.php 文件。如果设置为 false,WordPress 将不加载主题,这在你希望以不同的方式处理请求的情况下可能很有用,例如 AJAX 请求或 API 端点。

    最后,require 语句包含了 wp-blog-header.php 文件。这个文件负责设置 WordPress 环境,包括加载 WordPress 核心、插件和主题。使用 __DIR__ 魔术常量来获取当前文件的目录,确保无论从哪里运行脚本,wp-blog-header.php 的路径都是正确的。

    总的来说,这段代码设置并加载了 WordPress 环境和活动主题,准备了生成 WordPress 页面所需的一切。

  • 【WordPress】defined( ‘ABSPATH’ ) || exit;

    这行 PHP 代码是 WordPress 开发中常用的安全措施。它检查你的代码中是否定义了一个名为 ABSPATH 的常量。如果没有,脚本将停止执行并 exit

    我们来详细解析一下:

    • defined('ABSPATH'):这是 PHP 中的一个函数,用于检查是否在你的代码中定义了一个名为 ABSPATH 的常量。在 WordPress 中,ABSPATH 是一个常量,它保存了 WordPress 目录的绝对路径。它在 WordPress 的核心文件之一 wp-config.php 中定义。
    • ||:这是一个逻辑 OR 运算符。在这里用来检查两个条件。如果第一个条件 (defined('ABSPATH')) 为假,那么它将执行第二个条件。
    • exit:这是 PHP 中的一个语言结构,用于输出一条消息并终止当前脚本。在这里没有任何参数,所以它只会终止脚本,不输出任何消息。

    所以,在 WordPress 的上下文中,这行代码的意思是 “如果 ABSPATH 常量没有定义(意味着 WordPress 环境没有正确初始化),那么停止执行脚本。” 这是一种防止有人直接访问 PHP 文件并可能利用它的方式。

人生梦想 - 关注前沿的计算机技术 acejoy.com