Exakat 1.7.9 Review

Exakat 1.7.9 is bringing a wide range of updates and upgrades. First, support for PHP 7.4 is growing, with arrow functions and spread operators in arrays, and ffi extension. Then, we extended the nested ternary, in preparation for PHP 7.4’s non-nesting features. And finally, the Inventory report added the inclusions list, while Ambassador got an upgrade of the global inventory. You’ve got to keep moving forward to the Exakat 1.7.9 review! 

Exakat 1.7.9 review

Support for PHP 7.4 syntax

PHP 7.4 is still a few months away (December 2019), but the list of upgrade recommendations is already available. In particular, PHP 7.4 will introduce new syntax, such as arrow functions and spreads in array. Exakat is already supporting those new features! 

Arrow functions

Arrow functions are a new and shorter way to write a closure. Closure is already a lesser version of a function, without a name, and with more context integration. Arrow functions are an even shorter version. 

Taken from the RFC, here is the same code, written in two different versions : 

<?php    
function array_values_from_keys($arr, $keys) {      
   return array_map(function ($x) use ($arr) { return $arr[$x]; }, $keys); 
}
?>
<?php 
function array_values_from_keys($arr, $keys) {
     return array_map(fn($x) => $arr[$x], $keys);
}
?>

Both code applies a function to the array $arr, to extract a specific set of values, based on a set of keys. Note how the second syntax is much shorter. 

First, PHP 7.4 introduces the fn keyword. This keyword introduces the new syntax, and helps disambiguate the code from arrays and yield, which are also depending on the => operator. This also means that the code can’t use fn as a class or function name. This was checked, and it is extremely rare. 

Secondly, there are no curly brackets, and no return statement : after the double arrow =>, there is only one expression. There is no room for a block with multiple expressions. Arrow functions are for short expressions that need to be repeated or moved around. If the need emerges, more expression may be added, but it is not the case at the moment.

Arrow function will cut down on boiler plate code, and keep the code short. 

Support for the arrow functions was added to Exakat. It is now able to compile and manipulate arrow functions, just like closures and methods. The engine has been tested with arrow functions, and the analysis is upgraded to handle them too. 

Spread operator

Also known as variadic or ellipsis, the spread operator turns an array of array into distinct arguments. 


<?php 
$array = [[1,2,3],[4,5,6],[7,8,9]]; $list = array_merge(...$array); 
?>

Here, array_merge accepts an arbitrary number of arguments, and the ... operator spreads the elements from the $array array into distinct arguments, leading to the merge of all elements in one call. This is a great speed up. 

Strangely enough, the ... operator is not allowed in arrays themselves. While it is possible to use array_merge to combine multiple arrays into one, it could also be efficient to merge arrays together to form a new array. This is the case with PHP 7.4, since 2019-05-13 (that is yesterday, for those who read this in the future).

<?php 
   $list = [...[1,2,3], ...[4,5,6], ...[7,8,9]]; 
?>

The spread operator was already supported by the Exakat engine. In fact, it is interpreted just like any other call to a spread operator in a function or method call. Exakat first tokenize the code with PHP itself, and since PHP itself yielded a Fatal error, those files were not available for analysis. PHP 7.4 now accepts them and so is Exakat. 

We’ll be adding spread operator specific analysis in the future. 

FFI extension

The FFI extension is the Foreign Function Interface. It is an experimental function that “allows the loading of shared libraries (.DLL or .so), calling of C functions and accessing of C data structures in pure PHP, without having to have deep knowledge of the Zend extension API, and without having to learn a third “intermediate” language. ” You may learn more about FFI on Anthony Ferrara’s A PHP Compiler, aka The FFI Rabbit Hole blog post.

Unrelated to PHP 7.4, the UUIDpasswordzend monitor and svm, for Support Vector Machine Library, extensions were added to the list of supported extensions. Do not confuse this last one with the SVN extension. 

Nested Ternaries Gets A Facelift

Nested ternaries are getting a facelift, both in Exakat and PHP. 

First, in Exakat, nested ternaries are now taking into account parentheses. Until now, only directly nested ternaries were reported, while now, even the one written in parentheses are added. 

