WordPress 好实践:自动移动版模板文件路由

前言

熟悉 WordPress 开发的作者都知道,WordPress 对于页面的渲染会遵从一定的法则进行模板的定位,而模板之间沿用一定的层级链,这可以参考文档:

https://developer.wordpress.org/themes/basics/template-hierarchy/

这是一篇重要的文档,掌握这个概念对于如何编写主题有重要的意义。

举个例子,如果我们通过 http://example.com/about.html 路由到别名为 about 的一个页面,那么模板的层级系统就会尝试按照如下的方式去确定最终使用的模板:

Page

The template file used to render a static page (page post-type). Note that unlike other post-types, page is special to WordPress and uses the following patch:

  1. custom template file – The page template assigned to the page. See get_page_templates().

  2. page-{slug}.php – If the page slug is recent-news, WordPress will look to use page-recent-news.php.

  3. page-{id}.php – If the page ID is 6, WordPress will look to use page-6.php.

  4. page.php

  5. index.php

可见,WordPress 内核会在加载页面的时候依次视图查找这些文件:

  1. 手工指定的页面模板(数据库中保存的动态指定);
  2. page-{页面别名}.php
  3. page-{页面ID}.php
  4. page.php
  5. index.php

也就是说,系统会按照这个次序找到第一个存在的文件并用来渲染页面。

对应的内核代码

上面的逻辑是在哪里实现的呢?我们来看这个文件 /wp-includes/template-loader.php

底部这一段:

if ( defined('WP_USE_THEMES') && WP_USE_THEMES ) :
    $template = false;
    if     ( is_404()            && $template = get_404_template()            ) :
    elseif ( is_search()         && $template = get_search_template()         ) :
    elseif ( is_front_page()     && $template = get_front_page_template()     ) :
    elseif ( is_home()           && $template = get_home_template()           ) :
    elseif ( is_post_type_archive() && $template = get_post_type_archive_template() ) :
    elseif ( is_tax()            && $template = get_taxonomy_template()       ) :
    elseif ( is_attachment()     && $template = get_attachment_template()     ) :
        remove_filter('the_content', 'prepend_attachment');
    elseif ( is_single()         && $template = get_single_template()         ) :
    elseif ( is_page()           && $template = get_page_template()           ) :
    elseif ( is_category()       && $template = get_category_template()       ) :
    elseif ( is_tag()            && $template = get_tag_template()            ) :
    elseif ( is_author()         && $template = get_author_template()         ) :
    elseif ( is_date()           && $template = get_date_template()           ) :
    elseif ( is_archive()        && $template = get_archive_template()        ) :
    elseif ( is_comments_popup() && $template = get_comments_popup_template() ) :
    elseif ( is_paged()          && $template = get_paged_template()          ) :
    else :
        $template = get_index_template();
    endif;
    /**
     * Filter the path of the current template before including it.
     *
     * @since 3.0.0
     *
     * @param string $template The path of the template to include.
     */
    if ( $template = apply_filters( 'template_include', $template ) )
        include( $template );
    return;
endif;

内核的处理过程是,找到存在的模板文件,然后 include 进去。

在 include 之前,放了一个过滤器钩子:template_include

我们要解决的问题

现在,我们有这样一个场景,我们的网站是 PC 版和移动版都需要兼容的,但是我们希望能够在需要的情况下为 PC 版和 mobile 版分别指定模板文件。

例如 page.php 我们可以动态指定 page-mobile.php 或者避免冲突,使用 page[mobile].php 这样的文件名,如果是使用移动端访问,自动就用这个模板文件访问(如果这个文件不存在能够自动忽略)。

回到前面,我们看到 template_include 这个钩子,然后用下面的函数,就可以实现了。

将这段钩子函数加到主题的 functions.php 或者插件代码中:

/**
 * 移动端跳转
 * 如果当前 wp_is_mobile 为真
 * 而且路径渲染的模板文件存在 -mobile 版本
 * 则使用 {file}-mobile.php 的模板文件)
 */
add_filter('template_include', function($template) {

    $mobile_template_file = preg_replace('/\\.php$/', '-mobile.php', $template);

    if(wp_is_mobile() && file_exists($mobile_template_file)) {
        return $mobile_template_file;
    }

    return $template;

}, 10, 1);

至于中间正则替换的文件名模式是可以自行定义的,就可以换成 {origin}[mobile].php 这种命名风格也随意了。


【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2015/06/wordpress-template-mobile.html【WordPress 好实践:自动移动版模板文件路由】

发表评论

电子邮件地址不会被公开。 必填项已用*标注