{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Loader Functions","description":"Developer documentation for the WHMCS API — the","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"loader-functions","__idx":0},"children":["Loader Functions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Setting a loader function allows you to create a field that offers a dropdown of options for an end user to choose from."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Unlike the standard \"dropdown\" setting field type which allows you to offer a predefined and hard-coded choice of options to the user, a field with a loader function will display a list of options that have been fetched dynamically from a remote API service."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["An example use case for this is for a Package or Plan name field, where the values need to be fetched via an API from the remote system where the Packages or Plans are defined. Without a loader function, the end user would have to manually enter the package or plan name for the product. With a loader being used, WHMCS will poll the remote API service for a list of possible values when the field is rendered to the end user and allow them to make a choice."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To use a loader function for a field, when defining the field in the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["ConfigOptions"]}," function, you must also define a loader function that will be called to populate the field with a list of available options."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each field can have its own unique loader function defined. These fields will be populated with the return values of the associated loader function when simple mode is used."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here is an example of a field that defines a loader function with the name ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["provisioningmodule_LoaderFunction"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"function provisioningmodule_ConfigOptions($params)\n{\n    return [\n        // Text field powered by the Loader function\n        'Loader Populated Field' => [\n            'Type' => 'text',\n            'Size' => '25',\n            'Loader' => 'provisioningmodule_LoaderFunction',\n            'SimpleMode' => true,\n        ],\n    ];\n}\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The loader function you define must be created and should return an array of key value pairs."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The key should be the value that your module expects to receive, and the value should be a human friendly display label for the key value. In many cases these may be the same."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"error-handling","__idx":1},"children":["Error Handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the connection to the remote API service needed to fetch the dynamically loaded values fails, your code should throw an Exception."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["WHMCS will recognize an Exception and display the error message returned in that exception to the end user."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"/**\n * Loader function that will populate the field in ConfigOptions\n * @return array The list of package names\n */\nfunction provisioningmodule_LoaderFunction($params) {\n    // Make a call to the remote API endpoint\n    $ch = curl_init('https://www.example.com/api/function');\n    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n    $response = curl_exec($ch);\n\n    // Check for any curl errors or an empty response\n    if (curl_error($ch)) {\n        throw new Exception('Unable to connect: ' . curl_errno($ch) . ' - ' . curl_error($ch));\n    } elseif (empty($response)) {\n        throw new Exception('Empty response');\n    }\n\n    // We're done with curl so we can release the resource now\n    curl_close($ch);\n\n    // Attempt to decode the response\n    $packageNames = json_decode($response, true);  \n\n    // Check to make sure valid json was returned\n    if (is_null($packageNames)) {\n        throw new Exception('Invalid response format');\n    }\n\n    // Format the list of values for display\n    // ['value' => 'Display Label']\n    $list = [];\n    foreach ($packageNames as $packageName) {\n        $list[$packageName] = ucfirst($packageName);\n    }\n\n    return $list;\n}\n"},"children":[]}]},"headings":[{"value":"Loader Functions","id":"loader-functions","depth":1},{"value":"Error Handling","id":"error-handling","depth":2}],"frontmatter":{"title":"Loader Functions","seo":{"title":"Loader Functions"}},"lastModified":"2026-08-03T17:00:42.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/provisioning-modules/loader-functions","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}