Nested ternaries, with or without a parenthesis, are reported for poor readability. Two are immediately difficult to read, and the author has experienced a 6-level ternary monster expression. 

<?php
// nested and unreadable  
$a = $b ? $c ? $d : $e : $f;

// nested, unreadable and parenthesed  
$a = $b ? ($c ? $d : $e) : $f;

?>

In PHP 7.4, ternary operators are also getting a facelift. Since almost all other languages have a right associative ternary operator, it is confusing when switching from one language to the next. Since it would break too much code by switching the precedent from left to right, any ambiguous ternary operator will be flagged with a PHP Deprecation Warning.

<?php   
$a = $b ? $c ? $d : $e : $f ? $g : $h ;

//PHP Deprecated:  Unparenthesized `a ? b : c ? d : e` is deprecated. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`   
?>

// Note that the variable names are missing the initial $ : this is probably a development artefact. 

Not every nested ternary expressions will be flagged : only the one that are ambiguous, and may yield an different result than the one written. 

This feature is backward compatible. Simply, the code will need an update before moving to PHP 7.4. According to the EPIC (Exakat PHP Index of Coding, 12,2% of PHP code has to be upgraded.

Inclusion inventories

The Exakat report called ‘Inventory’ was upgraded with two new reports : inclusion list and global variable list.

The Inventory report collects all sorts of assets from the code, and deliver them as csv files. For example, you may review all your regex or variable names, gathered in the same place.

The csv format makes it easy to import those inventories into another data manipulation tool, such as Open Office spreadsheets, so that you may apply your own transformations before reporting them.

The inclusions list

This list collect all the inclusion calls, which are include, require, includeonce and requireonce, with their actual argument. The second column holds the name of the calling file. 

/tbl_select.php,"require_once ROOT_PATH . 'libraries/common.inc.php'" 
/tbl_select.php,"require_once ROOT_PATH . 'libraries/tbl_common.inc.php'"
 /error_report.php,"require_once ROOT_PATH . 'libraries/common.inc.php'"
 /db_multi_table_query.php,"require_once ROOT_PATH . 'libraries/common.inc.php'"

Inclusions have a few dedicated analysis in Exakat : Inclusion Wrong Case and Missing includecome to mind. 

Yet, the rules to build an inclusion path may be complex, and guessing them is out of the scope of Exakat. This is where inventories are a great start : all the occurrences of inclusion have been collected and gathered in one place. Add your own magic, and check if any of those inclusion are wrong or not.

Global Variables

Global variables were also added to the inventories system. They are also upgraded in the Ambassador report : 

Globals are now grouped by name, so you may have a better view over their location. Here, we can spot that most global variables are only used in one file, which reduces the risk of contagion.

Then, the second column indicates the type of global : it may be one of ‘implilcit’, ‘global’ or ‘$GLOBALS’, depending on the origin. ‘global’ means that the variable was explicitly declared, $GLOBALS means that it is accessed via the supreglobal $GLOBALS, and ‘implicit’ means that it is in the global space, and it is never explicitly made global, though PHP will make it global by default. 

The next column mentions if the variable is read R or modified W. This is interesting, since the example used here show some global variables such as $children or $createMisc which are written and read : this is the best combination, as it shows that the variable is both assigned and used. Yet, there are other variables which are read only, such as $productType. There are also situations where the variable usage is split over multiple files, or written only. 

With such an overview of the global variables, it is now easy to review them, and start removing them, or moving them to other storage locations. In particular, this is mostly useful when the global usage is spread across multiple files.

The Weekly Audits: 2019, Week #20

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 : 2019, week 2019-20

  • Parent First : When calling parent constructor, always put it first in the __constructmethod.
  • Substring First : Always start by reducing a string before applying some transformation on it.
  • Aliases Usage : PHP manual recommends to avoid function aliases.
  • Logical Mistakes : Avoid logical mistakes within long expressions.
  • Use List With Foreach : Foreach() structures accepts list() as blind key.

Happy PHP Code Reviews 

All the 352 analyzers are presented in the docs, including the grand : Could Use str_repeat(): Use strrepeat() or strpad() instead of making a loop.

It is still an unusual suggestion (12%), though it is nice to review one’s code and upgrade it with it! 

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.

[]