一、核心判断方法
1. 通过 ID 判断(推荐)
/**
* 判断文章是否存在
* @param int $post_id 文章ID
* @return bool
*/
function post_exists_by_id($post_id) {
// 方法1:使用 get_post_status()
$status = get_post_status($post_id);
return $status && $status !== false && $status !== 'trash';
// 方法2:使用 get_post()
$post = get_post($post_id);
return !is_null($post) && $post->post_type !== 'revision';
// 方法3:使用 get_post_type()
$post_type = get_post_type($post_id);
return $post_type && $post_type !== false;
// 方法4:使用 is_numeric() 和 get_post_status() 的组合
if (!is_numeric($post_id) || $post_id <= 0) {
return false;
}
$post = get_post($post_id);
return ($post instanceof WP_Post) && $post->post_status !== 'trash';
}
2. 通过标题/内容判断
/**
* 通过标题判断文章是否存在
* @param string $title 文章标题
* @param string $post_type 文章类型
* @return int|false 文章ID或false
*/
function post_exists_by_title($title, $post_type = 'post') {
global $wpdb;
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts}
WHERE post_title = %s
AND post_type = %s
AND post_status IN ('publish', 'draft', 'pending', 'future')
LIMIT 1",
$title,
$post_type
);
$post_id = $wpdb->get_var($sql);
return $post_id ? (int) $post_id : false;
}
/**
* 通过内容判断文章是否存在
* @param string $content 文章内容
* @param string $post_type 文章类型
* @return int|false
*/
function post_exists_by_content($content, $post_type = 'post') {
global $wpdb;
$content_hash = md5($content);
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts}
WHERE MD5(post_content) = %s
AND post_type = %s
LIMIT 1",
$content_hash,
$post_type
);
$post_id = $wpdb->get_var($sql);
return $post_id ? (int) $post_id : false;
}
二、综合判断函数
1. 完整的存在性检查
/**
* 完整检查文章是否存在
* @param mixed $identifier 文章ID、标题或对象
* @param string $post_type 文章类型
* @param string $status 文章状态
* @return int|false 文章ID或false
*/
function post_exists_extended($identifier, $post_type = 'post', $status = 'any') {
// 如果已经是文章对象
if ($identifier instanceof WP_Post) {
return $identifier->ID;
}
// 如果是数字,按ID处理
if (is_numeric($identifier)) {
$post_id = (int) $identifier;
$post = get_post($post_id);
if (!$post || $post->post_type !== $post_type) {
return false;
}
if ($status !== 'any' && $post->post_status !== $status) {
return false;
}
return $post_id;
}
// 如果是字符串,按标题或别名处理
if (is_string($identifier)) {
global $wpdb;
// 尝试通过标题查找
$sql = $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts}
WHERE (post_title = %s OR post_name = %s)
AND post_type = %s",
$identifier,
sanitize_title($identifier),
$post_type
);
if ($status !== 'any') {
$sql .= $wpdb->prepare(" AND post_status = %s", $status);
} else {
$sql .= " AND post_status IN ('publish', 'draft', 'pending', 'future')";
}
$sql .= " LIMIT 1";
$post_id = $wpdb->get_var($sql);
return $post_id ? (int) $post_id : false;
}
return false;
}
2. 带缓存的判断
/**
* 带缓存的文章存在性检查
* @param int $post_id
* @return bool
*/
function cached_post_exists($post_id) {
$cache_key = 'post_exists_' . $post_id;
$exists = wp_cache_get($cache_key, 'posts');
if ($exists === false) {
$status = get_post_status($post_id);
$exists = ($status && $status !== false && $status !== 'trash');
wp_cache_set($cache_key, $exists, 'posts', 3600); // 缓存1小时
}
return $exists;
}
/**
* 批量检查多个文章是否存在
* @param array $post_ids
* @return array
*/
function batch_check_posts_exist($post_ids) {
$result = array();
$to_check = array();
// 先尝试从缓存获取
foreach ($post_ids as $post_id) {
$cache_key = 'post_exists_' . $post_id;
$cached = wp_cache_get($cache_key, 'posts');
if ($cached !== false) {
$result[$post_id] = $cached;
} else {
$to_check[] = $post_id;
}
}
// 检查未缓存的文章
if (!empty($to_check)) {
global $wpdb;
$ids_string = implode(',', array_map('intval', $to_check));
$sql = "SELECT ID, post_status FROM {$wpdb->posts}
WHERE ID IN ({$ids_string})
AND post_status != 'trash'";
$posts = $wpdb->get_results($sql);
$existing_ids = wp_list_pluck($posts, 'ID');
foreach ($to_check as $post_id) {
$exists = in_array($post_id, $existing_ids);
$result[$post_id] = $exists;
wp_cache_set('post_exists_' . $post_id, $exists, 'posts', 3600);
}
}
return $result;
}
三、在模板中的使用方法
1. 在主题文件中使用
<?php
// 方法1:在文章详情页
if (is_single()) {
global $post;
if (isset($post->ID) && get_post_status($post->ID)) {
// 文章存在,正常显示
the_content();
} else {
// 文章不存在
get_template_part('template-parts/content', 'none');
}
}
// 方法2:判断指定文章
$post_id = 123;
if (post_exists_by_id($post_id)) {
$post = get_post($post_id);
setup_postdata($post);
the_title();
the_content();
wp_reset_postdata();
} else {
echo '文章不存在或已被删除';
}
// 方法3:在循环中判断
if (have_posts()) {
while (have_posts()) {
the_post();
$current_post_id = get_the_ID();
// 确保文章存在且不是垃圾箱中的
if (get_post_status($current_post_id) === 'publish') {
get_template_part('template-parts/content', get_post_format());
}
}
} else {
get_template_part('template-parts/content', 'none');
}
?>
2. 在页面模板中
<?php
/**
* 页面模板:显示特定文章
*/
$page_title = '关于我们';
// 通过标题查找页面
$page_id = post_exists_by_title($page_title, 'page');
if ($page_id) {
$page = get_post($page_id);
setup_postdata($page);
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<h1 class="entry-title"><?php the_title(); ?></h1>
</header>
<div class="entry-content">
<?php the_content(); ?>
</div>
</article>
<?php
wp_reset_postdata();
} else {
// 页面不存在,创建或显示错误
echo '<div class="alert alert-warning">页面未找到</div>';
}
?>
四、在函数/插件中使用
1. 创建文章前检查
/**
* 创建或更新文章
*/
function create_or_update_post($data) {
$post_data = array(
'post_title' => sanitize_text_field($data['title']),
'post_content' => wp_kses_post($data['content']),
'post_type' => 'post',
'post_status' => 'draft',
'meta_input' => array(
'custom_field' => $data['custom_field']
)
);
// 检查是否已存在
$existing_id = post_exists_by_title($data['title']);
if ($existing_id) {
// 更新现有文章
$post_data['ID'] = $existing_id;
$post_data['post_status'] = get_post_status($existing_id);
$result = wp_update_post($post_data, true);
if (is_wp_error($result)) {
error_log('更新文章失败: ' . $result->get_error_message());
return false;
}
return $existing_id;
} else {
// 创建新文章
$result = wp_insert_post($post_data, true);
if (is_wp_error($result)) {
error_log('创建文章失败: ' . $result->get_error_message());
return false;
}
return $result;
}
}
2. 批量导入检查
/**
* 批量导入文章,避免重复
*/
function import_posts_batch($posts_data) {
$results = array(
'created' => 0,
'updated' => 0,
'skipped' => 0,
'errors' => array()
);
foreach ($posts_data as $index => $post_data) {
// 检查必须字段
if (empty($post_data['title']) || empty($post_data['content'])) {
$results['skipped']++;
$results['errors'][] = "第 {$index} 行:缺少标题或内容";
continue;
}
// 检查是否已存在(通过标题)
$existing_id = post_exists_by_title($post_data['title']);
if ($existing_id) {
// 更新逻辑
$post_data['ID'] = $existing_id;
$post_id = wp_update_post($post_data, true);
$results['updated']++;
} else {
// 创建逻辑
$post_id = wp_insert_post($post_data, true);
$results['created']++;
}
if (is_wp_error($post_id)) {
$results['errors'][] = "文章 '{$post_data['title']}' 错误: " . $post_id->get_error_message();
}
}
return $results;
}
五、REST API 中判断
1. REST API 端点
/**
* 注册自定义 REST API 端点检查文章是否存在
*/
add_action('rest_api_init', function() {
register_rest_route('myplugin/v1', '/post-exists/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'check_post_exists_api',
'permission_callback' => '__return_true',
'args' => array(
'id' => array(
'validate_callback' => function($param) {
return is_numeric($param);
}
),
),
));
register_rest_route('myplugin/v1', '/post-exists-by-title', array(
'methods' => 'POST',
'callback' => 'check_post_exists_by_title_api',
'permission_callback' => function() {
return current_user_can('edit_posts');
},
));
});
function check_post_exists_api(WP_REST_Request $request) {
$post_id = (int) $request['id'];
if (!post_exists_by_id($post_id)) {
return new WP_REST_Response(array(
'exists' => false,
'message' => '文章不存在'
), 404);
}
$post = get_post($post_id);
return new WP_REST_Response(array(
'exists' => true,
'data' => array(
'id' => $post->ID,
'title' => $post->post_title,
'status' => $post->post_status,
'type' => $post->post_type,
'link' => get_permalink($post)
)
), 200);
}
function check_post_exists_by_title_api(WP_REST_Request $request) {
$parameters = $request->get_json_params();
$title = sanitize_text_field($parameters['title'] ?? '');
$post_type = sanitize_text_field($parameters['post_type'] ?? 'post');
if (empty($title)) {
return new WP_Error('missing_title', '标题不能为空', array('status' => 400));
}
$post_id = post_exists_by_title($title, $post_type);
return new WP_REST_Response(array(
'exists' => (bool) $post_id,
'post_id' => $post_id,
'title' => $title
), 200);
}
2. AJAX 检查
/**
* AJAX 检查文章是否存在
*/
add_action('wp_ajax_check_post_exists', 'ajax_check_post_exists');
add_action('wp_ajax_nopriv_check_post_exists', 'ajax_check_post_exists');
function ajax_check_post_exists() {
// 验证 nonce
if (!check_ajax_referer('post_exists_nonce', 'nonce', false)) {
wp_die('安全验证失败', 403);
}
$post_id = isset($_POST['post_id']) ? (int) $_POST['post_id'] : 0;
$title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
$response = array('success' => false);
if ($post_id > 0) {
$exists = post_exists_by_id($post_id);
$response = array(
'success' => true,
'exists' => $exists,
'method' => 'by_id',
'id' => $post_id
);
} elseif (!empty($title)) {
$post_id = post_exists_by_title($title);
$response = array(
'success' => true,
'exists' => (bool) $post_id,
'method' => 'by_title',
'post_id' => $post_id,
'title' => $title
);
} else {
$response['message'] = '缺少参数';
}
wp_send_json($response);
}
// 前端 JavaScript
jQuery(document).ready(function($) {
$('#check-post').on('click', function() {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'check_post_exists',
nonce: post_exists_vars.nonce,
post_id: $('#post_id').val(),
title: $('#post_title').val()
},
success: function(response) {
if (response.success) {
if (response.exists) {
alert('文章存在!ID: ' + response.post_id);
} else {
alert('文章不存在');
}
}
}
});
});
});
六、性能优化版本
1. 优化的批量检查
/**
* 高性能的文章存在性批量检查
*/
class Post_Existence_Checker {
private static $instance = null;
private $cache_group = 'post_exists';
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 批量检查文章是否存在
* @param array $post_ids
* @return array
*/
public function batch_check(array $post_ids) {
if (empty($post_ids)) {
return array();
}
$results = array();
$uncached_ids = array();
// 第一步:尝试从缓存获取
foreach ($post_ids as $post_id) {
$cached = wp_cache_get($post_id, $this->cache_group);
if (false !== $cached) {
$results[$post_id] = $cached;
} else {
$uncached_ids[] = (int) $post_id;
}
}
// 第二步:查询未缓存的项目
if (!empty($uncached_ids)) {
global $wpdb;
$ids_string = implode(',', $uncached_ids);
$sql = "SELECT ID, post_status FROM {$wpdb->posts}
WHERE ID IN ({$ids_string})";
$posts = $wpdb->get_results($sql);
// 构建存在性映射
$existing_ids = array();
foreach ($posts as $post) {
$existing_ids[$post->ID] = ($post->post_status !== 'trash');
}
// 处理结果并缓存
foreach ($uncached_ids as $post_id) {
$exists = isset($existing_ids[$post_id]) && $existing_ids[$post_id];
$results[$post_id] = $exists;
wp_cache_set($post_id, $exists, $this->cache_group, 3600);
}
}
return $results;
}
/**
* 通过多个标题检查
* @param array $titles
* @param string $post_type
* @return array
*/
public function batch_check_by_titles(array $titles, $post_type = 'post') {
if (empty($titles)) {
return array();
}
global $wpdb;
$placeholders = array_fill(0, count($titles), '%s');
$placeholders_string = implode(',', $placeholders);
$sql = $wpdb->prepare(
"SELECT ID, post_title FROM {$wpdb->posts}
WHERE post_title IN ($placeholders_string)
AND post_type = %s
AND post_status IN ('publish', 'draft', 'pending', 'future')",
array_merge($titles, array($post_type))
);
$results = $wpdb->get_results($sql);
$mapping = array();
foreach ($results as $row) {
$mapping[$row->post_title] = (int) $row->ID;
}
return $mapping;
}
}
// 使用示例
$checker = Post_Existence_Checker::get_instance();
$post_ids = array(1, 2, 3, 999);
$exists_map = $checker->batch_check($post_ids);
七、使用场景和最佳实践
1. 不同场景的选择
// 场景1:前端显示 - 使用 get_post(),简单快速
$post = get_post($post_id);
if ($post && $post->post_status === 'publish') {
// 显示文章
}
// 场景2:导入/同步 - 使用数据库查询,避免重复
global $wpdb;
$exists = $wpdb->get_var($wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'post'",
$title
));
// 场景3:后台管理 - 使用 get_post_status(),包含状态检查
$status = get_post_status($post_id);
if ($status && $status !== 'trash') {
// 可操作
}
// 场景4:高性能批量处理 - 使用自定义缓存类
$checker = Post_Existence_Checker::get_instance();
$results = $checker->batch_check(array(1, 2, 3, 4, 5));
2. 错误处理
function safely_get_post($post_id) {
try {
if (!is_numeric($post_id) || $post_id <= 0) {
throw new Exception('无效的文章ID');
}
$post = get_post($post_id);
if (!$post) {
throw new Exception('文章不存在');
}
if ($post->post_status === 'trash') {
throw new Exception('文章已在回收站');
}
if (!in_array($post->post_status, array('publish', 'draft', 'pending', 'future'))) {
throw new Exception('文章状态不可用: ' . $post->post_status);
}
return $post;
} catch (Exception $e) {
error_log('获取文章失败: ' . $e->getMessage());
return null;
}
}
// 使用
$post = safely_get_post(123);
if ($post) {
setup_postdata($post);
the_title();
wp_reset_postdata();
}
八、实用工具函数汇总
/**
* 判断文章是否存在的工具函数集合
*/
// 1. 基础判断
function wp_post_exists($post_id) {
return get_post_status($post_id) !== false;
}
// 2. 判断是否可访问
function wp_post_accessible($post_id) {
$status = get_post_status($post_id);
return in_array($status, array('publish', 'private', 'future'));
}
// 3. 判断是否已发布
function wp_post_is_published($post_id) {
return get_post_status($post_id) === 'publish';
}
// 4. 获取安全文章
function wp_get_safe_post($post_id) {
$post = get_post($post_id);
return ($post && $post->post_status !== 'trash') ? $post : null;
}
// 5. 批量获取安全文章
function wp_get_safe_posts($post_ids) {
$posts = get_posts(array(
'post__in' => array_map('intval', $post_ids),
'post_status' => array('publish', 'draft', 'pending', 'future'),
'posts_per_page' => -1,
'orderby' => 'post__in'
));
$result = array();
foreach ($posts as $post) {
$result[$post->ID] = $post;
}
return $result;
}
总结建议
安全考虑:检查用户权限,验证输入数据
前端显示:使用 get_post()+ 状态检查
批量处理:使用自定义的带缓存批量检查
导入/同步:使用数据库直接查询
性能优先:合理使用缓存,避免重复查询
错误处理:始终验证返回值,添加适当的错误处理


湘公网安备43020002000238