问题描述

更新:我的原始问题已经解决了,但这正在成为一个有效的讨论,为什么不使用全局变量,所以我正在更新这个问题来反映。该解决方案是<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>,如 @TomJNowell 所建议的。更新 2:我现在正在做正是我想要的。但是我仍然在使用全球范围,很乐意找到一个更好的方法。

我正在设计一大堆全球变量,将固定链接分类用于我主题的各个地方。其主要原因是用于主导航,以及根据当前帖子所属类别选择的一系列子导航。这不是我将被其他人使用的主题,但是建立在一个非常具体的目的。

这是我目前正在创建的 (我只粘贴了一些变量) 。

    function set_global_nav_var()
    {
    //proposal
    global $prop;
    // Get the ID of a given category
    $category_id_prop = get_cat_ID( 'proposal' );
    // Get the URL of this category
    $category_link_prop = get_category_link( $category_id_prop );
    $prop = '<a href="'%20.esc_url(%20$category_link_prop%20).%20'" title="Proposal">Proposal</a>';

    //Calvinball
    global $cb;
    // Get the ID of a given category
    $category_id_cb = get_cat_ID( 'calvinball' );
    // Get the URL of this category
    $category_link_cb = get_category_link( $category_id_cb );
    $cb = '<a href="'%20.esc_url(%20$category_link_cb).%20'" title="Calvinball">Calvinball</a>';
    }
    add_action( 'init', 'set_global_nav_var' );

我现在可以做<?php global $prop; echo $prop; ?>,他可以通过 4 个地方来获取代码的整个链接。当这种变化时,我只需要在一个地方改变它。我对不涉及全球范围的替代品开放。

最佳解决方案

虽然我强烈建议反对这一点,但它不会加快速度,您的使用不正确。

当您尝试使用全局时,您必须首先指定全局关键字。在定义其值时,您已经在此处指定了它,但在该范围之外,它需要作为全局作用域变量重新声明。

例如在 functions.php 中:

function test() {
    global $hello;
    $hello = 'hello world';
}
add_action( 'after_theme_setup', 'test' );

在 single.php 中,这将不起作用:

echo $hello;

因为 $ hello 是未定义的。但是这样做会:

global $hello;
echo $hello;

当然你也不应该这样做。 WordPress 已经尝试将这些东西缓存在对象缓存中。您将看到没有加快速度 (您可能会看到一个微小的速度降低),所有你会得到的是额外的复杂性,需要输出很多没有必要的全局声明。

您最好使用结构化数据,如对象或依赖注入,或在您的情况下,一组功能。

例如,这里是一种通过静态变量进行类似操作的方式 (由于相同的原因,它们仍然是不好的,但是稍微少一些,并且更易于键入) 。

function awful_function( $new_hello='' ) {
    static $hello;
    if ( !empty( $new_hello ) ) {
        $hello = $new_hello;
    }
    return $hello;
}

awful_function( 'telephone' );
echo awful_function(); // prints telephone
awful_function( 'banana');
echo awful_function(); // prints banana

如果您真的想通过将数据存储到 re-use 的某个地方来节省时间,请考虑使用 WP_Cache 系统

次佳解决方案

不要使用全局变量,就这么简单。

为什么不使用全局变量

由于使用全局变量使得长期维护软件变得更加困难。

  • 一个全局可以在代码中的任何地方被声明,或者根本就没有地方,因此没有任何地方可以直观地查看关于全局所用的一些注释

  • 在阅读代码时,通常会认为变量是函数本地的,不明白在函数中改变它们的值可能会有系统的变化。

  • 如果它们不处理输入,函数在使用相同参数调用时应返回相同的值/输出。在函数中使用全局变量引入了在函数声明中不是文档的附加参数。

  • 全局变量没有任何特定的初始化结构,因此您无法确定何时可以访问全局值,并且在初始化之前尝试访问全局时不会收到任何错误。

  • 有人 (一个插件可能) 可能会使用同名的全局变量,破坏你的代码,或者你根据初始化顺序毁了它。

WordPress 核心的方式方式很多地使用全局变量。在尝试了解 the_content 的基本功能如何工作时,您突然意识到 $more 变量不是本地的,而是全局的,需要搜索整个核心文件以了解何时设置为 true 。

那么当试图停止复制和粘贴几行代码而不是将第一个运行结果存储在全局中时,可以做些什么呢?有几种方法,功能和 OOP 。

甜味剂功能。它只是一个保存复制/粘贴的包装/宏

// input: $id - the category id
// returns: the foo2 value of the category
function notaglobal($id) {
  $a = foo1($id);
  $b = foo2($a);
  return $b;
}

好处是,现在有一个关于前一个全局功能的文档,当您返回的值不是您期望的值时,您有一个明显的要点。

一旦你有一个甜味剂,很容易缓存结果,如果需要 (只有当你发现这个功能需要很长时间才能执行)

function notaglobal($id) {
  static $cache;

  if (!isset($cache)) {
    $a = foo1($id);
    $b = foo2($a);
    $cache = $b;
  }
  return $cache;
}

这给你一个全球性的行为,但是每次访问它时都有一个有保证的初始化的优点。

您可以使用类似的 OOP 模式。我发现 OOP 通常不会在插件和主题中添加任何值,但这是一个不同的讨论

class notaglobal {
   var latestfoo2;

   __constructor($id) {
     $a = foo1($id);
     $this->latestfoo2 = foo2($a)
   }
}

$v = new notaglobal($cat_id);
echo $v->latestfoo2;

这是一个笨拙的代码,但如果您有几个值要预先计算,因为它们始终被使用,这可以是一种方式。基本上这是一个以有组织的方式包含所有全局变量的对象。为了避免使这个对象的实例成为一个全局 (你想要一个实例,否则重新计算值),你可能想使用一个 singleton pattern(有些人认为这是一个坏主意,YMMV)

我不喜欢直接访问对象属性,所以在我的代码中,它会变得更多

class notaglobal {
   var latestfoo2;

   __constructor() {}

   foo2($id) {
     if (!isset($this->latestfoo2)) {
       $a = foo1($id);
       $b = foo2($a);
       $this->latestfoo2= $b;
     }
     return $this->latestfoo2;
   }
}

$v = new notaglobal();
echo $v->foo2($cat_id);

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。