
Hướng Dẫn Chặn Tự Động Xóa Bài Viết Trong Thùng Rác WordPress
Sơ đồ trang
WordPress có cơ chế tự động xóa các bài viết đã nằm trong thùng rác quá 30 ngày thông qua hằng số EMPTY_TRASH_DAYS
.
Bài viết này sẽ hướng dẫn bạn cách chặn việc tự động xóa này, từ cách đơn giản nhất đến cách nâng cao chỉ áp dụng cho custom post type cụ thể.
Cơ Chế Hoạt Động Của WordPress
1. Hằng Số EMPTY_TRASH_DAYS
WordPress tự động định nghĩa hằng số này với giá trị 30 ngày:
// wp-includes/default-constants.php
if (!defined('EMPTY_TRASH_DAYS'))
define('EMPTY_TRASH_DAYS', 30);
2. Cron Job Hàng Ngày
WordPress lên lịch một sự kiện hàng ngày để xóa các bài viết hết hạn:
// wp-admin/admin.php
if (!wp_next_scheduled('wp_scheduled_delete') && !defined('WP_INSTALLING'))
wp_schedule_event(time(), 'daily', 'wp_scheduled_delete');
3. Meta Field Tracking
Khi bài viết được đưa vào thùng rác, WordPress tạo meta field _wp_trash_meta_time
:
// wp-includes/post.php
function wp_trash_post($post_id = 0) {
// ... mã khác
add_post_meta($post_id, '_wp_trash_meta_time', time());
// ... mã khác
}
Giải Pháp 1: Vô Hiệu Hóa Hoàn Toàn (Đơn Giản)
Phương Pháp A: Sử Dụng wp-config.php
Thêm dòng sau vào file wp-config.php
trước dòng /* That's all, stop editing! */
:
// Vô hiệu hóa hoàn toàn auto-delete trash
define('EMPTY_TRASH_DAYS', 0);
Lưu ý: Cách này sẽ vô hiệu hóa tính năng thùng rác hoàn toàn. Khi xóa bài viết, nó sẽ bị xóa vĩnh viễn ngay lập tức.
Phương Pháp B: Tăng Thời Gian Lên Rất Lớn
// Đặt thời gian xóa thành 365 ngày (1 năm)
define('EMPTY_TRASH_DAYS', 365);
Phương Pháp C: Hủy Cron Job
Thêm vào functions.php
:
Bài viết liên quan
/**
* Vô hiệu hóa tự động xóa thùng rác
*/
function disable_auto_delete_trash() {
wp_clear_scheduled_hook('wp_scheduled_delete');
}
add_action('init', 'disable_auto_delete_trash');
// Ngăn WordPress lên lịch lại
add_filter('schedule_event', function($event) {
if ($event && $event->hook === 'wp_scheduled_delete') {
return false;
}
return $event;
});
Giải Pháp 2: Chặn Chỉ Định Custom Post Type (Nâng Cao)
Đây là giải pháp phức tạp hơn nhưng linh hoạt, cho phép chặn auto-delete chỉ cho custom post type cụ thể (ví dụ: service
).
Bước 1: Tạo Plugin Hoặc Thêm Vào Functions.php
<?php
/**
* Custom Trash Management
* Chặn tự động xóa custom post type 'service' khỏi thùng rác
*/
class CustomTrashManager {
private $protected_post_types = array('service');
public function __construct() {
add_action('init', array($this, 'init'));
}
public function init() {
// Hủy cron job mặc định
$this->disable_default_scheduled_delete();
// Tạo cron job tùy chỉnh
$this->setup_custom_scheduled_delete();
// Hook vào quá trình xóa
add_action('wp_scheduled_delete', array($this, 'custom_scheduled_delete'));
}
/**
* Hủy cron job mặc định của WordPress
*/
private function disable_default_scheduled_delete() {
if (wp_next_scheduled('wp_scheduled_delete')) {
wp_clear_scheduled_hook('wp_scheduled_delete');
}
// Ngăn WordPress lên lịch lại
add_filter('schedule_event', function($event) {
if ($event && $event->hook === 'wp_scheduled_delete') {
return false;
}
return $event;
});
}
/**
* Tạo cron job tùy chỉnh
*/
private function setup_custom_scheduled_delete() {
if (!wp_next_scheduled('custom_scheduled_delete')) {
wp_schedule_event(time(), 'daily', 'custom_scheduled_delete');
}
add_action('custom_scheduled_delete', function() {
do_action('wp_scheduled_delete');
});
}
/**
* Xử lý tùy chỉnh khi chạy wp_scheduled_delete
*/
public function custom_scheduled_delete() {
// Xóa meta field để bảo vệ protected post types
$this->protect_post_types_from_deletion();
}
/**
* Bảo vệ các post type khỏi bị xóa tự động
*/
private function protect_post_types_from_deletion() {
global $wpdb;
foreach ($this->protected_post_types as $post_type) {
$this->remove_trash_meta_for_post_type($post_type);
}
}
/**
* Xóa meta field _wp_trash_meta_time cho post type cụ thể
*/
private function remove_trash_meta_for_post_type($post_type) {
global $wpdb;
$query = $wpdb->prepare("
DELETE pm FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
WHERE p.post_type = %s
AND p.post_status = 'trash'
AND pm.meta_key = '_wp_trash_meta_time'
", $post_type);
$wpdb->query($query);
}
/**
* Thêm post type vào danh sách bảo vệ
*/
public function add_protected_post_type($post_type) {
if (!in_array($post_type, $this->protected_post_types)) {
$this->protected_post_types[] = $post_type;
}
}
/**
* Xóa post type khỏi danh sách bảo vệ
*/
public function remove_protected_post_type($post_type) {
$key = array_search($post_type, $this->protected_post_types);
if ($key !== false) {
unset($this->protected_post_types[$key]);
}
}
}
// Khởi tạo
new CustomTrashManager();
Bước 2: Tùy Chỉnh Danh Sách Post Type Bảo Vệ
/**
* Thêm post type khác vào danh sách bảo vệ
*/
add_action('init', function() {
global $custom_trash_manager;
if (isset($custom_trash_manager)) {
$custom_trash_manager->add_protected_post_type('product');
$custom_trash_manager->add_protected_post_type('testimonial');
}
});
Giải Pháp 3: Sử Dụng Hook Filter (Linh Hoạt)
/**
* Bảo vệ post type cụ thể khỏi auto-delete
*/
function protect_custom_post_types_from_auto_delete() {
global $wpdb;
$protected_types = array('service', 'product', 'portfolio');
foreach ($protected_types as $post_type) {
$wpdb->query($wpdb->prepare("
UPDATE {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
SET pm.meta_value = %d
WHERE p.post_type = %s
AND p.post_status = 'trash'
AND pm.meta_key = '_wp_trash_meta_time'
", time(), $post_type));
}
}
// Chạy trước khi wp_scheduled_delete được thực thi
add_action('wp_scheduled_delete', 'protect_custom_post_types_from_auto_delete', 5);
Giải Pháp 4: Admin Interface (Cho Người Dùng Cuối)
/**
* Tạo trang cài đặt trong Admin
*/
function trash_management_admin_menu() {
add_options_page(
'Quản Lý Thùng Rác',
'Thùng Rác',
'manage_options',
'trash-management',
'trash_management_page'
);
}
add_action('admin_menu', 'trash_management_admin_menu');
function trash_management_page() {
if (isset($_POST['submit'])) {
$protected_types = sanitize_text_field($_POST['protected_types']);
update_option('protected_post_types', $protected_types);
echo '<div class="notice notice-success"><p>Đã lưu cài đặt!</p></div>';
}
$protected_types = get_option('protected_post_types', 'service');
?>
<div class="wrap">
<h1>Quản Lý Thùng Rác</h1>
<form method="post">
<table class="form-table">
<tr>
<th scope="row">Post Types Được Bảo Vệ</th>
<td>
<input type="text" name="protected_types" value="<?php echo esc_attr($protected_types); ?>" class="regular-text" />
<p class="description">Nhập các post type cách nhau bằng dấu phẩy. Ví dụ: service,product,portfolio</p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
Giải Pháp 5: Sử Dụng Plugin
Plugins Khuyến Nghị:
- WP-Sweep: Quản lý việc dọn dẹp database bao gồm trash
- Advanced Database Cleaner: Có thể cấu hình cho từng post type
- WP Reset: Có tùy chọn quản lý thùng rác chi tiết
Kiểm Tra Và Debug
Kiểm Tra Cron Job:
/**
* Hiển thị thông tin cron job
*/
function check_trash_cron_status() {
$next_run = wp_next_scheduled('wp_scheduled_delete');
$custom_next_run = wp_next_scheduled('custom_scheduled_delete');
echo "WordPress scheduled delete: " . ($next_run ? date('Y-m-d H:i:s', $next_run) : 'Not scheduled') . "\n";
echo "Custom scheduled delete: " . ($custom_next_run ? date('Y-m-d H:i:s', $custom_next_run) : 'Not scheduled') . "\n";
}
Kiểm Tra Meta Fields:
/**
* Hiển thị bài viết trong trash với meta time
*/
function list_trash_posts_with_meta() {
global $wpdb;
$results = $wpdb->get_results("
SELECT p.ID, p.post_title, p.post_type, pm.meta_value as trash_time
FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_status = 'trash'
AND pm.meta_key = '_wp_trash_meta_time'
ORDER BY p.post_type, p.post_title
");
foreach ($results as $post) {
echo "ID: {$post->ID}, Title: {$post->post_title}, Type: {$post->post_type}, Trash Time: " . date('Y-m-d H:i:s', $post->trash_time) . "\n";
}
}
Lưu Ý Quan Trọng
- Backup: Luôn backup database trước khi thực hiện thay đổi
- Testing: Kiểm tra trên staging site trước khi áp dụng lên production
- Performance: Các giải pháp phức tạp có thể ảnh hưởng đến hiệu suất
- Maintenance: Cần quản lý thùng rác thủ công nếu vô hiệu hóa auto-delete
- Updates: Kiểm tra tính tương thích khi cập nhật WordPress
Kết Luận
Tùy theo nhu cầu cụ thể, bạn có thể chọn:
- Giải pháp 1: Đơn giản, áp dụng cho toàn bộ site
- Giải pháp 2: Phức tạp nhưng linh hoạt, chỉ áp dụng cho post type cụ thể
- Giải pháp 3: Cân bằng giữa đơn giản và linh hoạt
- Giải pháp 4: Thân thiện với người dùng cuối
- Giải pháp 5: Sử dụng plugin có sẵn
Hãy chọn giải pháp phù hợp với kỹ năng và yêu cầu của bạn.
Bạn có thể yêu cầu thêm bài viết tại đây