探讨 `get_template_directory_uri()` 与 `get_stylesheet_directory_uri()` 的源码差异,以及它们在子主题中的应用。

主题公园探险:get_template_directory_uri() vs. get_stylesheet_directory_uri()——子主题寻宝之旅

大家好!我是你们今天的导游,代号“代码探险家”,今天咱们不爬山,不看海,咱们来WordPress主题公园玩一趟,专门探索两个听起来很像,但作用却大相径庭的函数:get_template_directory_uri()get_stylesheet_directory_uri()

准备好了吗?系好安全带,咱们发车!

第一站:函数源码剖析——解开身世之谜

要搞清楚这两个函数的区别,最好的办法就是直接看它们的源码。

get_template_directory_uri()

首先,咱们来扒一扒 get_template_directory_uri() 的底裤(咳咳,我是说源码)。在 wp-includes/theme.php 文件中,我们可以找到它的庐山真面目:

function get_template_directory_uri() {
    return apply_filters( 'template_directory_uri', get_template_directory_uri_raw(), get_template() );
}

function get_template_directory_uri_raw() {
    static $template_dir_uri = false;

    if ( ! $template_dir_uri ) {
        $template_dir = get_template_directory();
        $template_dir_uri = get_stylesheet_directory_uri_raw(); //注意这里!!!
        if ( is_child_theme() ) {
            $template_dir_uri = trailingslashit(get_theme_root_uri( get_template() ) . '/' . get_template());
        }
    }
    return $template_dir_uri;
}

这段代码看起来有点绕,咱们慢慢捋。

  • get_template_directory_uri(): 这是一个过滤器函数,它会调用 get_template_directory_uri_raw() 函数获取原始的 URI,然后应用 template_directory_uri 过滤器,允许我们修改最终的 URI 值。
  • get_template_directory_uri_raw(): 这个函数才是真正干活的。它首先检查是否已经缓存了模板目录的 URI。如果没有,它会调用 get_template_directory() 获取模板目录的绝对路径,然后重点来了,它先用get_stylesheet_directory_uri_raw()初始化$template_dir_uri。如果当前主题是子主题,它会使用 get_theme_root_uri() 获取主题根目录的 URI,并拼接上模板名称,最终得到父主题的 URI。

换句话说,get_template_directory_uri() 永远指向父主题的目录 URI。 无论你是否在子主题中使用它,它都会坚定不移地指向你的老爸(父主题)。

get_stylesheet_directory_uri()

接下来,我们来研究一下 get_stylesheet_directory_uri() 的源码:

function get_stylesheet_directory_uri() {
    return apply_filters( 'stylesheet_directory_uri', get_stylesheet_directory_uri_raw(), get_stylesheet() );
}

function get_stylesheet_directory_uri_raw() {
    static $stylesheet_dir_uri = false;

    if ( ! $stylesheet_dir_uri ) {
        $stylesheet_dir = get_stylesheet_directory();
        $stylesheet_dir_uri = trailingslashit(get_theme_root_uri( get_stylesheet() ) . '/' . get_stylesheet());
    }

    return $stylesheet_dir_uri;
}

是不是感觉似曾相识? 没错,它的结构和 get_template_directory_uri() 非常相似。

  • get_stylesheet_directory_uri(): 同样是一个过滤器函数,它调用 get_stylesheet_directory_uri_raw() 获取原始 URI,并应用 stylesheet_directory_uri 过滤器。
  • get_stylesheet_directory_uri_raw(): 这个函数获取样式表目录的绝对路径,并使用 get_theme_root_uri() 获取主题根目录的 URI,然后拼接上样式表名称,最终得到当前主题的 URI。

关键在于,get_stylesheet_directory_uri() 指向的是当前正在使用的主题的目录 URI。 如果你正在使用子主题,它就会指向子主题的目录。

源码对比总结

为了更清晰地对比这两个函数,我们用表格来总结一下:

函数 作用 指向 是否受子主题影响
get_template_directory_uri() 获取父主题的目录 URI 父主题目录
get_stylesheet_directory_uri() 获取当前主题的目录 URI (如果是子主题,则指向子主题目录,如果是父主题,则指向父主题目录) 当前主题目录 (子主题或父主题,取决于当前激活的主题)

第二站:子主题应用场景——宝藏在哪里?

现在我们知道了这两个函数的区别,接下来就要看看它们在子主题中如何应用了。 想象一下,你正在开发一个子主题,需要引用一些资源文件,比如 CSS、JavaScript、图片等等。 这时候,选择合适的函数就至关重要了。

场景一:引用子主题的 CSS 文件

假设你的子主题中有一个名为 custom.css 的自定义样式文件,你想要在主题中引用它。 应该使用哪个函数呢?

function my_theme_enqueue_styles() {
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' ); // 引用父主题的 style.css
    wp_enqueue_style( 'child-style',
        get_stylesheet_directory_uri() . '/custom.css',
        array( 'parent-style' ),
        wp_get_theme()->get('Version')
    );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );

