剖析 WordPress `get_child_theme_parent_slug()` 函数的源码:如何获取子主题的父主题 `slug`。

各位看官,大家好!今天咱们来聊聊 WordPress 里一个挺隐蔽,但有时候又很有用的小函数:get_child_theme_parent_slug()。 顾名思义,这个函数的作用就是获取子主题的父主题的 slug。 啥是 slug? 简单说,就是主题文件夹的名字,也是主题在 WordPress 内部的唯一标识符。

为什么要了解 get_child_theme_parent_slug()

  • 自定义子主题行为: 有时候我们需要根据父主题的不同,在子主题里做一些特殊的处理。 例如,如果父主题是 "twentytwentythree",我们可能要加载一些特定的 CSS 或者 JS。
  • 插件开发: 插件需要兼容不同的主题时,了解父主题的信息可以帮助插件更好地适应各种主题的特性。
  • 调试: 了解主题的结构,可以帮助我们更好地调试主题相关的问题。

get_child_theme_parent_slug() 源码剖析

咱们直接上代码,然后一行一行地拆解:

<?php
/**
 * Retrieves the parent theme slug for the current child theme.
 *
 * @since 5.3.0
 *
 * @return string The parent theme slug. Empty string if no child theme in use.
 */
function get_child_theme_parent_slug() {
    if ( ! is_child_theme() ) {
        return '';
    }

    $template_directory = get_template_directory();
    $theme              = wp_get_theme( get_stylesheet() );

    if ( empty( $theme['Template'] ) ) {
        return '';
    }

    return sanitize_title( $theme['Template'] );
}

第一步:确认是不是子主题 (is_child_theme())

if ( ! is_child_theme() ) {
    return '';
}

这段代码是整个函数的入口守卫。is_child_theme() 函数用来判断当前是否正在使用子主题。如果不是,直接返回空字符串 ''

is_child_theme() 函数的源码如下:

function is_child_theme() {
    static $is_child_theme = null;

    if ( is_null( $is_child_theme ) ) {
        $is_child_theme = ( get_template_directory() !== get_stylesheet_directory() );
    }

    return $is_child_theme;
}

它通过比较 get_template_directory()get_stylesheet_directory() 的返回值来判断。

  • get_template_directory() 返回父主题的目录。
  • get_stylesheet_directory() 返回当前主题(如果是子主题,那就是子主题)的目录。

如果这两个目录不一样,那就说明我们正在使用子主题。

第二步:获取父主题模板目录 (get_template_directory())

$template_directory = get_template_directory();

虽然这里用到了 $template_directory 这个变量,但在接下来的代码里并没有直接使用它。 它的作用,只是为了确保我们确实在使用子主题,因为如果不是子主题,get_template_directory() 会返回当前主题的目录,而 get_stylesheet_directory() 也会返回同样的值,is_child_theme() 就会返回 false

第三步:获取主题信息 (wp_get_theme())

$theme = wp_get_theme( get_stylesheet() );

wp_get_theme() 函数是获取主题信息的关键。 它接受一个参数,这个参数是主题的目录名 (slug)。这里我们传递的是 get_stylesheet() 的返回值,也就是当前主题的目录名,如果是子主题,就是子主题的目录名。

wp_get_theme() 函数会读取主题目录下的 style.css 文件,然后解析里面的主题信息,比如主题名称、作者、版本等等。

第四步:检查父主题模板是否存在 ($theme['Template'])

if ( empty( $theme['Template'] ) ) {
    return '';
}

这里检查 $theme['Template'] 是否为空。 $themewp_get_theme() 返回的主题对象, ['Template'] 对应的是主题 style.css 文件里的 Template 字段。

在子主题的 style.css 文件里,必须要有 Template 字段,用来指定父主题的目录名 (slug)。 如果没有这个字段,或者这个字段为空,那就说明这个主题不是一个有效的子主题,所以函数返回空字符串。

第五步:返回父主题的 slug (sanitize_title())

return sanitize_title( $theme['Template'] );

最后一步,也是最重要的一步,就是返回父主题的 slug$theme['Template'] 包含了父主题的 slug, 但是我们需要用 sanitize_title() 函数来对它进行清理。

