WordPress 中的 PHP 命名空间——一本严肃的指南

已发表: 2018-10-16

PHP 命名空间已经有将近十年的历史了。 是的,十年过去了(是的,你变老了)。 尽管 PHP v5.3 发布已经过去了十年,但许多开发人员仍然对命名空间没有基本的了解。 说实话WordPress 不使用命名空间,所以“如果你只使用 WordPress,你不需要知道如何使用命名空间。” 您不需要成为命名空间忍者,但掌握基础知识很简单,而且对您有好处。

PHP 命名空间已经存在了十年,您仍然不使用它们,因为#wordpress 也没有? 阅读并在 2 分钟内开始使用它们! #发展

点击推文

当没有命名空间支持时——使用前缀

很长很长一段时间以来,PHP 都没有原生命名空间支持。 这就是 WordPress 和许多其他大型代码库不使用本机命名空间的原因。 它们在需要时不在身边,因此使用了前缀。

命名空间很重要,因为它确保您的函数write_to_log()尚未由另一段代码定义。 为了避免名称冲突,全局范围内的所有内容都需要一个前缀,因此该函数变为awesome_project_write_to_log()并且所有其他函数和变量也获得了awesome_project_前缀。 简单的? 这是! 漂亮的? 不完全是。

该方法有一些替代方法,例如静态方法封装。 您将所有函数包装在一个类中并将它们声明为静态方法。 然后调用My_Class::my_function()而不是调用my_function() () 。 更好的? 有点,但仍然不是正确的命名空间。

让我们看看命名空间如何允许多个代码段(或如果需要,可以使用包)使用相同的类和函数名而不会发生冲突。 或者正如 PHP 手册所说——它们如何启用代码封装。 它们与文件和文件夹的类比也很明显——在很多方面命名空间的行为就像文件夹一样,所以我将从手册中复制/粘贴;

在任何操作系统中,目录用于对相关文件进行分组并充当其中文件的命名空间。 例如,文件 foo.txt 可以同时存在于目录 /home/greg 和 /home/other 中,但 foo.txt 的两个副本不能共存于同一目录中。 要访问 /home/greg 目录之外的 foo.txt 文件,我们必须使用目录分隔符将完整目录名添加到文件名前,以获取 /home/greg/foo.txt。

声明命名空间——记住第一行

关键字namespace必须是文件中的第一行代码(不包括注释和任何非 PHP 内容)。 命名空间只影响类、接口、函数和常量。 它们不影响变量。 您可以在多个文件中定义相同的命名空间,从而允许您将代码拆分为多个文件。 子命名空间允许在命名空间中定义层次结构,就像在文件夹中一样,使用反斜杠namespace myproject\level1\level2 。 这些是声明命名空间的基本规则和几乎所有规则。

// file-A.php contains a function under the myCompany\PackageA namespace
namespace myCompany\PackageA;
 
function do_something() {
  // do things
}
// file-B.php contains a function with the same name
// but under a different namespace
namespace myCompany\PackageB;
 
function do_something() {
  // do things
}

尽管可能,但我强烈建议不要将多个命名空间组合到一个文件中。 相信我,你迟早会忘记你做过,然后调试一个 2 分钟的错误需要两个小时。 但是,如果必须,这里是语法。

// do not put multiple namespace declarations into the same file
// but if you must, here's the syntax

namespace MyFirstProject {
  const CONST = true;
  class Connection { /* ... */ }
  function connect() { /* ... */  }
}

namespace MySecondProject {
  const CONST = true;
  class Connection { /* ... */ }
  function connect() { /* ... */  }
}

// any code after this has to go in the global namespace
namespace {
  $some_var = 1;
  function_in_global_namespace();
}

使用命名空间——记住文件夹

正如我已经说过的——命名空间与文件夹非常相似。 假设文件foo.txt在您当前的文件夹中; 你可以用一个简单的foo.txt来引用它。 如果您比具有foo.txt文件的文件夹高一级,则需要使用相对路径../foo.txt或绝对路径/folder1/folder2/foo.txt 。 没有什么花哨。 命名空间使用相同的范例。

// remember after declaring a namespace
// all our code is in it; like when you're working in a folder
namespace mycompany\project;

function foo() {}
class foo {
  static function staticmethod() {}
}

// resolves to mycompany\project\foo() because of line #3
foo();

// likewise, resolves to mycompany\project\foo::staticmethod()
foo::staticmethod();

// constant are affected by namespaces too
// so we're working with mycompany\project\FOO
echo FOO;

// this is a relative path
// resolves to mycompany\project\subnamespace\foo()
subnamespace\foo();

// static methods are no different
// mycompany\project\subnamespace\foo::staticmethod()
subnamespace\foo::staticmethod();
                                 
// a full namespace path starts with a backslash
// it resolves exactly to what it says it does
\otherNamespace\Bar\foo();

// again same thing for a constant, full path nothing magical
echo \otherNamespace\Bar\FOO;

看看 PHP 手册中的use关键字——例子很棒。 它提供了一种将代码从其他 PHP 命名空间导入当前命名空间或使用别名引用外部(完全限定)名称的方法。

是的,您需要命名空间并且应该使用它们

通过查看 WordPress 的源代码,这一点非常明显——您不必使用命名空间,但您必须使用一些命名空间的方法。 在 WP 的情况下以wp_为前缀。 那么,如果我们已经在做,为什么不正确地做呢?

PHP 中的命名空间很容易集成到任何开发工作流程中。 它们简化了自动加载、文件命名,并且通常使代码更清晰。 重构旧代码从来都不是一个流行的任务(不管编码语言如何),所以我不会告诉你继续重构一个工作的 2 MB 项目,以便你可以说你使用命名空间。 但是,我会坚持在处理新项目时使用命名空间。 你很快就会感谢自己的。

关于命名空间的官方 PHP 文档非常棒! 代码示例很干净,评论对现实世界很有帮助。 一定要浏览它,即使您认为不需要。