/**
	 * 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|stringextra_query_vars Set the extra query variables.
	 * @return bool Whether the request was parsed.
	 */
	public function parse_request( extra_query_vars = '' ) { 		globalwp_rewrite;

		/**
		 * Filters whether to parse the request.
		 *
		 * @since 3.5.0
		 *
		 * @param bool         bool             Whether or not to parse the request. Default true. 		 * @param WPwp               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 andreq_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]+)\]/',


友情链接:ACEJoy


 

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' ) aspost_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 aswpvar ) { 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' ) astaxonomy => 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 asvar ) { 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 arrayquery_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对不同请求的响应,这对于需要专门路由的自定义插件或主题特别有用。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注