开发插件时,应将这些功能分组到一个类中以避免命名空间冲突吗?
使用类会为PHP产生性能开销吗?
如果性能受到影响,函数名称是否应该只是前缀?
#1 楼
在开发插件时,应将功能分组到一个类中以避免名称空间冲突吗?
是的,但这只是次要参数之一。实际上,这不是OOAD中类的“真实”本质。
使用类是否会为PHP造成性能开销?
否,值得注意的是。错误的设计和/或糟糕的编写代码或过早的优化会比实际的语言功能造成更多的性能问题。
如果遇到性能问题,应仅在函数名前加上前缀而是?
按照书面规定,不会对性能造成影响。劣质的书面代码比具有许多行代码但不会强迫您做不良事情的优质书面代码更能提高性能。
底线:
您可以为插件使用不同的类。您可以使用它们来拥有某种名称空间,并“仅”将它们用于全局函数。最直接的形式是静态类函数,下面的代码示例同时显示了这两个全局函数,然后是全局静态类函数:
/* 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与全局函数Docs相比并没有什么其他功能。
这个示例也显示了:Namespacing很好,但是使用worpdress时,namespacing停止使用钩子:回调函数经过了硬编码,因此使用类(在基名中放置一个地方,classname)在命名空间中的好处在您干预代码时无济于事带有wordpress的钩子名称。
真正的好处始于使用实际的类实例和非静态函数。这样的好处是您可以开始使用OO原理,并且可以简化代码。静态类函数比实际解决方案更多的是问题。
那么,它不仅仅是语法糖。
关键点是:做一些有助于您编写代码的事情可以轻松处理和维护。不要高估性能,这是一个常见错误。更重要的是,您编写的代码易于阅读和理解,可以满足您的需求。在以下情况下,以下问题或答案可能对大局很有帮助:Multiple Custom Metabox Help。
即使是较小的插件,我也有一种常见的方法是使用静态助手函数来实例化插件,然后其余的则驻留在插件实例中。这有助于封装主要的插件逻辑,并通过使用钩子进行命名间隔以及在钩子之间重新使用私有成员(这是标准全局函数无法实现的)而受益。以下代码示例显示了该模式:
<?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()
{
}
# ...
}
在钩子注册时,此插件对象已经从其设计中受益:您已停止根据具体的插件类名对实际的钩子函数进行硬编码。这是可能的,因为该类已绑定到回调的对象实例。听起来很复杂,只是说:
$this
是插件。可以在钩子回调中使用,将Registering Class方法与钩子回调进行比较。此模式可以简化与wordpress的接口:注入被简化为钩子的名称以及它们提供的数据。然后,您可以开始直接在此插件类中实现或对它重构您的实现,以便仅将代码放到为针对Wordpress定义插件接口的最基本要求,而将通用逻辑放在一边。这是乐趣开始的地方,而且很可能是每个插件作者希望长期实现的目标。所以不要使用worpdress进行编程,而要反对它。由于worpdress非常灵活,因此没有通用或易于描述的程序接口。基本的插件类可以担当此角色,从而为您自己的代码提供更多的灵活性,这将使代码更容易实现并获得更好的性能。
因此,名称间隔不仅有好处。我能给出的最佳建议是:尝试一下。
您不会失去太多,只有发现的新事物。
您在通过了Wordpress的更多主要更新并同时保持插件兼容之后,很可能会注意到差异。 >
注意事项:如果您的插件直接与wordpress集成以完成工作,则使用一个或两个公共功能可能更适合您。选择正确的工具完成工作。
评论
如果静态类函数与全局函数确实没有什么不同,并且您的目标是防止命名空间冲突,那么我真的还不了解(现在)切换为类编写插件的必要性。另外,我对您的助手引导功能感到困惑。为什么不只将新对象声明为$ new_object = new MyClass();?
– AlxVallejo
2012年12月30日17:10
@AlxVallejo:单独命名空间并没有真正的必要(正如我在答案中所写,静态类方法与全局函数几乎相同)。因此,您可以自己进行命名空间设置(即PHP 5.3之前的那种命名空间)。所以您注意到这完全正确。与静态引导程序功能类似:从技术上讲,这是没有必要的,只需简单地返回$ myPlugin = new MyPlugin();即可。也一样。但是,从更大的角度来看,一个简单的新词可能还不够,请比较WordPress插件:如何避免“紧密耦合”?
– hakre
13年1月18日在13:58
#2 楼
类VS函数集性能
常规:Afaik,类和函数集之间的“性能”没有区别。
详细信息:
如果您对
function_exists()
与class_exists()
进行质疑,则存在很大差异,因为通常情况下,您会获得很多函数(wp内核中约为1.800(?))与类(在wp内核中为〜100(?))。因此,使东西“可插拔”并因此质疑其存在与执行时间是有区别的。与功能集相比,类具有一个很大的优势:您可以更轻松地避免在不需要它的请求上调用它,然后与功能。您只需要对类进行条件检查,而不必对每个函数进行条件检查。因此,如果您不需要在每次页面加载时都使用它,并且可以避免调用大量的if / else语句,则该函数“性能会更好”。
体系结构-工作原理:
功能集:通常,功能会在您调用它的行中执行。因此,每次调用某个东西时,如果必须多次调用它,就必须重新编写一次。
上课:上课有不同的方法。最接近功能集的类是“工厂”类(wikipedia / google)。 Imo它与一组函数几乎相同,但是封装在一个类中。但是也有其他“类型”的类。例如,您可以编写一个抽象类或一个父类类,然后再扩展一个子类。在一个真实的示例中:假设您有一个构建一些静态文本字段的类。在您的
__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中,您可能节省了几毫秒的执行时间。个人观点
如果您明智地编写类,那么您将获得次要的优势在性能上。但是您将有一个组织良好的结构来进行工作。到目前为止,没有什么壮观的。但是,如果您考虑以下插件中的类和函数的“拆分”用例,那么您将得到我的最终结论:类是内部的,函数是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>"
注意:请同时阅读Q的注释中张贴的链接@ t310s。
评论
只是好奇,为什么您希望您的插件文件被wordpress包含多次?
– hakre
2011年8月18日,0:34
@hakre我到底在哪里说这个?对不起,妈妈很累。
– kaiser
2011年8月18日在1:36
@kaiser,我想@hakre指的是您开头的if(!class_exists)行?
– jjeaton
11年8月18日在5:32
@hakre我认为@kaiser在进行class_exists检查不是因为它可以被包含一次以上,而是避免与另一个类发生冲突?
– Michal Mau
11年8月18日在16:35
是的,我想知道class_exists。
– hakre
11年8月18日在19:05
#3 楼
对于插件作者而言,这纯粹是一种风格选择。在速度方面没有真正的区别。#4 楼
类通常不会在性能方面提供任何好处,但是它们也很少有负面影响。它们的真正好处是使代码更清晰并避免名称空间冲突。评论
但是,正如@hakre所提到的,在全局函数上使用前缀时,名称空间冲突实际上没有什么不同。在这种情况下,“更干净”的代码和防止名称空间冲突是同义词,不是吗?
– AlxVallejo
2012年12月30日17:18
@AlxVallejo我猜是这样的:)
–互联网
2012年12月30日19:01在
#5 楼
在大多数情况下,如果您使用函数,则会在每个函数名称中放置插件的名称,因此,有效的是,如果插件具有许多功能,则该名称将被重复十几次。 。使用类,您只需在类名中输入一次插件名称即可。
另外,您可以使用继承或其他oo构造以非常干净的方式实现行为。这是一个例子:
class animalplugin{
//plugin functions...
function talk(){print "animalnoise";}
}
class animalplugin_with_cat_mods extends abcplugin{
//cat functions overrides
function talk(){print "meow";}
}
if (iscat()){
new animalplugin_with_cat_mods();
} else {
new animalplugin();
}
评论
PHP问题可能比WordPress问题更多,请查看此Stackoverflow问题是否可以解决您的问题。