Technical Guides January 13, 2026 Admin

WHMCS Module Development Tutorial 2026: Build Your First Module

WHMCS Module Development Tutorial 2026: Build Your First Module

WHMCS Module Development Tutorial 2026: Build Your First Module

Learn how to develop WHMCS modules from scratch in this comprehensive 2026 tutorial. We'll cover module structure, database operations, admin interfaces, and deployment best practices.

Introduction to WHMCS Module Development

WHMCS modules extend functionality without modifying core files. Types of modules include:

  • Addon Modules: Additional features and tools
  • Server Modules: Integration with hosting panels
  • Gateway Modules: Payment processing
  • Registrar Modules: Domain registration

Prerequisites

  • PHP knowledge (OOP, PDO, namespaces)
  • WHMCS installation for testing
  • Text editor or IDE
  • Basic understanding of databases

Module Structure

Basic Directory Structure

your_module/
├── your_module.php (main module file)
├── admin/
│   └── index.php (admin interface)
├── client/
│   └── index.php (client area)
├── includes/
│   └── functions.php (helper functions)
└── templates/
    ├── admin.tpl (admin template)
    └── client.tpl (client template)

Step 1: Create Module File

Basic Addon Module Structure

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

function your_module_config() {
    return array(
        "name" => "Your Module Name",
        "description" => "Module description",
        "version" => "1.0",
        "author" => "Your Name",
        "language" => "english",
        "fields" => array(
            "option1" => array(
                "FriendlyName" => "Option 1",
                "Type" => "text",
                "Size" => "25",
                "Description" => "Enter option 1 value"
            )
        )
    );
}

function your_module_activate() {
    // Create database tables
    $query = "CREATE TABLE IF NOT EXISTS `mod_your_module` (
        `id` INT(11) NOT NULL AUTO_INCREMENT,
        `setting` VARCHAR(255) NOT NULL,
        `value` TEXT,
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
    
    full_query($query);
    
    return array("status" => "success", "description" => "Module activated successfully");
}

function your_module_deactivate() {
    // Optional: Clean up on deactivation
    return array("status" => "success", "description" => "Module deactivated");
}

function your_module_output($vars) {
    // Client area output
    return "<p>Welcome to Your Module</p>";
}

function your_module_clientarea($vars) {
    // Client area function
    return array(
        "pagetitle" => "Your Module",
        "breadcrumb" => array("Your Module" => ""),
        "templatefile" => "client",
        "vars" => array(
            "message" => "Hello from Your Module"
        )
    );
}

function your_module_adminarea($vars) {
    // Admin area function
    return array(
        "pagetitle" => "Your Module Admin",
        "breadcrumb" => array("Your Module" => ""),
        "templatefile" => "admin",
        "vars" => array()
    );
}
?>

Step 2: Database Operations

Creating Tables

