WordPress 代码就要满屏的错误处理吗?

科技1年前 (2023)发布 iowen
213 0 0

我们知道 WordPress 的函数在失败的时候是不会抛出异常的,因为 WordPress 在 PHP 4 的时候就创建了,那时候 PHP 语法结构还没有 try/catch 异常处理机制。

WP_Error 错误处理机制


取而代之,WordPress 在失败的时候,返回返回一个WP_Error对象,比如插入文章的函数 wp_insert_post ,如果文章标题,内容摘要都为空的时候,就会插入失败,会返回 WP_Error 对象。

WP_Error 对象错误对象和异常很类似,也有一个错误代码和错误信息,比如上面的错误,返回 WP_Error 对象的错误代码就是 empty_content,错误信息是:内容,标题和摘要为空。

WordPress 还提供了 is_wp_error 函数,用于判断接受到数据是不是 WP_Error 对象,这样我们在写代码的时候,就需要自己判断返回值是不是 WP_Error 对象,然后进行额外处理,举个例子,WPJAM Basic 的快速复制扩展功能的代码:

function wpjam_duplicate_post($post_id){
// 获取旧文章信息,并插入新文章
$post_arr = get_post($post_id, ARRAY_A);
$new_post_id = wp_inssert_post($post_arr, $wp_error=true);

if(is_wp_error($new_post_id)){ // 如果失败,返回错误
return $new_post_id;
}

// 获取旧文章的分类信息,并将同样的分类信息设置到新的文章中
foreach(get_object_taxonomies($post_arr['post_type']) as $taxonomy){
$terms = wp_get_object_terms($post_id, $taxonomy, ['fields' => 'ids']);
$result = wp_set_object_terms($new_post_id, $terms, $taxonomy);

if(is_wp_error($result)){ // 如果失败,返回错误
return $result;
}
}

// 假如还有其他操作
$result = other_post_function($new_post_id, $args);

if(is_wp_error($result)){ // 如果失败,返回错误
return $result;
}

return $new_post_id; // 最后才返回复制成功的文章 ID
}

上面的代码我为了方便演示,做了一些简化,留下大致的骨架,可以看出快速复制文章有三个过程,注释里面已经写的非常清楚,下面简单说一下

  1. 获取旧文章信息,并插入新文章,如果 WP_Error 对象,则直接返回。

  2. 获取旧文章的分类信息,并将同样的分类信息设置到新的文章中,同样碰到 WP_Error 对象,则直接返回

  3. 最后假设还有其他操作,同样也要处理错误。

这样的代码给人感觉就是满屏的错误处理,非常难受。

使用 Try / Catch 异常处理机制


有没有办法优化我们的代码呢?可以把 WP_Error 对象转换成 PHP 异常继承类的对象,然后使用现代 PHP 的 Try / Catch 异常处理机制来优化。

首先创建用于处理 WP_Error 对象的异常处理类:

class WPJAM_Exception extends Exception{
private $wp_error = null;

public function __construct($message, $code=0, Throwable $previous=null){
if(is_wp_error($message)){
$this->wp_error = $message;

$message = $this->wp_error->get_error_message();
$code = $this->wp_error->get_error_code();
}else{
$this->wp_error = new WP_Error($code, $message);
}

parent::__construct($message, 0, $previous);
}

public function get_wp_error(){
return $this->wp_error;
}
}

创建一个高阶函数 wpjam_try,自动将 WP_Error 对象转换成异常:

function wpjam_try($callback, ...$args){
try{
$result = call_user_func_array($callback, $args);

if(is_wp_error($result)){
throw new WPJAM_Exception($result);
}

return $result;
}catch(Exception $e){
throw $e;
}
}

最后我们就可以使用 wpjam_try 对上面复制文章这段代码进行改造了

function wpjam_duplicate_post($post_id){
try{
// 获取旧文章信息,并插入新文章
$post_arr = get_post($post_id, ARRAY_A);
$new_post_id = wpjam_try('wp_inssert_post', $post_arr, $wp_error=true);

// 获取旧文章的分类信息,并将同样的分类信息设置到新的文章中
foreach(get_object_taxonomies($post_arr['post_type']) as $taxonomy){
$terms = wp_get_object_terms($post_id, $taxonomy, ['fields' => 'ids']);
$result = wpjam_try('wp_set_object_terms', $new_post_id, $terms, $taxonomy);
}

// 假如还有其他操作
$result = wpjam_try('other_post_function', $new_post_id, $args);

return $new_post_id; // 最后才返回复制成功的文章 ID
}catch(WPJAM_Exception $e){
if($exception){
throw $e;
}else{
return $e->get_wp_error();
}
}
}

改造的过程分成三步:

  1. 把会返回 WP_Error 对象的函数,通过 wpjam_try 调用。

  2. 去掉所有 is_wp_error 的判断,因为 wpjam_try 会抛出异常。

  3. 将所有代码放到 try/catch 的结构中,最后只需要捕捉异常,再将异常转换成 WP_Error 对象即可。

这样就可以在 WordPress 写代码的时候,避免满屏幕的错误处理,最后返回还是 WP_Error 对象,保证了对原来逻辑的兼容。



点击卡片关注「WordPress果酱」 
每天分享 WordPress 使用技巧 

⏬⏬ 下载 WPJAM Basic 请点击阅读原文

© 版权声明

相关文章

暂无评论

暂无评论...