问题描述
当开发一个插件应该将这些功能分组到一个类中以避免命名空间冲突?
使用类创建 PHP 的性能开销?
如果有性能打击,应该是功能名称只是 pre-fixed 而不是?
最佳解决方案
When developing a plugin should the functions be grouped together into a Class to avoid namespace conflicts?
是的,但这只是一个小小的论据。 In-fact 不是 OOAD 中的一个类的”true” 性质。
Does using classes create performance overheads for PHP?
不,不是特别。糟糕的设计和/或坏的书写代码或 pre-mature 优化比实际的语言功能创造出更多的性能问题。
If there is a performance hit, should function names just be pre-fixed instead?
如书面所述,没有表现打击。糟糕的书面代码将会更好的表现出色,而不是强制您做坏事的良好代码。
底线:
您可以对插件进行不同的使用。您可以使用它们具有某种命名空间,并将其用于全局函数”just” 。最直接的形式是静态类函数,下面的 code-example 显示了第一个全局函数,然后是全局静态类函数:
/* global function */
function myplug_hook()
{
}
add_filter('the_hook', 'myplug_hook');
/* global static function */
class myplug
{
public static function hook()
{
}
}
add_filter('the_hook', 'myplug::hook');
这只是一个示例,显示您需要为单个钩子键入更多。另外,它显示了命名空间的工作原理:您可以更容易地替换单个类名称来重命名所有静态函数,然后搜索并替换 myplug::
,因为 myplug_
可能因为错误的肯定而更难。但最终没有什么区别。
关键是:静态类函数 Docs 不是真的很多,然后是全局 functionsDocs 。
这个例子也是如此:命名空间很好,但是使用 worpdress,命名空间停止使用钩子:回调函数是硬编码的,因此使用类的命名空间的好处 (base-name 的一个位置,类名) 不会有帮助你的代码与 wordpress 的钩子名称进行干预。
真正的好处是使用实际的类实例和 non-static 函数。这有利于您开始使用 OO 原则,您可以简化代码。静态类函数比一个解决方案更为问题。
那么它不仅仅是语法糖。
要点是:做一些有助于您编写可以轻松处理和维护的代码的东西。不要 over-rate 的表现,这是一个常见的错误。更重要的是你编写的代码很容易阅读和理解,只是做你所需要的。也许这个问题和答案在这个上下文中有更大的帮助:多个自定义的 Metabox 帮助。
一个常见的方法我甚至使用较小的插件是使用静态帮助函数实例化插件,其余的驻留在插件实例中。这有助于封装主要的插件逻辑,它可以从命名空间中获益,而私有成员也可以使用不符合标准全局功能的钩子之间的 re-used 。以下 code-example 显示模式:
<?php
/** Plugin Headers ... */
return MyPlugin::bootstrap();
class MyPlugin
{
/** @var MyPlugin */
static $instance;
static public function bootstrap() {
if (NULL === self::$instance) {
self::$instance = new __CLASS__;
}
return self::$instance;
}
# ...
}
这是我用于基本插件文件的常见模式。插件类一方面表示 Wordpress 的插件,另一方面它允许开始为自己的代码使用面向对象的范例,甚至可以完全面向对象 (但不需要) 。它是一个控制器,与整个 wordpress API 接口作为请求。
如示例所示,将创建一个插件的实例。这样可以使用像构造函数文档 (__construct
) 这样的已知的常量来初始化实际的插件:
# ...
class MyPlugin
{
# ...
public function __construct()
{
add_filter('the_hook', array($this, 'hook'));
}
public function hook()
{
}
# ...
}
当钩子被注册时,这个插件对象已经受益于它的设计:你已经停止了 hard-code 的具体插件类名的实际钩子功能。这是可能的,因为该类与回调的对象实例绑定。听起来很复杂,只是说:$this
是插件。可以在钩子回调中使用,比较注册类方法作为钩子回调。
这种模式允许与 wordpress 更容易的接口:注入被减少到钩子的名称以及它们提供的数据。然后,您可以开始直接实现这个插件类,或者重构对它的实现,所以只能将代码放入插件类,这是最小限度,以定义你的插件与 wordpress 的接口,但保持一般的逻辑除了 worpdress 。这是乐趣开始的地方,最有可能是每个插件作者想要从长远来看。
所以不要用 worpdress 编程,而是反对它。由于 worpdress 是相当灵活的,没有通用或容易描述程序的接口。一个基本的插件类可以承担起这个角色,使您可以为自己的代码提供更多的灵活性,这将导致更容易的代码和更好的性能。
因此,对于 name-spacing 来说,不仅仅是一个好处。我可以给的最佳建议是:尝试自己。没有多少你会松动,只有新的东西要发现。
在您保持插件兼容性的同时,您通过了更多主要的 WordPress 更新之后,您可能会注意到差异。
注意事项:如果您的插件直接与 wordpress 集成以完成工作,则使用一个或两个公共功能可能更适合您。为工作采取正确的工具。
次佳解决方案
类 VS 函数集
Performance
一般:Afaik,”performance” 在类和函数集之间没有区别。
详情:
- 如果您对
function_exists()
和class_exists()
提出质疑,那么通常您会得到很多功能 (wp core 中的〜 1.800(?)) 与类 (〜 100(?) 在 wp core 中) 有很大差异。所以制作的东西”pluggable”,因此质疑存在是执行时间的不同。 - 类比函数集提供了一个很大的优势:你可以更容易地避免在不需要它的请求上调用它,然后使用函数。您只需要对类进行条件检查,而不是为每个函数执行条件检查。所以如果你不需要它在每一个页面加载,并可以避免调用大量的 if / else 语句,功能”performs better” 。
建筑 – 工作原理:
函数集:通常,函数在你调用的行中被执行。所以每次你打电话的东西,你必须再写一次,如果你不得不多说一次。
类:类有不同的亵渎。最接近函数集的类是”factory” 类 (wikipedia / google) 。 Imo 它几乎与一组函数相同,但封装在一个类中。但也有其他”types” 的类。你可以这样写一个抽象的或者一个父类的类,你可以用一个子类来扩展它。在一个现实世界的例子中:假设你有一个类来建立一些静态文本字段。在您的__construct()
功能中,您有一组场景,如”left_column”,”right_column”& “footer_field” 。然后你调用类似 $text_field = new TextFieldClass();
来实例化类。之后你只需调用 $text_field->add( $case => 'left_column', 'case' => 'foo text' );
和 $text_field->add( $case => 'footer_field', 'case' => 'bar text' );
。然后,当您实例化类时,只有当您构建文本字段时才会调用两个类函数,那么所有的条件都已经被执行了。在这个 szenario 中,你可以节省一些 ms 的执行时间。
个人想法
如果你明智地写下你的课,那么你的表现会有一个小的优势。但是,您将有一个组织良好的结构来工作。到目前为止没有什么壮观。但是,如果您考虑以下”split” 用于插件中的类和函数的用例,那么您将得到我的最后一点:类是内部的,函数是 API 。只要您通过公共可用功能 (即调用类或类函数) 提供 API,那么您将进一步开发您的插件。您可以自由地改变内部结构,甚至改变插件的可能性,而无需随时随地影响用户。
例:
// construction of object
if ( ! class_exists( 'WPSE_HelloWorld' ) )
{
class WPSE_HelloWorld
{
function __construct( $args = array( 'text', 'html', 'echo' ) )
{
// call your object building procedures here
$this->hello_world( 'text', 'html', 'echo' );
}
function hello_world( 'text', 'html', 'echo' )
{
$start_el = '<{$html}>';
$end_el = '</{$html}>';
if ( $echo )
{
return print "{$start_el}{$some}{$end_el}";
}
return "{$start_el}{$some}{$end_el}";
}
} // END Class
}
// API: public functions
function the_hello_world( $args( 'echo' => true ) )
{
$new = new WPSE_HelloWorld();
return $new->hello_world( $args );
}
function get_hello_world( array( $args( 'echo' => false) ) )
{
$new = new WPSE_HelloWorld();
return $new->hello_world( $args );
}
// then you can call it like get_the_title() or the_title(), which you know from the WP API:
// 'echo' is set to false per default:
$some_var = get_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *returns* "<strong>hello reader</strong>"
// 'echo' is set to true per default:
the_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *prints/echos* "<strong>hello reader</strong>"
注意:请同时阅读在评论中发布的链接 @ t310s 。
第三种解决方案
这是插件作者的一种纯粹的风格选择。速度没有真正的区别。
参考文献
注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。