function your_module_activate() {
    $query = "CREATE TABLE IF NOT EXISTS `mod_your_module_data` (
        `id` INT(11) NOT NULL AUTO_INCREMENT,
        `user_id` INT(11) NOT NULL,
        `data` TEXT,
        `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`),
        KEY `user_id` (`user_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
    
    full_query($query);
    
    return array("status" => "success");
}

Using Capsule (WHMCS Database Class)

use WHMCS\Database\Capsule;

// Insert data
Capsule::table("mod_your_module_data")->insert([
    "user_id" => $userid,
    "data" => $data
]);

// Query data
$results = Capsule::table("mod_your_module_data")
    ->where("user_id", $userid)
    ->get();

// Update data
Capsule::table("mod_your_module_data")
    ->where("id", $id)
    ->update(["data" => $newData]);

// Delete data
Capsule::table("mod_your_module_data")
    ->where("id", $id)
    ->delete();

Step 3: Admin Interface

Admin Template (admin.tpl)

{if $smarty.get.action == "settings"}
    <form method="post" action="addonmodules.php?module=your_module&action=save">
        <div class="form-group">
            <label>Setting 1</label>
            <input type="text" name="setting1" value="{$setting1}" class="form-control">
        </div>
        <button type="submit" class="btn btn-primary">Save</button>
    </form>
{else}
    <h2>Your Module Admin</h2>
    <p>Welcome to the admin area</p>
    <a href="addonmodules.php?module=your_module&action=settings" class="btn btn-default">Settings</a>
{/if}

Step 4: Client Area Interface

Client Template (client.tpl)

<div class="panel panel-default">
    <div class="panel-heading">
        <h3 class="panel-title">Your Module</h3>
    </div>
    <div class="panel-body">
        <p>{$message}</p>
        <!-- Your client area content -->
    </div>
</div>

Step 5: Using WHMCS API

Local API Calls

// Get client details
$result = localAPI("GetClientsDetails", array(
    "clientid" => $clientid
));

// Create invoice
$result = localAPI("CreateInvoice", array(
    "userid" => $userid,
    "date" => date("Y-m-d"),
    "duedate" => date("Y-m-d", strtotime("+30 days")),
    "itemdescription1" => "Service Fee",
    "itemamount1" => "10.00"
));

// Send email
sendMessage("Template Name", $userid, array(
    "customvar" => $value
));

Step 6: Hooks Integration

Registering Hooks

add_hook("InvoicePaid", 1, function($vars) {
    $invoiceId = $vars["invoiceid"];
    
    // Your custom logic here
    logActivity("Invoice #" . $invoiceId . " paid");
});

Step 7: Security Best Practices

Input Validation

// Always validate and sanitize input
$userid = (int)$_POST["userid"];
$data = trim($_POST["data"]);

// Use prepared statements
$stmt = Capsule::connection()->getPdo()->prepare(
    "SELECT * FROM mod_your_module WHERE id = ?"
);
$stmt->execute([$id]);
$result = $stmt->fetch();

Permission Checks

// Check admin permissions
if (!function_exists("checkPermission")) {
    require_once("../../../includes/adminfunctions.php");
}

if (!checkPermission("your_module", "access")) {
    die("Access denied");
}

Step 8: Testing Your Module

Testing Checklist

  • ✅ Module activates without errors
  • ✅ Database tables created correctly
  • ✅ Admin interface loads
  • ✅ Client area displays
  • ✅ API calls work
  • ✅ Hooks execute properly
  • ✅ Error handling works
  • ✅ Module deactivates cleanly

Step 9: Deployment

Packaging Your Module

  1. Create ZIP file with all module files
  2. Include installation instructions
  3. Add changelog
  4. Test installation on clean WHMCS

Version Control

function your_module_config() {
    return array(
        "name" => "Your Module",
        "version" => "1.0.0", // Use semantic versioning
        // ...
    );
}

Common Development Patterns

Configuration Management

// Get module configuration
$config = getModuleConfig("your_module");

// Save configuration
updateModuleConfig("your_module", array(
    "setting1" => $value1,
    "setting2" => $value2
));

Error Handling

try {
    // Your code
    $result = someFunction();
} catch (Exception $e) {
    logModuleCall("your_module", "function_name", $vars, "", $e->getMessage(), array());
    return array("error" => $e->getMessage());
}

Advanced Features

Cron Jobs

function your_module_cron() {
    // Your cron job code
    logActivity("Your Module Cron: Executed");
}

AJAX Support

// In your module file
if ($_GET["ajax"] == "1") {
    header("Content-Type: application/json");
    echo json_encode(array("status" => "success"));
    exit;
}

WHMCS 8.x Development Notes

  • Use namespaces for better code organization
  • Leverage new API features
  • Follow PSR coding standards
  • Use dependency injection where possible

Resources and Documentation

  • WHMCS Developer Documentation
  • WHMCS API Reference
  • WHMCS Hooks Documentation
  • WHMCS Community Forums

Conclusion

Developing WHMCS modules requires understanding of PHP, WHMCS architecture, and best practices. Start with simple modules and gradually add complexity. Always test thoroughly before deployment.

Need help with WHMCS module development? Check out our premium WHMCS modules for examples and inspiration, or contact us for custom development services.

Related Articles