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 文檔非常棒! 代碼示例很乾淨,評論對現實世界很有幫助。 一定要瀏覽它,即使您認為不需要。