Exakat 1.5.5 review

Exakat 1.5.5 Review

Exakat 1.5.5 is the sinkterklas version : it brings a lot of speed, reports and analysis on its boat, from Spain. Seriously, Exakat 1.5.5 now reports your HTTP headers for unsafe configuration; it also suggests speed up tricks for fputcsv(), and it recommends using the file() functions, instead of fileget_contents(). Then, Exakat turns your code into a city, with the help of PHP City. Hij komt, hij komt, the Exakat 1.5.5 review.

Speed up fputcsv()

fputcsv is a native function that writes files in the CSV format. It takes a single dimensional array, and add the separator, and the optional enclosing characters. Since it only accepts one row at a time, it is often used this way :

   
<?php

// range() accepts letters, but don't abuse them 
// array_chunk split an array into arrays, 3 by 3 
$source = array_chunk(range('a', 'z'), 3);

$fp = fopen('my.csv', 'w+');
foreach($source as $row) {    
   fputcsv($fp, $row);
}
fclose($fp);

?>

This is pretty convenient, but it tends to be a slow process. The fputcsv() actually write the line at call time, leading to a lot of flushes. Those are slow. It would be a lot faster to batch all the rows into one large text, and then, fwrite() it into the file.

While writing the CSV format manually is not too difficult, it is not convenient. fputcsv() does the work fast and clean, while rewriting the proper escaping of all elements in the array is gruesome. It would be nice to have fputcsv() as a formater, decoupled from the file pointer it requires as first argument.

Actually, this thought is the origin of this nice speed trick : let’s give fputcsv() a file to write on, then let’s use fwrite() to the disk in one shot. Of course, such a temporary file shouldn’t be on the disk, but in memory. So, we can rely on php://memory or php://temp. Those are special file that fopen() recognizes : the first one creates the file in memory, while the second creates the file in memory until a certain size. By default it is 2 Mb, but it may easily be configured. When using temp, PHP will automatically write the temp file on the disk when it reaches 2 Mb, so this will defeat our own target. So, we stick with memory.

Here is how it works :

  
<?php

// range() accepts letters, but don't abuse them // array_chunk split an array into arrays, 3 by 3 $source = array_chunk(range('a', 'z'), 3);

$f = fopen('php://memory', 'w+');
foreach($source as $row) {    fputcsv($f, $row);
}
rewind($f); // Important, otherwise we won't write anything $fp = fopen('my.csv', 'w+');
fwrite($fp, $f);
fclose($fp);
fclose($f);

?>

First, we open the memory file, and write everything with fputcsv(). Then, we rewind the file, and pour it in one shot into the destination file.

When writing 300 000 rows on the disk, fputcsv() in a foreach requires 1,192 ms, while the php://memory trick requires 308 ms. This is almost a 4-times speed up, for about 1 Mb of data on the disk.

The php://memory trick is interesting, as it shifts a flushing problem to a memory problem. Beware of this if you’re manipulating very large CSV, as the script may eat up all the memory. Otherwise, this acceleration is available starting with the smallest arrays, so there is no reason to avoid it!

Security HTTP header

From the MDN web docs :

The HTTP X-XSS-Protection response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks.

The Access-Control-Allow-Origin response header indicates whether the response can be shared with requesting code from the given origin.

Both those headers may be emitted from the PHP application, to change the security level. X-XSS-Protection may be set to 0, and Access-Control-Allow-Origin may be set to *, which are unsafe. Anytime headers are identified in the code as doing so, they are now reported.

   
<?php
// Don't disable security restrictions in the code 
header('Access-Control-Allow-Origin: *');
?>

Use the _file() function

Quite a number of PHP function have a _file version, that manipulates a file directly. For example, the hash function.

   
<?php

// calculate the SHA256 of a file 
echo hash_file('sha256', '/path/to/the/file.txt');

?>

Sadly, for those of use who keeps forgetting that file, the alternative is to use the hash function, after reading the file with file_get_contents();

   
<?php

// calculate the SHA256 of a file 
echo hash('sha256', file_get_contents('/path/to/the/file.txt'));

?>

The performance gain is not significant, but memory is saved in the process, leading to a less greedy script.

The PHPcity report

A new report was added to the current list : PHPcity. It originates from the code city source code visualisation, invented by Richard Wettel.

Spot those large tall building as the large and complex class of your code

The idea is to represent the code source as the building in a city. Pieces of code are first gathered as districts, based on namespaces or folders. Then, each class is represented, based on their number of properties, methods (for the base) and lines of code (for the height). Colors are also used to represent abstract, final or interfaces.

PHPcity is a project from Adrian Huna, that applies those principles to PHP. It is based on JScityand requires some data extraction from the code source.

Exakat provides the metrics for PHP city to display them. In command line, use this:

> php exakat.phar report -p <yourproject> -format Phpcity 

Then, upload the script to PHPcity demo and then interact with your code.

The Weekly Audits : 2018, Week #48

Exakat includes a ‘weekly’ report : this report is built with a selection of five analyses. This means a short audit report, with few issues to review. This is not a lot to read them, and review them in your code. Everyone in the PHP community can focus on one of the classic coding problems and fix it. Talk about the weekly audit around you : you’ll find programmers facing the same challenges.

To obtain the ‘weekly’ audit, run an audit, and request the ‘Weekly’ report.

\# Init the project (skip when it is already done)   
php exakat.phar init -p <yourproject> -R https://github.com/Seldaek/monolog.git -git 

\# Run the project (skip when it is already done)   
php exakat.phar project -p <yourproject> 

\# Export the weekly project (every monday)   
php exakat.phar report -p <yourproject> -format Weekly 

\# Open projects/<yourproject>/weekly/index.html in your browser    

Every week, you can find here 5 new analysis to review in your code. In fact, when your code is clean, you can also take a quick look at the upcoming

Weekly recommendations for PHP code review : 2018, week 2018-48

  • Throw Functioncall : The throw keyword expects to use an exception.
  • Not Not : Double not makes a boolean, not a true.
  • Invalid Pack Format : Some characters are invalid in a pack() format string.
  • Too Many Injections : When a class is constructed with more than four dependencies, it should be split into smaller classes.
  • Parent First : When calling parent constructors, always put it first in the __constructmethod.

Every week, you can find here 5 new analysis to review in your code. In fact, when your code is clean, you can also take a quick look at the upcoming week with the ‘Go further’ section.

Happy PHP Code Reviews

All the 362 analyzers are presented in the docs, including the obedient__DIR__ Then Slash : __DIR__ must be concatenated with a string starting with ‘/’.__DIR__ doesn’t include the final slash, so any concatenation that doesn’t start with it will see the directory name changed. It is a rare bug : 7% applications mishandle__DIR__.

You can check all of the Exakat reports at the gallery: exakat gallery.

Download Exakat on exakat.io, install it with Docker, upgrade it with ‘exakat.phar upgrade -u’ and like us on github.