4 September 2021

PHP versions are supported for two years, and it is recommended to always use the latest and greatest version. In theory, that is quite easy on cPanel servers. Any domain that uses the inherited PHP version can be bumped to a new PHP version by simply bumping the inherited version. In practice, it doesn’t always work like that. Major PHP updates have a habit of breaking websites using code that is not compatible with the new version.

As a result, the inherited PHP version is often just the oldest PHP version supported on a server. New accounts that are created are typically manually given whatever the latest PHP version is at that time via the MultiPHP Manager. Over time, this results in quite a mosaic of PHP versions.

Minor upgrades from, say, PHP 7.2 to 7.4 rarely cause issues. So, at some point you might want to upgrade the PHP version for all virtual hosts using a specific PHP version. WHM API 1 has two functions for that: php_get_vhosts_by_version and php_set_vhost_versions.

Listing PHP versions for domains

Let’s first get a count of PHP versions. To do so, you can grab all installed PHP versions using php_get_installed_versions and then loop through the values to get a count for each PHP version.

To take this one step at the time, you can return just the values with yq. I wrote about how to install and use yq in my introduction to WHM API 1. We also got a more in-depth article about parsing JSON and YAML files.

# whmapi1 php_get_installed_versions | yq e '.data.versions[]' -
ea-php56
ea-php70
ea-php72
ea-php73
ea-php74
ea-php80

The trick is to get the above output into an array so that you can pass the PHP versions to the php_get_installed_versions function. I like to use readarray for that. Here, I’m reading the output into an array named php_versions:

# readarray -t php_versions < <(whmapi1 php_get_installed_versions | yq e '.data.versions[]' -)
# for i in "${php_versions[@]}"; do
  printf '%s\t%s\n' "$i" "$(whmapi1 php_get_vhosts_by_version version="$i" | yq e '.data.vhosts[]' - | wc -l)";
done
ea-php56    2
ea-php70    1
ea-php72    48
ea-php73    67
ea-php74    109
ea-php80    1

It is worth noting that the list doesn’t include the default/inherited PHP version. If you want to include that version in the list then you need it to add it to the php_versions array:

# php_versions=("inherit" "${php_versions[@]}")

And you can then run the same for-loop again:

# for i in "${php_versions[@]}"; do
  printf '%s\t%s\n' "$i" "$(whmapi1 php_get_vhosts_by_version version="$i" | yq e '.data.vhosts[]' - | wc -l)";
done
inherit     191
ea-php56    2
ea-php70    1
ea-php72    48
ea-php73    67
ea-php74    109
ea-php80    1

Getting the default PHP version

The above command doesn’t tell us which PHP version the inherited version uses. Of course, there is a function to check the default version:

# whmapi1 php_get_system_default_version
---
data:
  version: ea-php56
metadata:
  command: php_get_system_default_version
  reason: OK
  result: 1
  version: 1

Batch updating PHP versions

As at September 2021 only PHP 7.4 and 8.0 are actively supported (PHP 7.3 still gets security updates). To change the PHP version for the 48 virtual hosts running PHP 7.2 you can use a variation on the for loop I used a minute ago. First, you need to get all virtual hosts running ea-php72 and you can then pass the domains to the php_set_vhost_versions version function.

# readarray -t doms < <(whmapi1 php_get_vhosts_by_version version=ea-php72 | yq e '.data.vhosts[]' -)

# for d in "${doms[@]}"; do
whmapi1 php_set_vhost_versions version=ea-php74 vhost="$d"
done

Note that both the version and vhost parameters are required. The former specifies the new PHP version and the latter the virtual host for which the version should be changed.

Managing PHP handlers

As a bonus tip, you can also manage PHP handlers using php_get_handlers and php_set_handler. The former function returns the PHP version, current handler and available handlers for each installed PHP version:

# whmapi1 php_get_handlers
---
data:
  version_handlers:
    -
      available_handlers:
        - cgi
        - lsapi
        - none
        - suphp
      current_handler: lsapi
      version: ea-php56
    -
      available_handlers:
        - cgi
        - lsapi
        - none
        - suphp
      current_handler: suphp
      version: ea-php70
    -
	...

You can of course shorten the output using yq:

# whmapi1 php_get_handlers api.columns.enable=1 api.columns.a=current_handler api.columns.b=version | yq e '.data.version_handlers[]' -
current_handler: lsapi
version: ea-php56
current_handler: suphp
version: ea-php70
...

The php_set_handler function changes the PHP handler for a PHP version. For instance, you can change the handler for PHP 7.0 from suphp to lsapi like so:

# whmapi1 php_set_handler \
  version='ea-php70' \
  handler='lsapi'

To change the PHP handler for all installed PHP version you can again use a loop, though it is probably quicker to run the above command a few times (scripts aren’t always the best option).