One trend that developers are taking advantage of is the use of anonymous functions. One classic problem, when dealing with anonymous functions, is to write them in such a way that any object can be bound to $this and the function will still work. The approach used in PHP 5 code is to use bindTo(). In PHP 7, a new method, call(), was added, which offers similar functionality, but vastly improved performance.
To take advantage of call(), execute an anonymous function in a lengthy loop. In this example, we will demonstrate an anonymous function, that scans through a log file, identifying IP addresses sorted by how frequently they appear:
Application\Web\Access class. In the constructor, we accept a filename as an argument. The log file is opened as an SplFileObject and assigned to $this->log:Namespace Application\Web;
use Exception;
use SplFileObject;
class Access
{
const ERROR_UNABLE = 'ERROR: unable to open file';
protected $log;
public $frequency = array();
public function __construct($filename)
{
if (!file_exists($filename)) {
$message = __METHOD__ . ' : ' . self::ERROR_UNABLE . PHP_EOL;
$message .= strip_tags($filename) . PHP_EOL;
throw new Exception($message);
}
$this->log = new SplFileObject($filename, 'r');
}public function fileIteratorByLine()
{
$count = 0;
while (!$this->log->eof()) {
yield $this->log->fgets();
$count++;
}
return $count;
}public function getIp($line)
{
preg_match('/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/', $line, $match);
return $match[1] ?? '';
}
}First of all, we define a calling program, chap_02_performance_using_php7_enchancement_call.php, that takes advantage of the autoloading class defined in Chapter 1 , Building a Foundation, to obtain an instance of Application\Web\Access:
define('LOG_FILES', '/var/log/apache2/*access*.log');
require __DIR__ . '/../Application/Autoload/Loader.php';
Application\Autoload\Loader::init(__DIR__ . '/..');Next we define the anonymous function, which processes one line in the log file. If an IP address is detected, it becomes a key in the $frequency array, and the current value for this key is incremented:
// define functions
$freq = function ($line) {
$ip = $this->getIp($line);
if ($ip) {
echo '.';
$this->frequency[$ip] =
(isset($this->frequency[$ip])) ? $this->frequency[$ip] + 1 : 1;
}
};We then loop through the iteration of lines in each log file found, processing IP addresses:
foreach (glob(LOG_FILES) as $filename) {
echo PHP_EOL . $filename . PHP_EOL;
// access class
$access = new Application\Web\Access($filename);
foreach ($access->fileIteratorByLine() as $line) {
$freq->call($access, $line);
}
}Finally, we reverse-sort the array, but maintain the keys. The output is produced in a simple foreach() loop:
arsort($access->frequency);
foreach ($access->frequency as $key => $value) {
printf('%16s : %6d' . PHP_EOL, $key, $value);
}The output will vary depending on which access.log you process. Here is a sample:

Many of the PHP 7 performance improvements have nothing to do with new features and functions. Rather, they take the form of internal improvements, which are invisible until you start running your programs. Here is a short list of improvements that fall into this category: