PHP and iControl REST

Problem this snippet solves:

PHP and iControl REST interfaces

Here are a couple of ways to use PHP and iControlREST (iCR). iCR is lighter-weight than iControl SOAP but is only supported on >= v11.5.

When using these, check that the PHP implementation supports cURL using phpinfo() or check your php.ini file for 'extension=php_curl.dll' or the relevant name.

I have included two ways to do this - via functions and via a PHP class. In practise the class is the simplest way to do this but the function seems to be the more efficient way of doing it. (Tested by retrieving ~700 Virtual Servers from a remote BIG-IP).

Using the attached files you can save them and modify as required. Change the IP address to be relevant to your setup. Note that the iCR class uses the default username/password admin/admin.

Feel free to PM me if you have any specific requirements or issues.

How to use this snippet:

Example Class Usage:

$r = new iCR ("");
echo "<html><body><pre>";
echo "<h2>Non-existent Virtual Server</h2><pre>";

echo $r->code;

$vs = array('name'=>"iCR_Test_VS",'destination'=>'','mask'=>'','ipProtocol'=>'tcp');

echo "</pre><h2>Created Virtual Server</h2><pre>";

echo "</pre><h2>Edited Virtual Server</h2><pre>";
$description = array('description' => 'This is a modified Virtual Server');
# Use the PATCH method to update ( the true as the third variable )
echo "Modify HTTP Return Code: $r->code\n";

echo "</pre><h2>Deleted Virtual Server</h2><pre>";
echo "Delete HTTP Return Code: $r->code\n";

echo "</pre></body></html>";

Example Function Usage:

$hostname = "";
$username = "admin";
$password = "admin";

$BIGIP_URL_BASE = "https://$hostname/mgmt/tm";
$url = $BIGIP_URL_BASE."/ltm/virtual";
$handle = curl_init();
echo "<html><body><h2><pre>";

echo "</pre><h2>Non-existent Virtual Server</h2><pre>";

// Create a Virtual Server
echo "</pre><h2>Created Virtual Server</h2><pre>";

$vs = array('name'=>"iCR_Test_VS",'destination'=>'','mask'=>'','ipProtocol'=>'tcp');

// Edit the Virtual Server
echo "</pre><h2>Edited Virtual Server</h2><pre>";
$description = array('description' => 'This is a modified Virtual Server');

// Delete the Virtual Server
echo "</pre><h2>Deleted Virtual Server</h2><pre>";

echo "</pre><h2>Post-delete Virtual Server</h2><pre>";

echo "</pre></body></html>";
Updated Jun 06, 2023
Version 2.0

Was this article helpful?


  • Thanks Pete. This was highly helpful. But I get performance issues when I do multiple calls. My code works like. 1. First Call - > get the pool names (/mgmt/tm/ltm/pool) 2. Second Call -> Based on the pool names(path), get it's status. (mgmt/tm/ltm/pool/~pool~name/stats) 3. Third Call -> Based on the pool names(path), get it's pool members. (/mgmt/tm/ltm/pool/~pool~names/members) PHP CODE ===================


    ` "; $tildaPath = str_replace("/", "~", $pools['fullPath']); //GET THE pool stats $pool_stats = iCR($username, $password, "GET", $BASE_URL."/ltm/pool/".$tildaPath."/stats/?\$select=status.availabilityState", NULL); echo $pool_stats["entries"]["status.availabilityState"]["description"] . "


    "; //GET THE pool members $pool_members = iCR($username, $password, "GET", $BASE_URL."/ltm/pool/".$tildaPath."/members/?\$select=name,address,state", NULL); foreach ($pool_members['items'] as $members) { echo $members['name']." ".$members['address']." ". $members['state']."


    "; } } ?> ` ============================CODE================================================


    So, when make first call, I get ~1200 pool. Second call, will degrade the performance. And third call even makes everything worse. I get execution time exceeded error. I increased it to 300s but still that's not enough. Do you have any thoughts on optimizing this code. I would appreciate any help. Thanks
  • Thanks DevBabu, glad you found it useful. I think the issue you have is related to the fact that you are performing an individual iControl request for each of these items. Each iControl request takes milliseconds to perform which is a long time so you are better to make few iControl calls that retrieve large amounts of data and loop through that data, than to make hundreds of individual iControl calls that retrieve a small amount of data. To give you an example here, you should do three iControl calls - retrieve all pools, all pools status and all pool members. Then loop through these arrays as required. This is generally true whether using SOAP or REST.
  • Hi Pete, I am trying to use similar code sent by you but to fetch pools. The output format is not what I expected, below is the snippet of the response :


    stdClass Object ( [kind] => tm:ltm:pool:poolcollectionstate [selfLink] => $select=name&ver=11.6.1 [items] => Array ( [0] => stdClass Object ( [name] => CTUSOPService_IAT )


            [1] => stdClass Object
                    [name] => adptlm

    And I expected it to be like below :


    { "kind":"tm:ltm:pool:poolcollectionstate", "selfLink":"$select=name&ver=11.6.1", "items":[ { "name":"CTUSOPService_IAT" }, { "name":"adptlm" },


    Any reason why this is happening..? My intention is to use JsonPath against the output to fetch the required fields. Eg : $.items[*].name


  • Hi Santosh, The functions and methods return PHP variables because I used the json_decode method on the returned JSON. So the returned data is an object that contains an array. Therefore you can manage the array by using foreach on the array eg:


    $handle = curl_init();
    $icr = iCR($handle,"admin","admin","GET","https:///mgmt/tm/ltm/pool")
    foreach ($icr->items as $i=>$v) {
      echo "Pool name:$v->name 

    If you want to retrieve the JSON, I suggest you use json_encode or alternatively change the code of the methods to return the JSON, although I can't see what using the JSON instead of the standard PHP functions will give you.


  • Hi Pete,


    For F5 LTM ver=13, needed to change the "PUT" to a "PATCH" in the modify() function. Otherwise got error when PATCHing the transaction like: transaction failed:0107028c:3: The source (::) and destination addresses for virtual server must be be the same type (IPv4 or IPv6).


    Hear the change was made in ver=12 Know that "PUT" worked in ver=11


    Maybe worth updating so it checks which version is in use and then uses the appropriate CURLOPT_CUSTOMREQUEST ?


    By the way, thank you for all the work you put into this!! It is getting lots and lots of good use :-)


  • Hi tgbauer,


    Great to hear that it has use, it helped me out when I needed it.


    You make a very good point - in my iCR Python module I added the ability to set PATCH in the modify method by setting PATCH=True. I'll look at doing the same with this, then you can decide for yourself whether to use PUT or PATCH.


    Are you able to send me details of the modify that you are trying to do - ie the URL and the data




  • Updated to include the use of PATCH. Note that with class the modify method is updated to include the PATCH variable. Set this to true to use PATCH method. Remove it or set to false to use PUT. For function, I have added the PATCH variable to the other methods.


    Example with class:


     'This is a modified Virtual Server');
    echo "Modify HTTP Return Code: $r->code\n";

    Example with function:


     'This is a modified Virtual Server');

    Let me know if you feel there are any other useful features required