vBulletin 4 and PHP 7, making it work.

Note: vBulletin has now released versions that support PHP 7+, I recommend doing a vBulletin upgrade instead of following this guide. If you do not want to upgrade your forum then you can still use this guide.

PHP 7 has been officially released on the 3rd of December.
It introduces a lot of new features, deprecates a bunch of functions and most importantly, its performance received a huge boost.

I personally used https://webtatic.com/packages/php70/ to upgrade my PHP from 5.4.45 to 7 on CentOS 6.7.
Make sure that you install PHP OPCache as well, it gives you a huge performance boost.

Now vBulletin 4 (<= 4.2.3 at the time of writing this post) does not support PHP 7 out of the box. A couple of changes have to be made in order to make it work smoothly with PHP 7.
There are 3 things we have to fix:
– Methods with the same name as their class may not be constructors.
– Function name must be a string.
– Redefinition of arguments are not allowed.

Step 1: configuration file
First be sure you have a backup of your forum files, this is very important in case the changes do not end up working for you.
Now open the /includes/config.php file and make sure that your datastore class is set to vB_Datastore_Filecache, APC/xCache/Memcached will not work since they do not support PHP 7 (yet) and it’s not necessary to use either of those anyway since OPCache does the job.

Step 2: fixing “function name must be a string”
First we edit /includes/class_bbcode.php. Look for the following:

$pending_text = $this->$tag_info['callback']($open['data'], $open['option']);

and change it to:

$function = $tag_info['callback'];
$pending_text = $this->$function($open['data'], $open['option']);

This will fix the “function name must be a string” error. It seems that PHP doesn’t like it when the value of a key in an array is directly being used as a function name. My fix first assigns it to a variable and then uses it as the function name.

Step 3: fixing /includes/class_datastore.php
Open the file /includes/class_datastore.php and find each of the following:

function vB_Datastore_Memcached(&$registry, &$dbobject)
function vB_Datastore_Filecache(&$registry, &$dbobject)

change them both to:

function __construct(&$registry, &$dbobject)

Now also find the following:

parent::vB_Datastore($registry, $dbobject);

and replace all occurrences to:

parent::__construct($registry, $dbobject);

Step 4: fixing /includes/class_hook.php
Open the file /includes/class_hook.php and find the following:

	function vBulletinHook()
	{
	}

and change it to:

	function __construct()
	{
	}

Step 5: fixing /includes/class_core.php
Open the file /includes/class_core.php and find each of the following:

function vB_Database(&$registry)
function vB_Datastore(&$registry, &$dbobject)
function vB_Input_Cleaner(&$registry)
function vB_Registry()
function vB_Session(&$registry, $sessionhash = '', $userid = 0, $password = '', $styleid = 0, $languageid = 0)

and change all of the function names to __construct:

function __construct(&$registry)
function __construct(&$registry, &$dbobject)
function __construct(&$registry)
function __construct()
function __construct(&$registry, $sessionhash = '', $userid = 0, $password = '', $styleid = 0, $languageid = 0)

Step 6: fixing /vb/exception/parser.php
This is probably a mistake by vBulletin, but we have to fix it in order to make it work.
Open the file /vb/exception/parser.php and find the following:

	public function __construct($message, $line = false, $code = false, $file = false, $line = false)
	{
		$message = $message ? $message : 'Parser Error';
		
		if (!empty($line))
		{
			$message .= "::$line";
		}
		
		parent::__construct($message, $code, $file, $line);
	}

and replace it by:

	public function __construct($message, $line = false, $code = false, $file = false, $line2 = false)
	{
		$message = $message ? $message : 'Parser Error';
		
		if(empty($line)){
			$line = $line2;
		}

		if (!empty($line))
		{
			$message .= "::$line";
		}
		
		parent::__construct($message, $code, $file, $line);
	}

And that’s it. Your vBulletin installation should now work correctly with PHP 7.
In case it does not, check the error logs of your web-server/PHP and make sure that none of your plugins or custom scripts are making use of deprecated functions.

Below is a comparison of vBulletin 4 and PHP 5.4, PHP 7 and PHP 7 with OPCache.
As you can see, vBulletin loads almost 2.5(!) times faster.

Before the upgrade (PHP 5.4.45)
Homepage
409.31 – 429.84 – 389.37 – 401.51 – 389.75 – 426.69
~407.75ms average loading time

Forum Category
518.51 – 491.49 – 447.64 – 491.94 – 433.52 – 543.93
~487.84ms average loading time

Thread
326.34 – 399.72 – 387.09 – 383.79 – 370.03 – 375.21
~373.70ms average loading time

—–

After the upgrade (PHP 7 WITHOUT OPCache)
Homepage
289.79 – 291.41 – 289.11 – 253.45 – 285.06 – 259.98
~278.13ms average loading time

Forum Category
281.83 – 333.31 – 293.23 – 276.73 – 268.91 – 281.63
~289.27ms average loading time

Thread
221.73 – 344.83 – 257.84 – 250.72 – 250.04 – 220.07
~257.53ms average loading time

—–

After the upgrade (PHP 7 WITH OPCache)
Homepage
225.63 – 200.26 – 219.48 – 181.72 – 199.93 – 177.55
~200.76ms average loading time

Forum Category
194.95 – 184.47 – 237.45 – 182.62 – 185.93 – 178.06
~193.91ms average loading time

Thread
207.83 – 156.41 – 146.43 – 143.13 – 155.13 – 142.61
~158.59ms average loading time