我认为在这里不可能给出一个明确的答案,因为这样的选择是个人的偏好。
考虑到以下是我的方法,我不认为这是正确的方法。
我可以肯定的是,你应该避免第三种选择:
仅返回null/false
这在不同方面是不好的:
返回类型一致性使函数更难进行单元测试(if (! is_null($thing))...
) 使代码更难阅读,我经常使用OOP来编写插件,当出现问题时,我的对象方法经常抛出异常。
这样做,我:
实现返回类型一致性使代码易于单元测试不需要对返回的类型进行条件检查,但是,在WordPress插件中引发异常意味着没有任何东西会捕捉到它们,最终导致致命错误not 理想的,尤其是在生产中。
为了避免这个问题,我通常在主插件文件中有一个“主例程”,我将其包装在try
/ catch
块这使我有机会捕获生产中的异常并防止致命错误。
类的粗略示例:
# myplugin/src/Foo.php
namespace MyPlugin;
class Foo {
/**
* @return bool
*/
public function doSomething() {
if ( ! get_option(\'my_plugin_everything_ok\') ) {
throw new SomethingWentWrongException(\'Something went wrong.\');
}
// stuff here...
return true;
}
}
并从主插件文件中使用它:
# myplugin/main-plugin-file.php
namespace MyPlugin;
function initialize() {
try {
$foo = new Foo();
$foo->doSomething();
} catch(SomethingWentWrongException $e) {
// on debug is better to notice when bad things happen
if (defined(\'WP_DEBUG\') && WP_DEBUG) {
throw $e;
}
// on production just fire an action, making exception accessible e.g. for logging
do_action(\'my_plugin_error_shit_happened\', $e);
}
}
add_action(\'wp_loaded\', \'MyPlugin\\\\initialize\');
当然,在现实世界中,您可能会抛出和捕获不同类型的异常,并根据异常表现出不同的行为,但这应该给您一个方向。
我经常使用的另一个选项(您没有提到)是返回包含标志的对象,以验证是否没有发生错误,但保持返回类型的一致性。
这是这样一个对象的粗略示例:
namespace MyPlugin;
class Options {
private $options = [];
private $ok = false;
public function __construct($key)
{
$options = is_string($key) ? get_option($key) : false;
if (is_array($options) && $options) {
$this->options = $options;
$this->ok = true;
}
}
public function isOk()
{
return $this->ok;
}
}
现在,您可以在插件的任何位置执行以下操作:
/**
* @return MyPlugin\\Options
*/
function my_plugin_get_options() {
return new MyPlugin\\Options(\'my_plugin_options\');
}
$options = my_plugin_get_options();
if ($options->isOk()) {
// do stuff
}
注意如何
my_plugin_get_options()
以上始终返回
Options
类,通过这种方式,您可以始终传递返回值,甚至可以将其注入到使用类型提示的其他对象,现在您担心类型不同。
如果函数已返回null
/ false
如果出现错误,在传递之前,您必须检查返回的值是否有效。
同时,您可以清楚地了解option实例是否有问题。
这是一个很好的解决方案,可以使用默认值或任何适合的方法轻松恢复错误。