Giới Thiệu User Cleanup Tool – Tiện Ích Xoá Người Dùng Không Cần Thiết Trên WHMCS

19 Tháng 6, 2025

Trong quá trình vận hành hệ thống WHMCS, việc có hàng trăm đến hàng nghìn tài khoản khách hàng không còn sử dụng, không có dịch vụ hoặc chỉ đăng ký thử nghiệm là điều không thể tránh khỏi. Điều này không chỉ làm cơ sở dữ liệu trở nên cồng kềnh, mà còn gây khó khăn trong việc quản lý, tìm kiếm và báo cáo.

Đó là lý do GizaData phát triển công cụ User Cleanup Tool – một addon tiện ích, giúp lọc và xoá nhanh những người dùng không còn liên quan chỉ với vài thao tác.


✅ Tính Năng Nổi Bật

1. Hiển thị danh sách toàn bộ khách hàng

Addon sẽ tự động liệt kê tất cả các khách hàng trong hệ thống WHMCS. Bạn có thể:

  • Tìm kiếm theo tên hoặc email
  • Tuỳ chỉnh số lượng kết quả hiển thị trên mỗi trang (10, 20, 50, 100…)

2. Đánh dấu & chọn nhiều người dùng để xoá

Giao diện hiển thị rõ ràng:

  • ✅ Checkbox chọn từng khách hàng
  • 📌 Xem được ID, họ tên, email và số lượng dịch vụ đang có

3. Tự động xoá toàn bộ dữ liệu liên quan

Chỉ với một cú click, addon sẽ xoá sạch các dữ liệu liên quan đến khách hàng được chọn:

  • Thông tin khách hàng (tblclients)
  • Dịch vụ đang có (tblhosting)
  • Đơn hàng (tblorders)
  • Hóa đơn & chi tiết hóa đơn (tblinvoices, tblinvoiceitems)
  • Email liên hệ, ghi chú, ticket, tên miền
  • Thông tin liên kết với người dùng đăng nhập (tblusers, tbluserclients)

⚠️ Lưu ý: Tính năng này không ảnh hưởng đến dịch vụ thật sự đang chạy như VPS hoặc hosting đã được tạo trên các nền tảng ngoài (Virtualizor, DirectAdmin, v.v.). Tuy nhiên, WHMCS sẽ không còn ghi nhận các dịch vụ đó sau khi khách hàng bị xoá.


🛡️ Tính Bảo Vệ – Không Xoá Người Dùng Đang Sử Dụng

Addon có thể được mở rộng để chỉ xoá khách hàng không có dịch vụ, tránh ảnh hưởng đến những tài khoản vẫn đang hoạt động.

Bạn có thể bổ sung logic kiểm tra trước khi xoá

$hostingCount = Capsule::table('tblhosting')->where('userid', $id)->count();
if ($hostingCount === 0) {
    // Tiến hành xoá
}

🧩 Dễ Dàng Cài Đặt & Tùy Biến

  • File PHP độc lập, dễ dàng chèn vào thư mục modules/addons/usercleanup
  • Tương thích tốt với WHMCS mới và cũ (kiểm tra bảng tbluserclients nếu có)
  • Có thể tích hợp thêm tính năng lọc tự động, nhật ký xoá, xác nhận từng bước…

📌 Kết Luận

User Cleanup Tool là giải pháp tối ưu dành cho các quản trị viên WHMCS muốn:

  • Giữ hệ thống gọn gàng, hiệu suất cao
  • Xoá nhanh khách hàng không còn sử dụng
  • Đảm bảo không làm gián đoạn dịch vụ đang chạy

Hãy trải nghiệm ngay hôm nay để tăng hiệu quả quản trị hệ thống WHMCS của bạn!

Full code

<?php
if (!defined("WHMCS")) {
    die("This file cannot be accessed directly");
}

use WHMCS\Database\Capsule;

function usercleanup_config() {
    return [
        "name" => "User Cleanup Tool",
        "description" => "Hiển thị danh sách người dùng và xóa những người dùng được chọn.",
        "version" => "1.2",
        "author" => "GizaData",
        "fields" => []
    ];
}

