关于重新调整WordPress 404处理程序用途的问题

时间:2021-01-14 作者:Yvan Gagnon

我一直在尝试为我正在开发的一个房地产网站重新调整WordPress的404处理程序/模板文件的用途。我知道,当请求一个不存在的URL时,404页面会被提供,并且它会返回404状态码(而不是200)。但我最近发现了一种方法来调整404模板文件,使其更具创造性。更具体地说,我首先解析请求的不存在的URL,然后使用返回值查询外部API,然后显示返回的数据。到目前为止,它的效果比我预期的要好得多,尽管我知道一个重要的问题,我希望我能解决。

In those situations where the 404 handler is served up, yet data is returned from querying the external API, .. how can I then -- and only then -- re-write the "404" header information so that it\'s a "200" status code? 我这样问是因为我不想要这些。”;“找不到页面”;条目乱扔我们的谷歌分析报告,破坏了网站的搜索引擎优化排名。

下面是一个不存在的URL示例,它会触发404处理程序的服务:

https://example.com/property/123-four-street/

我正在使用以下PHP代码段解析此URL:

$url = $_SERVER[\'REQUEST_URI\'];
$path_parts = explode(\'/\', $url);   
$address = $path_parts[2];  
$parsedaddress = str_replace("-", " ", $address);                   
echo $parsedaddress;    
“The”;parsedaddress“;然后使用值来查询外部API,然后我希望在逻辑方面发生的事情大致如下。。。

if (query returns valid MLS data)

then (force a "200" status code and display the MLS data)

else (retain the "404" status code and display the 404 error page)

我已经将此自定义函数添加到我的函数中。php文件,正在成功更改404处理程序的默认页面标题。。。所以我知道我可以参与其中。但是我应该如何调整它,以便它有条件地重写标题信息?

function theme_slug_filter_wp_title( $title_parts ) {
    if ( is_404() ) {               
        
        $url = $_SERVER[\'REQUEST_URI\'];
        $path_parts = explode(\'/\', $url);   
        $address = $path_parts[2];  
        $parsedaddress = str_replace("-", " ", $address);           
        
        $title_parts[\'title\'] = ucwords($parsedaddress) . \' | AAA Real Estate;
    }

    return $title_parts;
} 
add_filter( \'document_title_parts\', \'theme_slug_filter_wp_title\' );
如有任何帮助或建议,将不胜感激。

谢谢,-伊万

1 个回复
最合适的回答,由SO网友:KAGG Design 整理而成

以下是经过测试的代码,您可以将其用作mu插件:

<?php
/**
 * Filters whether to short-circuit default header status handling.
 *
 * Returning a non-false value from the filter will short-circuit the handling
 * and return early.
 *
 * @param bool     $preempt  Whether to short-circuit default header status handling. Default false.
 * @param WP_Query $wp_query WordPress Query object.
 *
 * @return bool
 * @since 4.5.0
 */
function pre_handle_404_filter( bool $preempt, WP_Query $wp_query ) {
    global $parsed_address, $api_results;

    $parsed_address = get_parsed_address();

    if ( ! $parsed_address ) {
        return $preempt;
    }

    // Make a request to  API, get status.
    $status      = true; // For debug purposes.
    $api_results = null;

    if ( $status ) {
        // Save results to $api_results.
        // Return true to avoid 404 processing by WP.
        return true;
    }

    return $preempt;
}

add_filter( \'pre_handle_404\', \'pre_handle_404_filter\', 10, 2 );

/**
 * Handle 404.
 */
function handle_404() {
    global $parsed_address, $api_results, $wp_query;

    if ( ! $parsed_address ) {
        return;
    }

    // Set 404 here to prevent bugs in get_header().
    $wp_query->set_404();

    get_header();
    echo \'API Results\'; // Output $api_results here.
    get_footer();
    exit();
}

add_action( \'template_redirect\', \'handle_404\', - PHP_INT_MAX );

/**
 * Get parsed address from the request URI.
 * Make sure we have an address in the URI, otherwise return an empty string.
 *
 * @return string
 */
function get_parsed_address() {
    $request_uri =
        isset( $_SERVER[\'REQUEST_URI\'] ) ?
            filter_var( wp_unslash( $_SERVER[\'REQUEST_URI\'] ), FILTER_SANITIZE_STRING ) :
            \'\';

    if ( url_to_postid( $request_uri ) ) {
        return \'\';
    }

    $path_parts = explode( \'/\', $request_uri );
    $part1      = isset( $path_parts[1] ) ? $path_parts[1] : \'\';

    if ( \'property\' !== $part1 ) {
        return \'\';
    }

    $address = isset( $path_parts[2] ) ? $path_parts[2] : \'\';

    return str_replace( \'-\', \' \', $address );
}

/**
 * Filter page title.
 *
 * @param array $title_parts Title parts.
 *
 * @return mixed
 */
function theme_slug_filter_wp_title( $title_parts ) {
    global $parsed_address, $api_results, $wp_query;

    if ( ! $parsed_address ) {
        return $title_parts;
    }

    $title_parts[\'title\'] = ucwords( $parsed_address ) . \' | AAA Real Estate\';

    return $title_parts;
}

add_filter( \'document_title_parts\', \'theme_slug_filter_wp_title\' );
我们通过pre_handle_404, 发出API请求并保存结果。请注意,当我们只解析URI中的地址时,它就会工作。

过后template_redirect 事件中,我们再次检查是否已解析地址并设置回404状态,以防止get\\u header()中出现错误。请注意,我们拦截template_redirect 尽可能早,在- PHP_INT_MAX 优先在标准之前执行我们的代码template_redirect 钩住WP芯。