问题描述

有没有人在插件或主题中使用 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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。