Woocommerce - woocommerce_locate_template 的替代品

Woocommerce - Alternative for woocommerce_locate_template

我正在开发一个基于 woocommerce 的插件,作为其中的一部分,我不得不覆盖 woocommerce 的默认模板文件位置。我的意思是我希望从我的插件中加载自定义 woocommerce 模板。

为了做到这一点,我在 woocommerce 中阅读了有关 woocommerce_locate_template 的文章,基于此 article, but I noticed that the same function has been deprecated as per this link。现在我想知道什么是替代功能。

我的全部意图是将默认的 woocommerce 模板加载位置更改为我的插件文件夹。对解决这个问题有帮助吗? 提前致谢。

woocommerce_locate_template 函数已弃用,取而代之的是 wc_locate_template:您可以阅读代码 here

但是,如果您要查找 过滤器,它仍然是 woocommerce_locate_template 并且需要三个参数:

  1. $template 即wp核心函数locate_template
  2. 的结果
  3. $template_name 那只是文件名
  4. $template_path 这是模板的 woocommerce 路径

所以你可以检查 $template_name 是否是你想要拦截的,如果是的话改变路径,像这样

function intercept_wc_template($template, $template_name, $template_path) {
    if ($template_name == 'that_template.php') {
        $template = 'the/path/of/your/plugin/template.php';
    }
    return $template;
}

add_filter('woocommerce_locate_template', 'intercept_wc_template', 20, 3);

我还没有测试过,对于任何可能的语法错误,我们深表歉意:)

希望对您有所帮助!

-- 更新 1:我忘了分号 :P --
-- 更新二:我搞错了! --

我不得不修改上面的代码以使其正确匹配我需要的模板文件,在我的例子中是 "variable.php"。

$template_name 需要是完整的 woocommerce 根路径,见下文:

查看下面修改后的代码:

function intercept_wc_template($template, $template_name, $template_path) {
    if ($template_name == 'single-product/add-to-cart/variable.php') {
        $template = 'wp-content/themes/theme-name/woocommerce/single-product/add-to-cart/variable.php';
    }

    return $template;
}

add_filter('woocommerce_locate_template', 'intercept_wc_template', 20, 3);

如果有人在 2021 年遇到这个问题,值得一提的是过滤器'woocommerce_locate_template'不会过滤所有模板 woocommerce 文件夹。相反,您需要过滤 2 个其他函数:

add_filter('wc_get_template', 'entex_wc_get_template', 20, 5);
add_filter('wc_get_template_part', 'entex_wc_get_template_part', 20, 3);

例如,根 woocommerce 模板 content-single-product.php 必须用 wc_get_template_part 过滤。

这适用于我们的插件:

function template_base(){
    return untrailingslashit(plugin_dir_path( __FILE__ )) .'/templates/';
}

function entex_wc_get_template($template, $template_name, $args, $template_path, $default_path){

    /* custom theme templates has priority */
    if(strpos($template, '/themes/') !== FALSE) return $template;

    static $cache = array();
    if(isset($cache[$template_name])) return $cache[$template_name];
    
    $plugin_template = wc_locate_template($template_name, WC()->template_path(), $this->template_base());
    if($plugin_template && file_exists($plugin_template)){
        $template = $plugin_template;
        $cache[$template_name] = $template;
    }
    return $template;
}

function entex_wc_get_template_part($template, $slug, $name){
    
    /* custom theme templates has priority */
    if(strpos($template, '/themes/') !== FALSE) return $template;
    
    $template_name = '';
    if($name){
        $template_name = "{$slug}-{$name}.php";
    } else if($slug){
        $template_name = "{$slug}.php";
    }
    if(!$template_name) return $template;
    
    static $cache = array();
    if(isset($cache[$template_name])) return $cache[$template_name];
    
    $plugin_template = template_base().$template_name;
    if($plugin_template && file_exists($plugin_template)){
        $template = $plugin_template;
        $cache[$template_name] = $template;
    }
    return $template;
} 

这是从 PHP class 中撕下并粘贴在这里,希望代码没有被破坏。

如果您只使用几个模板,我们建议注册模板以获得更清晰的性能,并在函数的早期添加如下内容:

if(!in_array($template_name, array(
    'archive-product.php',
    'content-product.php',
    'content-product-cat.php',
    'content-single-product.php',
    'content-widget-product.php',
    'checkout/form-checkout.php',
    'checkout/thankyou.php',
    'loop/loop-start.php',
    'loop/loop-end.php'
))) return $template;