問題描述

有沒有人在插件或主題中使用 autoloading 和/或 PHP 命名空間?

使用它們的想法?有什麼傷害嗎陷阱?

注意:命名空間僅限於 PHP 5.3+。假設在這個問題上,你知道你會處理你所知道的具有 PHP 5.3 或更高版本的服務器。

最佳解決方案

好吧,我有兩個大項目,我已經控制了服務器足夠的命名空間,並依靠自動加載。

第一。自動加載真棒不用擔心需求是一件比較好的事情。

這是一個我在幾個項目中使用的裝載機。檢查以確保類在當前的命名空間中,然後 bails 如果沒有。從那裏只是一些字符串操作來找到類。

<?php
spl_autoload_register(__NAMESPACE__ . 'autoload');
function autoload($cls)
{
    $cls = ltrim($cls, '');
    if(strpos($cls, __NAMESPACE__) !== 0)
        return;

    $cls = str_replace(__NAMESPACE__, '', $cls);

    $path = PLUGIN_PATH_PATH . 'inc' .
        str_replace('', DIRECTORY_SEPARATOR, $cls) . '.php';

    require_once($path);
}

人們可以很容易地適應這個使用沒有命名空間。假設你的插件’s/theme’s 的前綴是統一的,你可以測試該前綴。然後在類名中使用下劃線作為目錄分隔符的佔位符。如果你正在使用很多類,你可能想要使用某種類的自動加載器。

命名空間和掛鈎

WordPress 的鈎子系統通過使用 call_user_func(和 call_user_func_array) 工作,它將函數名稱作為字符串,並在 do_action(以及隨後的 call_user_func) 函數調用時調用它們。

使用命名空間,這意味着您需要將包含命名空間的完全限定的函數名稱傳遞給鈎子。

<?php
namespace WPSESomeNameSpace;

add_filter('some_filter', 'WPSESomeNameSpacethe_function');
function the_function()
{
   return 'did stuff';
}

如果要這樣做,自由使用__NAMESPACE__魔法常數可能會更好。

<?php
namespace WPSESomeNameSpace;

add_filter('some_filter', __NAMESPACE__ . 'the_function');
function the_function()
{
   return 'did stuff';
}

如果你總是將你的鈎子放在課堂上,那就更容易了。使用 $this 的構造函數中的類的標準創建實例和所有鈎子都可以正常工作。

<?php
namespace WPSESomeNameSpace;

new Plugin;

class Plugin
{
    function __construct()
    {
        add_action('plugins_loaded', array($this, 'loaded'));
    }

    function loaded()
    {
        // this works!
    }
}

如果您使用像我想要的靜態方法,則需要將完整的類名作為數組的第一個參數傳遞。這是很多工作,所以你可以使用魔術__CLASS__常數或 get_class

<?php
namespace WPSESomeNameSpace;

Plugin::init();

class Plugin
{
    public static function init()
    {
        add_action('plugins_loaded', array(__CLASS__, 'loaded'));
        // OR: add_action('plugins_loaded', array(get_class(), 'loaded'));
    }

    public static function loaded()
    {
        // this works!
    }
}

使用核心類

PHP 的類名解析有點不了瞭如果要使用核心 WP 類 (WP_Widget 在下面的示例中),您必須提供 use 語句。

  

use WP_Widget;

class MyWidget extends WP_Widget
{
   // ...
}

或者您可以使用完全限定的類名稱 – 基本上只是使用反斜槓前綴。

<?php
namespace WPSESomeNameSpace;

class MyWidget extends WP_Widget
{
   // ...
}

Defines

這是更通用的 PHP,但它有點我,所以這裏是。

你可能想要定義你經常使用的東西,就像插件的路徑一樣。使用 define 語句將東西放在根命名空間中,除非你明確地將命名空間傳遞給 define 的第一個參數。

<?php
namespace WPSESomeNameSpace;

// root namespace
define('WPSE_63668_PATH', plugin_dir_path(__FILE__));

// in the current namespace
define(__NAMESPACE__ . 'PATH', plugin_dir_path(__FILE__));

您還可以使用 PHP 5.3 plus 的文件根級別中的 const 關鍵字。 consts 始終在當前的命名空間中,但是 define 調用的靈活性較低。

<?php
namespace WPSESomeNameSpace;

// in the current namespace
const MY_CONST = 1;

// this won't work!
const MY_PATH = plugin_dir_path(__FILE__);

請隨意添加您可能有的任何其他提示!

次佳解決方案

我使用自動加載 (因為我的插件有很多類,部分原因是它包括 Twig),從來沒有引起我的注意 (插件安裝> 20,000 次) 。

如果您有信心,永遠不會需要使用不支持命名空間的 php 安裝,那麼您再次可以使用 (約 70%的當前 wordpress 博客不支持命名空間) 。需要注意的幾件事情

我似乎記得,命名空間在常規 PHP 中不區分大小寫,但是當在 iis 上使用 fastcgi php 時,這會導致一些頭痛,如果您在 linux 上測試並且不會發現流氓小寫字母。

即使您確定您正在開發的代碼只能在> 5.3.0 您將無法重用任何沒有奢侈項目的代碼,這就是為什麼我沒有在內部項目中使用命名空間的主要原因。我發現命名空間真的不會增加那麼多,與可能的頭痛不得不刪除它們的依賴。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。