function usercleanup_output($vars) {
    // Xử lý xóa trước khi render giao diện
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['delete_ids']) && is_array($_POST['delete_ids'])) {
        foreach ($_POST['delete_ids'] as $id) {
            Capsule::table('tblhosting')->where('userid', $id)->delete();
            Capsule::table('tblorders')->where('userid', $id)->delete();
            Capsule::table('tblinvoices')->where('userid', $id)->delete();
            Capsule::table('tblinvoiceitems')->where('userid', $id)->delete();
            Capsule::table('tblemails')->where('userid', $id)->delete();
            Capsule::table('tblnotes')->where('userid', $id)->delete();
            Capsule::table('tbldomains')->where('userid', $id)->delete();
            Capsule::table('tbltickets')->where('userid', $id)->delete();
            $client = Capsule::table('tblclients')->where('id', $id)->first();
            $email = $client ? $client->email : null;
            Capsule::table('tblclients')->where('id', $id)->delete();
            if ($email) {
                $user = Capsule::table('tblusers')->where('email', $email)->first();
                if ($user) {
                    if (Capsule::schema()->hasTable('tbluserclients')) {
                        $userClientCount = Capsule::table('tbluserclients')->where('auth_user_id', $user->id)->count();
                        if ($userClientCount <= 1) {
                            Capsule::table('tbluserclients')->where('auth_user_id', $user->id)->delete();
                            Capsule::table('tblusers')->where('id', $user->id)->delete();
                        }
                    } else {
                        Capsule::table('tblusers')->where('id', $user->id)->delete();
                    }
                }
            }

        }
        echo '<div style="color:green; font-weight:bold; margin-bottom:10px">✔ Đã xoá ' . count($_POST['delete_ids']) . ' khách hàng và người dùng liên quan.</div>';
        echo '<meta http-equiv="refresh" content="2">';
        return;
    }

    $limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 10;
    $page = isset($_GET['page']) ? (int) $_GET['page'] : 1;
    $offset = ($page - 1) * $limit;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';

    $query = Capsule::table('tblclients');
    if ($search !== '') {
        $query->where(function ($q) use ($search) {
            $q->where('firstname', 'like', "%$search%")
              ->orWhere('lastname', 'like', "%$search%")
              ->orWhere('email', 'like', "%$search%");
        });
    }

    $totalClients = $query->count();
    $clients = $query->skip($offset)->take($limit)->get();

    echo '<style>
        form.usercleanup-wrapper { font-family: sans-serif; }
        form.usercleanup-wrapper table { border-collapse: collapse; width: 100%; margin-top: 10px; }
        form.usercleanup-wrapper th, form.usercleanup-wrapper td { border: 1px solid #ccc; padding: 8px; text-align: left; }
        form.usercleanup-wrapper th { background-color: #f4f4f4; }
        form.usercleanup-wrapper input[type="text"] { padding: 6px; width: 250px; }
        form.usercleanup-wrapper select, form.usercleanup-wrapper button { padding: 6px 10px; margin-left: 10px; }
    </style>';

    echo '<form method="get" class="usercleanup-wrapper">
        <input type="hidden" name="module" value="usercleanup" />
        <input type="text" name="search" value="' . htmlspecialchars($search) . '" placeholder="Tìm theo tên hoặc email..." />
        <button type="submit">Tìm kiếm</button>
        <label>Hiển thị:</label>
        <select name="limit" onchange="this.form.submit()">';

    foreach ([10, 20, 50, 100, 200, 500] as $opt) {
        $selected = ($limit == $opt) ? ' selected' : '';
        echo "<option value='$opt'$selected>$opt</option>";
    }

    echo '</select>';
    echo '</form>';


    echo '<form method="post" class="usercleanup-wrapper">
        <h2>Danh sách khách hàng</h2>
        <button type="submit" name="delete" onclick="return confirm(\'Xoá những khách hàng đã chọn?\')">Xóa đã chọn</button>
        <table>
        <tr><th><input type="checkbox" id="checkAll"></th><th>ID</th><th>Tên</th><th>Email</th><th>Số dịch vụ</th></tr>';

    foreach ($clients as $client) {
        $hostingCount = Capsule::table('tblhosting')->where('userid', $client->id)->count();
        echo "<tr>
            <td><input type='checkbox' name='delete_ids[]' value='{$client->id}'></td>
            <td>{$client->id}</td>
            <td>{$client->firstname} {$client->lastname}</td>
            <td>{$client->email}</td>
            <td>$hostingCount</td>
        </tr>";
    }

    echo '</table>
    </form>';

    echo <<<HTML
    <script>
    document.getElementById("checkAll").addEventListener("click", function() {
        var checkboxes = document.querySelectorAll("input[name='delete_ids[]']");
        checkboxes.forEach(function(cb) {
            cb.checked = this.checked;
        }, this);
    });
    </script>
    HTML;

}

Blog ..

Hướng dẫn dịch vụ ..

Sản phẩm nổi bật

dịch vụ chất lượng khách hàng tin tưởng

NVMe VPS

Tốc độ cao và bảo mật

Xem thêm

SSD VPS

Hiệu năng và tối ưu chi phí

Xem thêm

Proxy

Ẩn danh và mượt mà

Xem thêm

NVMe Hosting

Ổn định và tiện dụng

Xem thêm