在这个例子中,我们使用 get_stylesheet_directory_uri() 来获取子主题的目录 URI,并拼接上 custom.css 的路径。 这样做可以确保即使你的子主题被移动到不同的目录下,或者父主题的目录结构发生变化,你的 custom.css 文件依然能够被正确引用。

如果你错误地使用了 get_template_directory_uri(),那么 WordPress 会尝试在父主题的目录下查找 custom.css 文件,这显然是错误的。

场景二:覆盖父主题的模板文件

子主题的一个重要功能就是覆盖父主题的模板文件。 假设你想修改父主题的 header.php 文件,你只需要在子主题中创建一个同名的 header.php 文件,并进行修改即可。

但是,如果你需要在 header.php 文件中引用一些资源文件,比如父主题的 logo 图片,你应该使用哪个函数呢?

<img src="<?php echo get_template_directory_uri(); ?>/images/logo.png" alt="Logo">

在这个例子中,我们使用 get_template_directory_uri() 来获取父主题的目录 URI,并拼接上 logo.png 的路径。 这样做可以确保你引用的是父主题的 logo 图片,而不是子主题的。

如果你错误地使用了 get_stylesheet_directory_uri(),那么 WordPress 会尝试在子主题的目录下查找 logo.png 文件,这可能会导致图片无法显示。 当然,如果你打算用子主题的 logo 覆盖父主题的 logo,那就可以使用 get_stylesheet_directory_uri()

场景三:引用公共资源

有时候,你可能需要在父主题和子主题中共享一些资源文件,比如 JavaScript 库。 这种情况下,你可以将这些资源文件放在父主题的目录下,并在子主题中使用 get_template_directory_uri() 来引用它们。

wp_enqueue_script( 'my-script', get_template_directory_uri() . '/js/my-script.js', array( 'jquery' ), '1.0', true );

总结:选择函数的黄金法则

通过以上几个场景,我们可以总结出一个黄金法则:

  • 引用子主题的资源文件: 使用 get_stylesheet_directory_uri()
  • 引用父主题的资源文件: 使用 get_template_directory_uri()
  • 引用公共资源 (放在父主题中): 使用 get_template_directory_uri()

第三站:高级技巧——玩转过滤器

还记得我们在源码分析中提到的过滤器吗? template_directory_uristylesheet_directory_uri 这两个过滤器可以让你更加灵活地控制主题目录的 URI。

修改父主题的 URI

有时候,你可能需要修改 get_template_directory_uri() 返回的 URI。 比如,你可能想将父主题的资源文件放在 CDN 上,或者使用一个自定义的目录结构。 你可以使用 template_directory_uri 过滤器来实现这个目的。

function my_theme_template_directory_uri( $template_dir_uri, $template ) {
    // 将父主题的 URI 修改为 CDN 地址
    return 'https://cdn.example.com/themes/' . $template;
}
add_filter( 'template_directory_uri', 'my_theme_template_directory_uri', 10, 2 );

修改子主题的 URI

类似地,你也可以使用 stylesheet_directory_uri 过滤器来修改 get_stylesheet_directory_uri() 返回的 URI。

function my_theme_stylesheet_directory_uri( $stylesheet_dir_uri, $stylesheet ) {
    // 将子主题的 URI 修改为自定义目录
    return get_site_url() . '/wp-content/my-themes/' . $stylesheet;
}
add_filter( 'stylesheet_directory_uri', 'my_theme_stylesheet_directory_uri', 10, 2 );

注意: 使用过滤器修改 URI 需要谨慎,确保你的修改不会导致资源文件无法加载,或者引起其他问题。

第四站:常见错误与陷阱——避坑指南

在实际开发中,很多开发者都会犯一些常见的错误,导致主题出现问题。 让我们来看看有哪些常见的陷阱需要避免:

  • 混淆 get_template_directory_uri()get_stylesheet_directory_uri() 这是最常见的错误。 务必记住,get_template_directory_uri() 永远指向父主题,而 get_stylesheet_directory_uri() 指向当前主题。
  • 忘记使用 trailingslashit() 函数: 在拼接 URI 时,最好使用 trailingslashit() 函数来确保 URI 以斜杠结尾。 这样可以避免一些潜在的问题。
  • 硬编码 URI: 尽量避免在主题中硬编码 URI。 这样做会使你的主题难以维护和移植。
  • 不考虑子主题的情况: 在开发父主题时,要考虑到子主题的使用场景,尽量使用 get_template_directory_uri()get_stylesheet_directory_uri() 来引用资源文件。

终点站:总结与展望——未来之路

恭喜大家,我们已经完成了这次主题公园的探险之旅! 现在,你应该对 get_template_directory_uri()get_stylesheet_directory_uri() 这两个函数有了更深入的理解。

记住,它们就像两个导航仪,一个永远指向你的老家(父主题),一个指向你现在所在的地方(当前主题)。 正确使用它们,可以让你在子主题开发中游刃有余。

未来,WordPress 的主题系统可能会发生更多的变化,但掌握这些基础知识,可以让你更好地适应未来的发展。

希望这次讲座对你有所帮助! 代码探险家,下课!

发表回复

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