sanitize_title() 函数的作用是将字符串转换成一个安全的 URL 友好型字符串, 也就是 slug。 它会移除字符串里的所有非字母、数字和连字符 - 的字符,并将字符串转换成小写。

总结

get_child_theme_parent_slug() 函数的整个流程可以总结如下:

步骤 代码 说明
1 if ( ! is_child_theme() ) { return ''; } 检查是否是子主题,如果不是,返回空字符串。
2 $template_directory = get_template_directory(); 获取父主题模板目录,虽然没有直接使用,但间接验证了是否是子主题。
3 $theme = wp_get_theme( get_stylesheet() ); 获取当前主题的信息。
4 if ( empty( $theme['Template'] ) ) { return ''; } 检查父主题模板是否存在,如果不存在,返回空字符串。
5 return sanitize_title( $theme['Template'] ); 返回父主题的 slug,并使用 sanitize_title() 函数进行清理。

使用示例

假设我们有一个子主题,它的 style.css 文件里有如下内容:

/*
 Theme Name:   My Child Theme
 Theme URI:    https://example.com/my-child-theme/
 Description:  My Child Theme based on Twenty Twenty-Three
 Author:       Your Name
 Author URI:   https://example.com
 Template:     twentytwentythree
 Version:      1.0.0
*/

在这个例子里,Template: twentytwentythree 指定了父主题的 slugtwentytwentythree

如果我们在这个子主题里调用 get_child_theme_parent_slug() 函数:

<?php
$parent_slug = get_child_theme_parent_slug();
echo 'Parent theme slug: ' . $parent_slug; // 输出: Parent theme slug: twentytwentythree
?>

应用场景

  1. 加载父主题特定的CSS/JS:

    假设我们需要在子主题里加载父主题 "twentytwentythree" 特有的 CSS 文件。

    <?php
    function my_child_theme_enqueue_styles() {
        $parent_slug = get_child_theme_parent_slug();
    
        if ( $parent_slug === 'twentytwentythree' ) {
            wp_enqueue_style( 'twentytwentythree-specific', get_stylesheet_directory_uri() . '/css/twentytwentythree-specific.css' );
        }
    }
    add_action( 'wp_enqueue_scripts', 'my_child_theme_enqueue_styles' );
    ?>
  2. 根据父主题显示不同的内容:

    假设我们要根据父主题的不同,在子主题里显示不同的版权信息。

    <?php
    function my_child_theme_copyright_notice() {
        $parent_slug = get_child_theme_parent_slug();
    
        if ( $parent_slug === 'twentytwentythree' ) {
            echo '<p>Copyright 2023. Powered by Twenty Twenty-Three.</p>';
        } elseif ( $parent_slug === 'twentytwentyfour' ) {
            echo '<p>Copyright 2024. Powered by Twenty Twenty-Four.</p>';
        } else {
            echo '<p>Copyright. Powered by an unknown theme.</p>';
        }
    }
    add_action( 'wp_footer', 'my_child_theme_copyright_notice' );
    ?>
  3. 插件开发中的主题兼容性:

    如果你的插件需要根据不同的主题来做一些调整,可以使用 get_child_theme_parent_slug() 函数来判断当前使用的父主题,然后根据父主题的特性来调整插件的行为。

注意事项

  • get_child_theme_parent_slug() 函数只能在子主题里使用。如果在非子主题里使用,它会返回空字符串。
  • 子主题的 style.css 文件里必须要有 Template 字段,用来指定父主题的目录名。
  • Template 字段的值必须是父主题的目录名,也就是父主题的 slug
  • sanitize_title() 函数会对父主题的 slug 进行清理,所以返回的 slug 一定是 URL 友好型的。

总结的总结

get_child_theme_parent_slug() 函数是一个小巧但实用的函数,它可以帮助我们获取子主题的父主题 slug,从而可以根据父主题的不同来定制子主题的行为,或者在插件开发中更好地兼容不同的主题。 理解了这个函数的源码,可以帮助我们更好地理解 WordPress 主题的工作原理,从而可以更好地开发 WordPress 主题和插件。

希望今天的讲解对大家有所帮助。下次再见!

发表回复

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