Rules list¶

$HTTP_RAW_POST_DATA¶ Starting at PHP 5.6,$HTTP_RAW_POST_DATA is deprecated, and should be replaced by php://input. You may get ready by setting always_populate_raw_post_data to -1.

<?php

// PHP 5.5 and older
$postdata =$HTTP_RAW_POST_DATA;

// PHP 5.6 and more recent
$postdata = file_get_contents(php://input); ?>   Command Line Php/RawPostDataUsage Analyzers CompatibilityPHP56, Analyze, CompatibilityPHP70, CompatibilityPHP71 $this Belongs To Classes Or Traits¶

$this variable represents only the current object. It is a pseudo-variable, and should be used within class’s or trait’s methods (except for static) and not outside. PHP 7.1 is stricter and check for$this at several positions. Some are found by static analysis, some are dynamic analysis.

<?php

// as an argument
function foo($this) { // Using global global$this;
// Using static (not a property)
static $this; // Can't unset it unset($this);

try {
// inside a foreach
foreach($a as$this) {  }
foreach($a as$this => $b) { } foreach($a as $b =>$this) {  }
} catch (Exception $this) { // inside a catch } // with Variable Variable$a = this;
$$a = 42; } class foo { function bar() { // Using references a =& this; a = 42; // Using extract(), parse_str() or similar functions extract([this => 42]); // throw new Error(Cannot re-assign this) var_dump(this); } static function __call(name, args) { // Using __call var_dump(this); // prints object(C)#1 (0) {}, php-7.0 printed NULL this->test(); // prints ops } } ?>   Command Line Classes/ThisIsForClasses Analyzers Analyze this Is Not An Array¶ this variable represents the current object and it is not an array, unless the class (or its parents) has the ArrayAccess interface. <?php // this is an array class Foo extends ArrayAccess { function bar() { ++this[3]; } } // this is not an array class Foo2 { function bar() { ++this[3]; } } ?>   Command Line Classes/ThisIsNotAnArray Analyzers Analyze this Is Not For Static Methods¶ Static methods shouldn’t use this variable. this variable represents an object (the current object) and it is not compatible with a static method, which may operate without any object. <?php class foo { static public function bar() { return this->a; // No this usage in a static method } } ?>   Command Line Classes/ThisIsNotForStatic clearPHP no-static-this Analyzers Analyze ** For Exponent¶ PHP 5.6 introduced the operator ** to provide exponents, instead of the slower function pow(). <?php cube = pow(2, 3); // 8 cubeInPHP56 = 2 ** 3; // 8 ?>  If the code needs to be backward compatible to 5.5 or less, don’t use the new operator.  Command Line Php/NewExponent Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 ... Usage¶ Usage of the ... keyword, either in function definitions, either in functioncalls.  Command Line Php/EllipsisUsage Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 ::class¶ PHP 5.5 introduced a special class constant, relying on the ‘class’ keyword. It will solve the classname that is used in the left part of the operator. <?php class foo { public function bar( ) { echo ClassName::class; } } f = new Foo( ); f->bar( ); // return Namespace\ClassName ?>   Command Line Php/StaticclassUsage Analyzers CompatibilityPHP53, CompatibilityPHP54 <?= Usage¶ Usage of the <?= tag, that echo’s directly the following content. <?= variable; ?>  Command Line Php/EchoTagUsage Analyzers Analyze Abstract Static Methods¶ Methods cannot be both abstract and static. Static methods belong to a class, and will not be overridden by the child class. For normal methods, PHP will start at the object level, then go up the hierarchy to find the method. With static, you have to mention the name, or use Late Static Binding, with self or static. Hence, it is useless to have an abstract static method : it should be a simple static method. A child class is able to declare a method with the same name than a static method in the parent, but those two methods will stay independant.  Command Line Classes/AbstractStatic Analyzers Analyze Access Protected Structures¶ It is not allowed to access protected properties or methods from outside the class or its relatives.  Command Line Classes/AccessProtected Analyzers Analyze Accessing Private¶ List of calls to private properties/methods that will compile but yield some fatal error upon execution. <?php class a { private a; } class b extends a { function c() { this->a; } } ?>   Command Line Classes/AccessPrivate Analyzers Analyze Adding Zero¶ Adding 0 is useless, as 0 is the neutral element for addition. It may trigger a cast (to integer), though behavior changes from PHP 7.0 to PHP 7.1. <?php a = 123 + 0; a = 0 + 123; // Also works with minus b = 0 - c; // drop the 0, but keep the minus b = c - 0; // drop the 0 and the minus ?>  If it is used to type cast a value to integer, then casting (integer) is clearer.  Command Line Structures/AddZero clearPHP no-useless-math Analyzers Analyze Aliases Usage¶ PHP manual recommends to avoid function aliases. Some functions have several names, and both may be used the same way. However, one of the names is the main name, and the others are aliases. Aliases may be removed or change or dropped in the future. Even if this is not forecast, it is good practice to use the main name, instead of the aliases. <?php // official way to count an array n = count(array); // official way to count an array n = sizeof(array); ?>  Aliases are compiled in PHP, and do not provide any performances over the normal function. Aliases are more likely to be removed later, but they have been around for a long time. See documentation : List of function aliases.  Command Line Functions/AliasesUsage clearPHP no-aliases Analyzers Analyze All Uppercase Variables¶ Usually, global variables are all in uppercase, so as to differentiate them easily. Though, this is not always the case, with examples like argc, argv or http_response_header. When using custom variables, try to use lowercase variables, camelCase, sturdyCase or snake_case. <?php // PHP super global, also identified by the initial _ localVariable = _POST; // PHP globals localVariable = GLOBALS['HTTPS']; ?>  Predefined Variables  Command Line Variables/VariableUppercase Analyzers Coding Conventions Already Parents Interface¶ The same interface is implemented by a class and one of its children. That way, the child doesn’t need to implement the interface, nor define its methods to be an instance of the interface. <?php interface i { function i(); } class A implements i { function i() { return __METHOD__; } } // This implements is useless. class AB extends A implements i { // No definition for function i() } // Implements i is understated class AB extends A { // redefinition of the i method function i() { return __METHOD__.' '; } } x = new AB; var_dump(x instanceof i); // true x = new AC; var_dump(x instanceof i); // true ?>   Command Line Interfaces/AlreadyParentsInterface Analyzers Analyze Altering Foreach Without Reference¶ Foreach() loop When using a foreach loop that modifies the original source, it is recommended to use referenced variables, rather than access the original value with source[index]. Using references is then must faster, and easier to read. <?php // Using references in foreach foreach(source as key => &value) { value = newValue(value, key); } // Avoid foreach : use array_map source = array_walk(source, 'newValue'); // Here, key MUST be the second argument or newValue // Slow version to update the array foreach(source as key => &value) { source[key] = newValue(value, key); } ?>  You may also use array_walk() or array_map() (when key is not used) to avoid the use of foreach.  Command Line Structures/AlteringForeachWithoutReference clearPHP use-reference-to-alter-in-foreach Analyzers Analyze Always Positive Comparison¶ Some PHP native functions, such as count(), strlen(), or abs() only returns positive or null values. When comparing them to 0, the following expressions are always true and should be avoided. <?php a = [1, 2, 3]; var_dump(count(a) >= 0); var_dump(count(a) < 0); ?>   Command Line Structures/NeverNegative Analyzers Analyze Ambiguous Array Index¶ Those indexes are defined with different types, in the same array. Array indices only accept integers and strings, so any other type of literal is reported. <?php x = [ 1 => 1, '1' => 2, 1.0 => 3, true => 4]; // x only contains one element : 1 => 4 // Still wrong, immediate typecast to 1 x[1.0] = 5; x[true] = 6; ?>  They are indeed distinct, but may lead to confusion.  Command Line Arrays/AmbiguousKeys Analyzers Analyze Anonymous Classes¶ Anonymous classes. <?php // Anonymous class, available since PHP 7.0 object = new class { function __construct() { echo __METHOD__; } }; ?>   Command Line Classes/Anonymous Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Argument Should Be Typehinted¶ When a method expects objects as argument, those arguments should be typehinted, so as to provide early warning that a wrong object is being sent to the method. The analyzer will detect situations where a class, or the keywords ‘array’ or ‘callable’. <?php // What are the possible classes that have a 'foo' method? function foo(bar) { return bar->foo(); } ?>  Closure arguments are omitted.  Command Line Functions/ShouldBeTypehinted clearPHP always-typehint Analyzers Analyze Assign Default To Properties¶ Properties may be assigned default values at declaration time. Such values may be later modified, if needed. <?php class foo { private propertyWithDefault = 1; private propertyWithoutDefault; private propertyThatCantHaveDefault; public function __construct() { // Skip this extra line, and give the default value above this->propertyWithoutDefault = 1; // Static expressions are available to set up simple computation at definition time. this->propertyWithoutDefault = OtherClass::CONSTANT + 1; // Arrays, just like scalars, may be set at definition time this->propertyWithoutDefault = [1,2,3]; // Objects or resources can't be made default. That is OK. this->propertyThatCantHaveDefault = fopen('/path/to/file.txt'); this->propertyThatCantHaveDefault = new Fileinfo(); } } ?>  Default values will save some instructions in the constructor, and makes the value obvious in the code.  Command Line Classes/MakeDefault clearPHP use-properties-default-values Analyzers Analyze Assigned Twice¶ The same variable is assigned twice in the same function. While this is possible and quite common, it is also a good practice to avoid changing a value from one literal to another. It is far better to assign the new value to Incremental changes to a variables are not reported here. <?php function foo() { // incremental changes of a; a = 'a'; a++; a = uppercase(a); b = 1; c = bar(b); // B changed its purpose. Why not call it d? b = array(1,2,3); // This is some forgotten debug e = config->getSomeList(); e = array('OneElement'); } ?>   Command Line Variables/AssignedTwiceOrMore Analyzers Analyze Avoid Large Array Assignation¶ Avoid setting large arrays to local variables. This is done everytime the function is called. There are different ways to avoid this : inject the array, build the array once. Using an constant or even a global variable is faster. The effect on small arrays (less than 10 elements) is not significant. Arrays with 10 elements or more are reported here. The effect is also more important on functions that are called often, or within loops. <?php // with constants, for functions const ARRAY = array(1,2,3,4,5,6,7,8,9,10,11); function foo() { array = ARRAY; //more code } // with class constants, for methods class x { const ARRAY = array(1,2,3,4,5,6,7,8,9,10,11); function foo() { array = self::ARRAY; //more code } } // with properties, for methods class x { private array = array(1,2,3,4,5,6,7,8,9,10,11); function foo() { array = this->array; //more code } } // injection, leveraging default values function foo(array = array(1,2,3,4,5,6,7,8,9,10,11)) { //more code } // local cache with static function foo() { static array; if (array === null) { array = array(1,2,3,4,5,6,7,8,9,10,11); } //more code } // Avoid creating the same array all the time in a function class x { function foo() { // assign to non local variable is OK. // Here, to a property, though it may be better in a __construct or as default values this->s = array(1,2,3,4,5,6,7,8,9,10,11); // This is wasting resources, as it is done each time. array = array(1,2,3,4,5,6,7,8,9,10,11); } } ?>   Command Line Structures/NoAssignationInFunction Analyzers Performances Avoid Non Wordpress Globals¶ Refren using any global variable that is not Wordpress’s own. <?php my_hook() { // This is a Wordpress global GLOBALS['is_safari'] = true; // is_iphone7 is not a Wordpress variable global is_iphone7; } ?>  See also Global Variables  Command Line Wordpress/AvoidOtherGlobals Analyzers Wordpress Avoid Parenthesis¶ Avoid Parenthesis for language construct. Languages constructs are a few PHP native elements, that looks like functions but are not. Among other distinction, those elements cannot be directly used as variable function call, and they may be used with or without parenthesis. The usage of parenthesis actually give some feeling of confort, it won’t prevent PHP from combining those argument with any later operators, leading to unexpected results. Even if most of the time, usage of parenthesis is legit, it is recommended to avoid them.  Command Line Structures/PrintWithoutParenthesis Analyzers Analyze Avoid Those Crypto¶ The following cryptographic algorithms are considered unsecure, and should be replaced with new and more performant algorithms. MD2, MD4, MD5, SHA0, SHA1, CRC, DES, 3DES, RC2, RC4. When possible, avoid using them, may it be as PHP functions, or hashing function configurations (mcrypt, hash...).  Command Line Security/AvoidThoseCrypto Analyzers Security Avoid Using stdClass¶ stdClass is the default class for PHP. It is instantiated when PHP needs to return a object, but no class is specifically available. It is recommended to avoid instantiating this class, nor use it is any way. <?php json = '{a:1,b:2,c:3}'; object = json_decode(json); // object is a stdClass, as returned by json_decode // Fast building of o a = []; a['a'] = 1; a['b'] = 2; a['c'] = 3; json_encode( (object) a); // Slow building of o o = new stdClass(); o->a = 1; o->b = 2; o->c = 3; json_encode(o); ?>  If you need a stdClass object, it is faster to build it as an array, then cast it, than instantiate stdClass. This is a micro-optimisation.  Command Line Php/UseStdclass Analyzers Analyze Avoid array_push()¶ array_push() is slower than the [] operator. This is also true if the [] operator is called several times, while array_push() may be called only once. And using count after the push is also faster than collecting array_push() return value. <?php a = [1,2,3]; // Fast version a[] = 4; a[] = 5; a[] = 6; a[] = 7; count = count(a); // Slow version array_push(a, 4); count = array_push(a, 5,6,7); // Multiple version : a[] = 1; a[] = 2; a[] = 3; array_push(a, 1, 2, 3); ?>  This is a micro-optimisation.  Command Line Performances/AvoidArrayPush Analyzers Performances Avoid array_unique()¶ The native function array_unique() is much slower than using other alternative, such as array_count_values(), array_flip()/array_keys(), or even a foreach() loops. <?php // using array_unique() uniques = array_unique(someValues); // When values are strings or integers uniques = array_keys(array_count_values(someValues)); uniques = array_flip(array_flip(someValues)) //even some loops are faster. uniques = []; foreach(someValues as s) { if (!in_array(uniques, s)) { uniques[] s; } } ?>   Command Line Structures/NoArrayUnique Analyzers Performances Avoid get_class()¶ get_class() should be replaced with the instanceof operator to check the class of an object. get_class() will only compare the full namespace name of the object’s class, while instanceof actually resolve the name, using the local namespace and aliases. <?php use Stdclass as baseClass; function foo(arg) { // Slow and prone to namespace errors if (get_class(arg) === 'Stdclass') { // doSomething() } } function bar(arg) { // Faster, and uses aliases. if (arg instanceof baseClass) { // doSomething() } } ?>   Command Line Structures/UseInstanceof Analyzers none Avoid sleep()/usleep()¶ sleep() and usleep() help saturate the web server. Pausing the script for a specific amount of time means that the Web server is also making all related ressources sleep, such as database, sockets, session, etc. This may used to set up a DOS on the server. <?php begin = microtime(true); checkLogin(user, password); end = microtime(true); // Making all login checks looks the same usleep(1000000 - (end - begin) * 1000000); // Any hit on this page now uses 1 second, no matter if load is high or not // Is it now possible to saturate the webserver in 1 s ? ?>  As much as possible, avoid delaying the end of the script. sleep() and usleep() have less impact in commandline (CLI).  Command Line Security/NoSleep Analyzers Security Bail Out Early¶ When using conditions, it is recommended to return in the then, and avoid else clause. The main benefit is to make clear the method applies a condition, and stop quickly went it is not satisfied. The main sequence is then focused on the useful code. This works with break, continue too, inside loops. <?php // Bailing out early, low level of indentation function foo1(a) { if (a > 0) { return false; } a++; return a; } // Works with continue too foreach(array as a => b) { if (a > 0) { continue false; } a++; return a; } // No need for else function foo2(a) { if (a > 0) { return false; } else { a++; } return a; } // No need for else : return goes into then. function foo3(a) { if (a < 0) { a++; } else { return false; } return a; } ?>   Command Line Structures/BailOutEarly Analyzers Analyze Binary Glossary¶ List of all the integer values using the binary format. <?php a = 0b10; b = 0B0101; ?>   Command Line Type/Binary Analyzers CompatibilityPHP53 Bracketless Blocks¶ PHP allows one liners as for(), foreach(), while(), do..while() loops, or as then/else expressions. It is generally considered a bad practice, as readability is lower and there are non-négligeable risk of excluding from the loop the next instruction. <?php // Legit one liner foreach(range('a', 'z') as letter) ++letterCount; // More readable version, even for a one liner. foreach(range('a', 'z') as letter) { ++letterCount; } ?>  switch() cannot be without bracket.  Command Line Structures/Bracketless Analyzers Coding Conventions Break Outside Loop¶ Starting with PHP 7, break or continue that are outside a loop (for, foreach(), do...while() <http://php.net/manual/en/control-structures.while.php>_, while()) or a switch() statement won’t compile anymore. It is not possible anymore to include a piece of code inside a loop that will then break. <?php // outside a loop : This won't compile break 1; foreach(array as a) { break 1; // Compile OK break 2; // This won't compile, as this break is in one loop, and not 2 } foreach(array as a) { foreach(array2 as a2) { break 2; // OK in PHP 5 and 7 } } ?>   Command Line Structures/BreakOutsideLoop Analyzers Analyze, CompatibilityPHP70, CompatibilityPHP71 Break With 0¶ Cannot break 0, as this makes no sense. Break 1 is the minimum, and is the default value. <?php // Can't break 0. Must be 1 or more, depending on the level of nesting. for(i = 0; i < 10; i++) { break 0; } for(i = 0; i < 10; i++) { for(j = 0; j < 10; j++) { break 2; } } ?>   Command Line Structures/Break0 Analyzers Analyze, CompatibilityPHP53 Break With Non Integer¶ When using a break, the argument of the operator must be a positive non-null integer literal or be omitted. Other values were acceptable in PHP 5.3 and previous version, but this is now reported as an error. <?php // Can't break a, even if it contains an integer. a = 1; for(i = 0; i < 10; i++) { break a; } // can't break on float for(i = 0; i < 10; i++) { for(j = 0; j < 10; j++) { break 2.2; } } ?>   Command Line Structures/BreakNonInteger Analyzers Analyze, CompatibilityPHP54, CompatibilityPHP70, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP71 Buried Assignation¶ Those assignations are buried in the code, and placed in unexpected situations. They will be difficult to spot, and may be confusing. It is advised to place them in a more visible place.  Command Line Structures/BuriedAssignation Analyzers Analyze Calltime Pass By Reference¶ PHP doesn’t allow when a value is turned into a reference at functioncall, since PHP 5.4. Either the function use a reference in its signature, either the reference won’t pass.  Command Line Structures/CalltimePassByReference Analyzers Analyze, CompatibilityPHP54, CompatibilityPHP70, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP71 Can’t Extend Final¶ It is not possible to extend final classes. Since PHP fails with a fatal error, this means that the extending class is probably not used in the rest of the code. Check for dead code. <?php // File Foo final class foo { public final function bar() { // doSomething } } ?>  In a separate file : <?php // File Bar class bar extends foo { } ?>   Command Line Classes/CantExtendFinal Analyzers Analyze, Dead code Cant Use Return Value In Write Context¶ Until PHP 5.5, it was not possible to use directly function calls inside an empty() function call : they were met with a ‘Can’t use function return value in write context’ fatal error. <?php function foo(boolean) { return boolean; } // Valid since PHP 5.5 echo empty(foo(true)) : 'true' : 'false'; ?>  This also applies to methodcalls, static or not.  Command Line Php/CantUseReturnValueInWriteContext Analyzers CompatibilityPHP53, CompatibilityPHP54 Cast To Boolean¶ This expression may be reduced by casting to boolean type. <?php variable = condition == 'met' ? 1 : 0; // Same as variable = (bool) condition == 'met'; variable = condition == 'met' ? 0 : 1; // Same as (Note the condition inversion) variable = (bool) condition != 'met'; // also, with an indentical condition variable = !(bool) condition == 'met'; ?>   Command Line Structures/CastToBoolean Analyzers Analyze Catch Overwrite Variable¶ The try...catch structure uses some variables that also in use in this scope. In case of a caught exception, the exception will be put in the catch variable, and overwrite the current value, loosing some data. It is recommended to use another name for these catch variables.  Command Line Structures/CatchShadowsVariable clearPHP no-catch-overwrite Analyzers Analyze Class Const With Array¶ Constant defined with const keyword may be arrays but only stating with PHP 5.6. Define never accept arrays : it only accepts scalar values.  Command Line Php/ClassConstWithArray Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 Class Function Confusion¶ Avoid classes and functions bearing the same name. When functions and classes bear the same name, calling them may be confusing. This may also lead to forgotten ‘new’ keyword. <?php class foo {} function foo() {} // Forgetting the 'new' operator is easy object = new foo(); object = foo(); ?>   Command Line Php/ClassFunctionConfusion Analyzers Analyze Class Name Case Difference¶ The spotted classes are used with a different case than their definition. While PHP will accept this, this makes the code harder to read. Most of the time, this is also a violation of coding conventions.  Command Line Classes/WrongCase Analyzers Coding Conventions, Analyze Class Should Be Final By Ocramius¶ ‘Make your classes always final, if they implement an interface, and no other public methods are defined’. When a class should be final, as explained by Ocramiux (Marco Pivetti). Full article : When to declare classes final. <?php interface i1 { function i1() ; } final class finalClass implements i1 { // public interface function i1 () {} // private method private function a1 () {} } ?>   Command Line Classes/FinalByOcramius Analyzers Analyze Class, Interface Or Trait With Identical Names¶ The following names are used at the same time for classes, interfaces or traits. For example, class a {} interface a {} trait a {} Even if they are in different namespaces, this makes them easy to confuse. Besides, it is recommended to have markers to differentiate classes from interfaces from traits.  Command Line Classes/CitSameName Analyzers Analyze Classes Mutually Extending Each Other¶ Those classes are extending each other, creating an extension loop. PHP will yield a fatal error at running time, even if it is compiling the code. <?php // This code is lintable but won't run class Foo extends Bar { } class Bar extends Foo { } // The loop may be quite large class Foo extends Bar { } class Bar extends Bar2 { } class Bar2 extends Foo { } ?>   Command Line Classes/MutualExtension Analyzers Analyze Close Tags¶ PHP manual recommends that script should be left open, without the final closing ?>. This way, one will avoid the infamous bug ‘Header already sent’, associated with left-over spaces, that are lying after this closing tag.  Command Line Php/CloseTags clearPHP leave-last-closing-out Analyzers Coding Conventions Closure May Use this¶ When closure were introduced in PHP, they couldn’t use the this variable, making is cumbersome to access local properties when the closure was created within an object. This is not the case anymore since PHP 5.4.  Command Line Php/ClosureThisSupport Analyzers Analyze, CompatibilityPHP53 Common Alternatives¶ In the following conditional structures, expressions were found that are common to both ‘then’ and ‘else’. It may be interesting, though not always possible, to put them both out of the conditional, and reduce line count. <?php if (c == 5) { b = strtolower(b[2]); a++; } else { b = strtolower(b[2]); b++; } ?>  may be rewritten in : <?php b = strtolower(b[2]); if (c == 5) { a++; } else { b++; } ?>   Command Line Structures/CommonAlternatives Analyzers Analyze Compare Hash¶ When comparing hash values, it is important to use the strict comparison : === or !==. In a number of situations, the hash value will start with ‘0e’, and PHP will understand that the comparison involves integers : it will then convert the strings into numbers, and it may end up converting them to 0. Here is an example <?php // The two following passwords hashes matches, while they are not the same. hashed_password = 0e462097431906509000000000000; if (hash('md5','240610708',false) == hashed_password) { print Matched.\n; } ?>  You may also use password_hash() and password_verify(). See also Magic Hashes.  Command Line Security/CompareHash clearPHP strict-comparisons Analyzers Security Compared Comparison¶ Usually, comparison are sufficient, and it is rare to have to compare the result of comparison. Check if this two-stage comparison is really needed.  Command Line Structures/ComparedComparison Analyzers Analyze Concrete Visibility¶ Methods that implements an interface in a class must be public.  Command Line Interfaces/ConcreteVisibility Analyzers Analyze Confusing Names¶ The following variables’s name are very close and may lead to confusion. Variables are 3 letters long (at least). Variables names build with an extra ‘s’ are omitted. Variables may be scattered across the code, or close to each other. <?php // Variable names with one letter difference fWScale = 1; fHScale = 1; fScale = 2; oFrame = 3; iFrame = new Foo(); v2_norm = array(); v1_norm = 'string'; exept11 = 1; exept10 = 2; exept8 = 3; // This even looks like a typo privileges = 1; privilieges = true; // This is not reported : Adding extra s is tolerated. rows[] = row; ?>   Command Line Variables/CloseNaming Analyzers Analyze Const With Array¶ The const keyword supports array since PHP 5.6.  Command Line Php/ConstWithArray Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 Constant Class¶ A class or an interface only made up of constants. Constants usually have to be used in conjunction of some behavior (methods, class...) and never alone. As such, they should be PHP constants (build with define or const), or included in a class with other methods and properties.  Command Line Classes/ConstantClass Analyzers Analyze Constant Comparison¶ Constant to the left or right is a favorite. Comparisons are commutative : they may be a == B or B == a. The analyzed code show less than 10% of one of the two : for consistency reasons, it is recommended to make them all the same. Putting the constant on the left is also called ‘Yoda Comparison’, as it mimics the famous characters style of speech. It prevents errors like ‘B = a’ where the comparison is turned into an assignation. The natural way is to put the constant on the right. It is often less surprising. Every comparison operator is used when finding the favorite. <?php // if (a === B) { doSomething(); } if (c > D) { doSomething(); } if (e !== G) { doSomething(); } do { doSomething(); } while (f === B); while (a === B) { doSomething(); } // be consistent if (B === a) {} // Compari if (B <= a) {} ?>   Command Line Structures/ConstantComparisonConsistance Analyzers Coding Conventions Constant Scalar Expressions¶ Starting with PHP 5.6, it is possible to define constant that are the result of expressions. Those expressions (using simple operators) may only manipulate other constants, and all values must be known at compile time. This is not compatible with previous versions.  Command Line Structures/ConstantScalarExpression Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 Constants Created Outside Its Namespace¶ Constants Created Outside Its Namespace. Using the define() function, it is possible to create constant outside their namespace, but using the fully qualified namespace. <?php namespace A\B { // define A\B\C as 1 define('C', 1); } namespace D\E { // define A\B\C as 1, while outside the A\B namespace define('A\B\C', 1); } ?>  However, this makes the code confusing and difficult to debug. It is recommended to move the constant definition to its namespace.  Command Line Constants/CreatedOutsideItsNamespace Analyzers Analyze Constants With Strange Names¶ List of constants being defined with names that are incompatible with PHP standards. <?php // Define a valid PHP constant define('ABC', 1); const ABCD = 2; // Define an invalid PHP constant define('ABC!', 1); echo defined('ABC!') ? constant('ABC!') : 'Undefined'; // Const doesn't allow illegal names ?>   Command Line Constants/ConstantStrangeNames Analyzers Analyze Could Be Class Constant¶ When a property is defined and read, but never modified, it may be a constant. <?php class foo { // this->bar is never modified. private bar = 1; // this->foofoo is modified, at least once private foofoo = 2; function method(a) { this->foofoo = this->bar + a + this->foofoo; return this->foofoo; } } ?>  Starting with PHP 5.6, even array() may be defined as constants.  Command Line Classes/CouldBeClassConstant Analyzers Analyze Could Be Protected Property¶ Those properties are declared public, but are never used publicly. They may be made protected. <?php class foo { // Public, and used publicly public publicProperty; // Public, but never used outside the class or its children public protectedProperty; function bar() { this->protectedProperty = 1; } } foo = new Foo(); foo->publicProperty = 3; ?>  This property may even be made private.  Command Line Classes/CouldBeProtectedProperty Analyzers Analyze Could Be Static¶ This global is only used in one function or method. It may be called ‘static’, instead of global. This allows you to keep the value between call to the function, but will not be accessible outside this function. <?php function foo( ) { static variableIsReservedForX; // only accessible within foo( ), even between calls. global variableIsGlobal; // accessible everywhere in the application } ?>   Command Line Structures/CouldBeStatic Analyzers Analyze Could Be Typehinted Callable¶ Those arguments may use the callable Typehint. ‘callable’ is a PHP keyword that represents callback functions. Those may be used in dynamic function call, like function(); or as callback functions, like with array_map(); callable may be a string representing a function name or a static call (including ::), an array with two elements, (a class or object, and a method), or a closure. When arguments are used to call a function, but are not marked with ‘callable’, they are reported by this analysis. <?php function foo(callable callable) { // very simple callback return callable(); } function foo2(array, callable) { // very simple callback return array_map(array, callable); } ?>  See also Callback / callable.  Command Line Functions/CouldBeCallable Analyzers Analyze Could Return Void¶ The following functions may bear the Void return typeHint. <?php // This can be Void function foo(&a) { ++a; return; } // This can't be Void function bar(a) { ++a; return a; } ?>   Command Line Functions/CouldReturnVoid Analyzers Analyze Could Use Alias¶ This long name may be reduced by using an available alias. <?php use a\b\c; // This may be reduced with the above alias new a\b\c\d(); // This too new a\b\c\d\e\f(); // This yet again new a\b\c(); ?>   Command Line Namespaces/CouldUseAlias Analyzers Analyze Could Use Short Assignation¶ Some operators have a compact ‘do-and-assign’ version. They looks like a compacted version for = and the operator. This syntax is good for readability, and saves some memory in the process. <?php a = a + 0; a += 0; b = b - 1; b -= 1; c = c * 2; c *= 2; d = d / 3; d /= 3; e = e % 4; e %= 4; f = f | 5; f |= 5; g = g & 6; g &= 6; h = h ^ 7; h ^= 7; i = i >> 8; i >>= 8; j = j << 9; j <<= 9; ?>   Command Line Structures/CouldUseShortAssignation clearPHP use-short-assignations Analyzers Analyze, Performances Could Use __DIR__¶ Use __DIR__ function to access the current file’s parent directory. <?php assert(dirname(__FILE__) == __DIR__); ?>  __DIR__ has been introduced in PHP 5.3.0.  Command Line Structures/CouldUseDir Analyzers Analyze Could Use self¶ ‘self’ keyword refers to the current class, or any of its parents. Using it is just as fast as the full classname, it is as readable and it is will not be changed upon class or namespace change. It is also routinely used in traits : there, ‘self’ represents the class in which the trait is used, or the trait itself. <?php class x { const FOO = 1; public function bar() { return self::FOO; // same as return x::FOO; } } ?>   Command Line Classes/ShouldUseSelf Analyzers Analyze Curly Arrays¶ It is possible to access individual elements in an array by using its offset between square brackets [] or curly brackets {}. Curly brackets are seldom used, and will probably confuse or surprise the reader. It is recommended not to used them.  Command Line Arrays/CurlyArrays Analyzers Coding Conventions Dangling Array References¶ Always unset a referenced-variable used in a loop. It is highly recommended to unset blind variables when they are set up as references after a loop. <?php array = array(1,2,3,4); foreach(array as &a) { a += 1; } // This only unset the reference, not the value unset(a); // Dangling array problem foreach(array as &a) { a += 1; } //array === array(3,4,5,6); // This does nothing (apparently) foreach(array as a) {} //array === array(3,4,5,6); ?>  When omitting this step, the next loop that will also require this variable will deal with garbage values, and produce unexpected results. See also : No Dangling Reference.  Command Line Structures/DanglingArrayReferences clearPHP no-dangling-reference Analyzers Analyze Deep Definitions¶ Structures, such as functions, classes, interfaces, traits, etc. may be defined anywhere in the code, including inside functions. This is legit code for PHP. Since the availability of __autoload, there is no need for that kind of code. Structures should be defined, and accessible to the autoloading. Inclusion and deep definitions should be avoided, as they compell code to load some definitions, while autoloading will only load them if needed. Functions are excluded from autoload, but shall be gathered in libraries, and not hidden inside other code. Constants definitions are tolerated inside functions : they may be used for avoiding repeat, or noting the usage of such function.  Command Line Functions/DeepDefinitions Analyzers Analyze Define With Array¶ PHP 7.0 has the ability to define an array as a constant, using the define() native call. This was not possible until that version, only with the const keyword.  Command Line Php/DefineWithArray Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Dependant Trait¶ Traits should be autonomous. It is recommended to avoid depending on methods or properties that should be in the using class. The following traits make usage of methods and properties, static or not, that are not defined in the trait. This means the host class must provide those methods and properties, but there is no way to enforce this. This may also lead to dead code : when the trait is removed, the host class have unused properties and methods. <?php // autonomous trait : all it needs is within the trait trait t { private p = 0; function foo() { return ++this->p; } } // dependant trait : the host class needs to provide some properties or methods trait t2 { function foo() { return ++this->p; } } class x { use t2; private p = 0; } ?>   Command Line Traits/DependantTrait Analyzers Analyze Deprecated Code¶ The following functions have been deprecated in PHP. Whatever the version you are using, it is recommended to stop using them and replace them with a durable equivalent.  Command Line Php/Deprecated clearPHP no-deprecated Analyzers Analyze Dereferencing String And Arrays¶ PHP 5.5 introduced the direct dereferencing of strings and array. No need anymore for an intermediate variable between a string and array (or any expression generating such value) and accessing an index. x = array(4,5,6); y = x[2] ; // is 6 May be replaced by y = array(4,5,6)[2]; y = [4,5,6][2];  Command Line Structures/DereferencingAS Analyzers CompatibilityPHP53, CompatibilityPHP54 Direct Injection¶ The following code act directly upon PHP incoming variables like _GET and _POST. This make those snippet very unsafe.  Command Line Security/DirectInjection Analyzers Security Don’t Change Incomings¶ PHP hands over a lot of information using special variables like _GET, _POST, etc... Modifying those variables and those values inside de variables means that the original content is lost, while it will still look like raw data, and, as such, will be untrustworthy. <?php // filtering and keeping the incoming value. _DATA'id'] = (int) _GET['id']; // filtering and changing the incoming value. _GET['id'] = strtolower(_GET['id']); ?>  It is recommended to put the modified values in another variable, and keep the original one intact.  Command Line Structures/NoChangeIncomingVariables Analyzers Analyze Dont Change The Blind Var¶ When using a foreach(), the blind variables are a copy. It is confusing to change them. <?php foo = [1, 2, 3]; foreach(foo as bar) { // bar is updated but its final value is lost print bar . ' => ' . (bar + 1) . PHP_EOL; // if bar + 1 is repeated several times, consider assigning it to a variable. foobar(bar + 1); } foo = [1, 2, 3]; foreach(foo as bar) { // bar is updated but its final value is lost print bar . ' => ' . (++bar) . PHP_EOL; // Now that bar is reused, it is easy to confuse its value foobar(bar); } ?>   Command Line Structures/DontChangeBlindKey Analyzers Analyze Dont Echo Error¶ It is recommended to avoid displaying error messages directly to the browser. <?php // Inside a 'or' test mysql_connect('localhost', user, pass) or die(mysql_error()); // Inside a if test result = pg_query( db, query ); if( !result ) { echo Erreur SQL: . pg_error(); exit; } ?>  Error messages should be logged, but not displayed.  Command Line Security/DontEchoError Analyzers Analyze, Security Double Assignation¶ This happens when a container (variable, property, array index) is assigned with values twice in a row. One of them is probably a debug instruction, that was forgotten. <?php // Normal assignation a = 1; // Double assignation b = 2; b = 3; ?>   Command Line Structures/DoubleAssignation Analyzers Analyze Double Instructions¶ Twice the same call in a row. This is worth a check. <?php ?>   Command Line Structures/DoubleInstruction Analyzers Analyze Drop Else After Return¶ Avoid else clause when the then clause returns, but not the else. The else may simply be set in the main sequence of the function. This is also true if else has a return, and then not : simply reverse the condition. <?php // drop the else if (a) { return a; } else { doSomething(); } // drop the then if (b) { doSomething(); } else { return a; } // return in else and then if (a3) { return a; } else { b = doSomething(); return b; } ?>   Command Line Structures/DropElseAfterReturn Analyzers Analyze Echo Or Print¶ Echo and print have the same functional use. <?= is also considered in this analysis. There seems to be a choice that is not enforced : one form is dominent, (> 90%) while the others are rare. The analyzed code has less than 10% of one of the three : for consistency reasons, it is recommended to make them all the same. It happens that print, echo or <?= are used depending on coding style and files. One file may be consistently using print, while the others are all using echo. <?php echo 'a'; echo 'b'; echo 'c'; echo 'd'; echo 'e'; echo 'f'; echo 'g'; echo 'h'; echo 'i'; echo 'j'; echo 'k'; // This should probably be written 'echo'; print 'l'; ?>   Command Line Structures/EchoPrintConsistance Analyzers Coding Conventions Echo With Concat¶ Optimize your echo’s by not concatenating at echo() time, but serving all argument separated. This will save PHP a memory copy. If values (literals and variables) are small enough, this won’t have impact. Otherwise, this is less work and less memory waste. <?php echo a, ' b ', c; ?>  instead of <?php echo a . ' b ' . c; echo a b c; ?>   Command Line Structures/EchoWithConcat clearPHP no-unnecessary-string-concatenation Analyzers Performances, Analyze Else If Versus Elseif¶ Always use elseif instead of else and if. “The keyword elseif SHOULD be used instead of else if so that all control keywords look like single words”. Quoted from the PHP-FIG documentation <?php // Using elseif if (a == 1) { doSomething(); } elseif (a == 2) { doSomethingElseIf(); } else { doSomethingElse(); } // Using else if if (a == 1) { doSomething(); } else if (a == 2) { doSomethingElseIf(); } else { doSomethingElse(); } // Using else if, no {} if (a == 1) doSomething(); else if (a == 2) doSomethingElseIf(); else doSomethingElse(); ?>  .  Command Line Structures/ElseIfElseif Analyzers Analyze Empty Blocks¶ The listed control structures are empty, or have one of the commanded block empty. It is recommended to remove those blocks, so as to reduce confusion in the code. <?php foreach(foo as bar) ; // This block seems erroneous foobar++; if (a === b) { doSomething(); } else { // Empty block. Remove this } // Blocks containing only empty expressions are also detected for(i = 0; i < 10; i++) { ; } // Although namespaces are not control structures, they are reported here namespace A; namespace B; ?>   Command Line Structures/EmptyBlocks Analyzers Analyze Empty Classes¶ List of empty classes. Classes that are directly derived from an exception are omited. <?php //Empty class class foo extends bar {} //Not an empty class class foo2 extends bar { const FOO = 2; } //Not an empty class, as derived from Exception class barException extends \Exception {} ?>   Command Line Classes/EmptyClass Analyzers Analyze Empty Function¶ Function or method whose body is empty. Such functions or methods are rarely useful. As a bare minimum, the function should return some useful value, even if constant. <?php // classic empty function function emptyFunction() {} class bar { // classic empty method function emptyMethod() {} // classic empty function function emptyMethodWithParent() {} } class barbar extends bar { // NOT an empty method : it overwrites the parent method function emptyMethodWithParent() {} } ?>   Command Line Functions/EmptyFunction Analyzers Analyze Empty Instructions¶ Empty instructions are part of the code that have no instructions. This may be trailing semi-colon or empty blocks for if-then structures. condition = 3;;;; if (condition) { }  Command Line Structures/EmptyLines Analyzers Dead code, Analyze Empty Interfaces¶ Empty interfaces. Interfaces should contains some function, and not be totally empty. <?php // an empty interface interface empty {} // an normal interface interface normal { public function i() ; } // an constant interface interface constantsOnly { const FOO = 1; } ?>   Command Line Interfaces/EmptyInterface Analyzers Analyze Empty List¶ Empty list() are not allowed anymore in PHP 7. There must be at least one variable in the list call. <?php //Not accepted since PHP 7.0 list() = array(1,2,3); //Still valid PHP code list(,x) = array(1,2,3); ?>   Command Line Php/EmptyList Analyzers Analyze, CompatibilityPHP70, CompatibilityPHP71 Empty Namespace¶ Declaring a namespace in the code and not using it for structure declarations (classes, interfaces, etc...) or global instructions is useless. Using simple style : <?php namespace X; // This is useless namespace Y; class foo {} ?>  Using bracket-style syntax : <?php namespace X { // This is useless } namespace Y { class foo {} } ?>   Command Line Namespaces/EmptyNamespace clearPHP no-empty-namespace Analyzers Analyze, Dead code Empty Slots In Arrays¶ PHP tolerates the last element of an array to be empty. <?php a = array( 1, 2, 3, ); b = [ 4, 5, ]; ?>   Command Line Arrays/EmptySlots Analyzers Coding Conventions Empty Traits¶ List of all empty trait defined in the code. <?php // empty trait trait t { } // Another empty trait trait t2 { use t; } ?>  Such traits may be reserved for future use. They may also be forgotten, and dead code.  Command Line Traits/EmptyTrait Analyzers Analyze Empty Try Catch¶ The code does try, then catch errors but do no act upon the error. <?php try { doSomething(); } catch (Throwable e) { // simply ignore this } ?>  At worst, the error should be logged, so as to measure the actual usage of the catch expression. catch( Exception e) (PHP 5) or catch(Throwable e) with empty catch block should be banned, as they will simply ignore any error.  Command Line Structures/EmptyTryCatch Analyzers Analyze Empty With Expression¶ empty() doesn’t accept expressions until PHP 5.5. Until then, it is necessary to store the result of the expression in a variable and then, test it with empty(). <?php // PHP 5.5+ empty() usage if (empty(strtolower(b . c))) { doSomethingWithoutA(); } // Compatible empty() usage a = strtolower(b . c); if (empty(a)) { doSomethingWithoutA(); } ?>   Command Line Structures/EmptyWithExpression Analyzers CompatibilityPHP55, CompatibilityPHP70, CompatibilityPHP56, CompatibilityPHP71 Encoded Simple Letters¶ Some simple letters are written in escape sequence. Usually, escape sequences are made to encode unusual characters. Using escape sequences for simple characters, like letters or numbers is suspicious. <?php // This escape sequence makes eval hard to spot a = ev1l; a('php_info();'); // With a PHP 7.0 unicode code point sequence a = ev\u{41}l; a('php_info();'); // With a PHP 5.0+ hexadecimal sequence a = ev\x41l; a('php_info();'); ?>   Command Line Security/EncodedLetters Analyzers Security Eval() Usage¶ Using eval() is bad for performances (compilation time), for caches (it won’t be compiled), and for security (if it includes external data). <?php // Avoid using incoming data to build the eval() expression : any filtering error leads to PHP injection mathExpression = _GET['mathExpression']; mathExpression = preg_replace('#[^0-9+\-*/\(/)]#is', '', mathExpression); // expecting 1+2 literalCode = 'a = '.mathExpression.';'; eval(literalCode); echo a; // If eval'ed code is known at compile time, it is best to put it inline literalCode = 'phpinfo();'; eval(literalCode); ?>  Most of the time, it is possible to replace the code by some standard PHP, like variable variable for accessing a variable for which you have the name. At worse, including a pre-generated file will be faster. For PHP 7.0 and later, it is important to put eval() in a try..catch expression.  Command Line Structures/EvalUsage clearPHP no-eval Analyzers Analyze, Performances Exception Order¶ When catching exception, the most specialized exceptions must be in the early catch, and the most general exceptions must be in the later catch. Otherwise, the general catches intercept the exception, and the more specialized will not be read. <?php class A extends \Exception {} class B extends A {} try { throw new A(); } catch(A a1) { } catch(B b2 ) { // Never reached, as previous Catch is catching the early worm } ?>   Command Line Exceptions/AlreadyCaught Analyzers Dead code Exit() Usage¶ Using exit or die() in the code makes the code untestable (it will break unit tests). Morover, if there is no reason or string to display, it may take a long time to spot where the application is stuck. <?php // Throw an exception, that may be caught somewhere throw new \Exception('error'); // Dying with error message. die('error'); function foo() { //exiting the function but not dying if (somethingWrong()) { return true; } } ?>  Try exiting the function/class with return, or throw exception that may be caught later in the code.  Command Line Structures/ExitUsage clearPHP no-exit Analyzers Analyze Exponent Usage¶ Usage of the ** operator or **=, to make exponents. <?php eight = 2 ** 3; sixteen = 4; sixteen \*\*\= 2; ?>   Command Line Php/ExponentUsage Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 Failed Substr Comparison¶ The extracted string must be of the size of the compared string. This is also true for negative lengths. <?php // Possible comparison if (substr(a, 0, 3) === 'abc') { } if (substr(b, 4, 3) === 'abc') { } // Always failing if (substr(a, 0, 3) === 'ab') { } if (substr(a, 3, -3) === 'ab') { } // Omitted in this analysis if (substr(a, 0, 3) !== 'ab') { } ?>   Command Line Structures/FailingSubstrComparison Analyzers Analyze Fetch One Row Format¶ When reading results with ext/Sqlite3, it is recommended to explicitely request SQLITE3_NUM or SQLITE3_ASSOC, while avoiding the default value and SQLITE3_BOTH. <?php res = database->query(query); // Fastest version, but less readable row = res->fetchArray(\SQLITE3_NUM); // Almost the fastest version, and more readable row = res->fetchArray(\SQLITE3_ASSOC); // Default version. Quite slow row = res->fetchArray(); // Worse case row = res->fetchArray(\SQLITE3_BOTH); ?>  This is a micro-optimisation. The difference may be visible with 200k rows fetches, and measurable with 10k.  Command Line Performances/FetchOneRowFormat Analyzers Performances For Using Functioncall¶ It is recommended to avoid functioncall in the for() statement. <?php // Fastest way nb = count(array); for(i = 0; i < nb; ++i) { doSomething(i); } // Same as above, but slow for(i = 0; i < count(array); ++i) { doSomething(i); } // Same as above, but slow foreach(portions as &portion) { // here, array_sum() doesn't depends on the grade. It should be out of the loop portion = portion / array_sum(portions); } total = array_sum(portion); foreach(portion as &portion) { portion = portion / total; } ?>  This is true with any kind of functioncall that returns the same value throughout the loop.  Command Line Structures/ForWithFunctioncall clearPHP no-functioncall-in-loop Analyzers Analyze, Performances Foreach Don’t Change Pointer¶ In PHP 7.0, the foreach loop won’t change the internal pointer of the array, but will work on a copy. So, applying array pointer’s functions such as current() or next() to the source array won’t have the same behavior than in PHP 5. This anly applies when a foreach() by reference is used. <?php numbers = range(1, 10); next(numbers); foreach(numbers as &number){ print number; print current(numbers).\n; // Always } ?>   Command Line Php/ForeachDontChangePointer Analyzers CompatibilityPHP70, CompatibilityPHP71 Foreach Needs Reference Array¶ When using foreach with a reference as value, the source must be a referenced array, which is a variable (or array or property or static property). When the array is the result of an expression, the array is not kept in memory after the foreach loop, and any change made with & are lost. This will do nothing <?php foreach(array(1,2,3) as &value) { value *= 2; } ?>  This will have an actual effect <?php array = array(1,2,3); foreach(array as &value) { value *= 2; } ?>   Command Line Structures/ForeachNeedReferencedSource Analyzers Analyze Foreach Reference Is Not Modified¶ Foreach statement may loop using a reference, especially when the loop has to change values of the array it is looping on. In the spotted loop, reference are used but never modified. They may be removed.  Command Line Structures/ForeachReferenceIsNotModified Analyzers Analyze Foreach With list()¶ PHP 5.5 introduced the ability to use list in foreach loops. This was not possible in the earlier versions. <?php foreach(array as list(a, b)) { // do something } ?>  Previously, it was compulsory to extract the data from the blind array : <?php foreach(array as c) { list(a, b) = c; // do something } ?>   Command Line Structures/ForeachWithList Analyzers CompatibilityPHP53, CompatibilityPHP54 Forgotten Thrown¶ An exception is instantiated, but not thrown. <?php class MyException() extends \Exception { } if (error !== false) { // This looks like 'throw' was omitted new MyException(); } ?>   Command Line Exceptions/ForgottenThrown Analyzers Analyze Forgotten Visibility¶ Some classes elements (property, method, and constant in PHP 7.1) are missing their explicit visibility. By default, it is public. It should at least be mentioned as public, or may be reviewed as protected or private. final, static and abstract are not counted as visibility. Only public, private and protected. The PHP 4 var keyword is counted as undefined. Traits, classes and interfaces are checked. <?php // class X { const NO_VISIBILITY_CONST = 1; // For PHP 7.1 and later var noVisibilityProperty = 2; // Only with var function NoVisibilityForMethod() {} } ?>   Command Line Classes/NonPpp clearPHP always-have-visibility Analyzers Analyze Forgotten Whitespace¶ Those are white space that are at either end of a script : at the beginning or the end. Usually, such white space are forgotten, and may end up summoning the infamous ‘headers already sent’ error. It is better to remove them.  Command Line Structures/ForgottenWhiteSpace Analyzers Analyze Fully Qualified Constants¶ Constants defined with their namespace. When defining constants with define() function, it is possible to include the actual namespace : <?php define('a\b\c', 1); ?>  However, the name should be fully qualified without the initial . Here, abc constant will never be accessible as a namespace constant, though it will be accessible via the constant() function. Also, the namespace will be absolute, and not a relative namespace of the current one.  Command Line Namespaces/ConstantFullyQualified Analyzers Analyze Function Subscripting¶ This is a new PHP 5.4 feature, where one may use the result of a method directly as an array, given that the method actually returns an array. <?php function foo() { return array(1 => 'a', 'b', 'c'); } echo foo()[1]; // displays 'a'; // Function subscripting, the old way function foo() { return array(1 => 'a', 'b', 'c'); } x = foo(); echo x[1]; // displays 'a'; ?>  This was not possible until PHP 5.4. Is used to be necessary to put the result in a variable, and then access the desired index.  Command Line Structures/FunctionSubscripting Analyzers CompatibilityPHP53 Function Subscripting, Old Style¶ Since PHP 5.4, it is now possible use function results as an array, and access directly its element : <?php function foo() { return array(1 => 'a', 'b', 'c'); } echo foo()[1]; // displays 'a'; // Function subscripting, the old way function foo() { return array(1 => 'a', 'b', 'c'); } x = foo(); echo x[1]; // displays 'a'; ?>   Command Line Structures/FunctionPreSubscripting Analyzers Analyze Functions In Loop Calls¶ The following functions call each-other in a loop fashion : A -> B -> A. When those functions have no other interaction, the code is useless and should be dropped. <?php function foo1(a) { if (a < 1000) { return foo2(a + 1); } return a; } function foo2(a) { if (a < 1000) { return foo1(a + 1); } return a; } // if foo1 nor foo2 are called, then this is dead code. // if foo1 or foo2 are called, this recursive call should be investigated. ?>  Loops of size 2, 3 and 4 function are supported by this analyzer.  Command Line Functions/LoopCalling Analyzers Analyze, Performances Functions Removed In PHP 5.4¶ Those functions were removed in PHP 5.4.  Command Line Php/Php54RemovedFunctions Analyzers Analyze, CompatibilityPHP54 Functions Removed In PHP 5.5¶ Those functions were removed in PHP 5.5.  Command Line Php/Php55RemovedFunctions Analyzers CompatibilityPHP55 Getting Last Element¶ Getting the last element of an array is done with count() or end(). <?php array = [1, 2, 3]; // Best solutions, just as quick as each other last = array[count(array) - 1]; last = end(array); // Bad solutions // popping, but restoring the value. last = array_pop(array); array[] = last; // array_unshift would be even worse // reversing array last = array_reverse(array)[0]; // slicing the array last = array_slice(array, -1)[0]', last = current(array_slice(array, -1)); ); ?>   Command Line Arrays/GettingLastElement Analyzers Performances Global Inside Loop¶ The global keyword must be out of loops. It is evaluated each loop, slowing the whole process. <?php // Good idea, global is used once global total; foreach(a as b) { total += b; } // Bad idea, this is slow. foreach(a as b) { global total; total += b; } ?>   Command Line Structures/GlobalOutsideLoop Analyzers Performances Global Usage¶ List usage of globals variables, with global keywords or direct access to GLOBALS. It is recommended to avoid using global variables, at it makes it very difficult to track changes in values across the whole application.  Command Line Structures/GlobalUsage clearPHP no-global Analyzers Analyze Hardcoded Passwords¶ Hardcoded passwords in the code. Hardcoding passwords is a bad idea. Not only it make the code difficult to change, but it is an information leak. It is better to hide this kind of information out of the code. <?php ftp_server = '300.1.2.3'; // conn_id = ftp_connect(ftp_server); // login with username and password login_result = ftp_login(conn_id, 'login', 'password'); ?>   Command Line Functions/HardcodedPasswords clearPHP no-hardcoded-credential Analyzers Analyze, Security Hash Algorithms¶ There is a long but limited list of hashing algorithm available to PHP. The one found below doesn’t seem to be existing.  Command Line Php/HashAlgos Analyzers Analyze Hash Algorithms Incompatible With PHP 5.3¶ List of hash algorithms incompatible with PHP 5.3. They were introduced in newer version, and, as such, are not available with older versions. fnv132, fnv164 and joaat were added in PHP 5.4. <?php // Valid in PHP 5.4 + hash('joaat', 'string'); // Valid in PHP all versions hash('crc32', 'string'); ?>   Command Line Php/HashAlgos53 Analyzers CompatibilityPHP53 Hash Algorithms Incompatible With PHP 5.4/5¶ List of hash algorithms incompatible with PHP 5.4 and 5.5. They were introduced in newer version, or removed in PHP 5.4. As such, they are not available with older versions.  Command Line Php/HashAlgos54 Analyzers CompatibilityPHP54 Hexadecimal In String¶ Mark strings that may be confused with hexadecimal.  Command Line Type/HexadecimalString Analyzers CompatibilityPHP70, CompatibilityPHP71, CompatibilityPHP72 Hidden Use Expression¶ The use expression for namespaces should always be at te beginning of the namespace block. It is where everyone expect them, and it is less confusing than having them at various levels. <?php // This is visible use A; class B {} // This is hidden use C as D; class E extends D { use traitT; // This is a use for a trait function foo() { // This is a use for a closure return function (a) use (b) {} } } ?>   Command Line Namespaces/HiddenUse Analyzers Analyze Htmlentities Calls¶ htmlentities() and htmlspecialchars() are used to prevent injecting special characters in HTML code. As a bare minimum, they take a string and encode it for HTML. The second argument of the functions is the type of protection. The protection may apply to quotes or not, to HTML4 or 5, etc. It is highly recommended to set it explicitely. The third argument of the functions is the encoding of the string. In PHP 5.3, it as ‘ISO-8859-1’, in 5.4, was ‘UTF-8’, and in 5.6, it is now default_charset, a php.ini configuration that has the default value of ‘UTF-8’. It is highly recommended to set this argument too, to avoid distortions from the configuration. Also, note that arguments 2 and 3 are constants and string (respectively), and should be issued from the list of values available in the manual. Other values than those will make PHP use the default values.  Command Line Structures/Htmlentitiescall Analyzers Analyze Identical Conditions¶ These logical expressions contain members that are identical. This means those expressions may be simplified. <?php // twice a if (a || b || c || a) { } // Hiding is parenthesis is bad if ((a) ^ (a)) {} // expressions may be large if (a === 1 && 1 === a) {} ?>   Command Line Structures/IdenticalConditions Analyzers Analyze If With Same Conditions¶ Successive If / then structures that have the same condition may be either merged or have one of the condition changed. <?php if (a == 1) { doSomething(); } if (a == 1) { doSomethingElse(); } // May be replaced by if (a == 1) { doSomething(); doSomethingElse(); } ?>  Note that if the values used in the condition have been modified in the first if/then structure, the two distinct conditions may be needed. <?php // May not be merged if (a == 1) { // Check that this is really the situation a = checkSomething(); } if (a == 1) { doSomethingElse(); } ?>   Command Line Structures/IfWithSameConditions Analyzers Analyze Iffectations¶ Affectations that appears in a conditions. Iffectations are a way to do both a test and an affectations. They may also be typos, such as if (x = 3) { ... }, leading to a constant condition. <?php // an iffectation : assignation in a If condition if(connexion = mysql_connect(host, user, pass)) { res = mysql_query(connexion, query); } // Iffectation may happen in while too. while(row = mysql_fetch(res)) { store[] = row; } ?>   Command Line Structures/Iffectation Analyzers Analyze Illegal Name For Method¶ PHP has reserved usage of methods starting with __ for magic methods. It is recommended to avoid using this prefix, to prevent confusions. <?php class foo{ // Constructor function __construct() {} // Constructor's typo function __constructor() {} // Illegal function name, even as private private function __bar() {} } ?>   Command Line Classes/WrongName Analyzers Analyze Implement Is For Interface¶ When deriving classes, implements should be used for interfaces, and extends with classes.  Command Line Classes/ImplementIsForInterface Analyzers Analyze Implicit Global¶ Global variables, that are used in local scope with global keyword, but are not declared as global in the global scope. They may be mistaken with distinct values, while, in PHP, variables in the global scope are truly global.  Command Line Structures/ImplicitGlobal Analyzers Analyze Incompilable Files¶ Files that cannot be compiled, and, as such, be run by PHP. Scripts are linted against PHP versions 5.2, 5.3, 5.4, 5.5, 5.6, 7.0-dev and 7.1. This is usually undesirable, as all code must compile before being executed. It may simply be that such files are not compilable because they are not yet ready for an upcoming PHP version. <?php // Can't compile this : Print only accepts one argument print a, b, c; ?>  Code that is incompilable with older PHP versions means that the code is breaking backward compatibility : good or bad is project decision.  Command Line Php/Incompilable clearPHP no-incompilable Analyzers Analyze Indices Are Int Or String¶ Indices in an array notation such as array[‘indice’] may only be integers or string. Boolean, Null or float will be converted to their integer or string equivalent. <?php a = [true => 1, 1.0 => 2, 1.2 => 3, 1 => 4, '1' => 5, 0.8 => 6, 0x1 => 7, 01 => 8, null => 1, '' => 2, false => 1, 0 => 2, '0.8' => 3, '01' => 4, '2a' => 5 ]; print_r(a); ?>:: Array ( [1] => 8 [0] => 2 [] => 2 [0.8] => 3 [01] => 4 [2a] => 5 )  Decimal numbers are rounded to the closest integer; Null is transtyped to ‘’ (empty string); true is 1 and false is 0; Integers in strings are transtyped, while partial numbers or decimals are not analyzed in strings. As a general rule of thumb, only use integers or strings that don’t look like integers.  Command Line Structures/IndicesAreIntOrString Analyzers Analyze Indirect Injection¶ Look for injections through indirect usage for GPRC values (_GET, _POST, _REQUEST, _COOKIE). <?php a = _GET['a']; echo a; ?>   Command Line Security/IndirectInjection Analyzers Security Instantiating Abstract Class¶ Those code will raise a PHP fatal error at execution time : ‘Cannot instantiate abstract class’. The classes are actually abstract classes, and should be derived into a concrete class to be instantiated.  Command Line Classes/InstantiatingAbstractClass Analyzers Analyze Interpolation¶ The following strings contain variables that are will be replaced. However, the following characters are ambiguous, and may lead to confusion. For example, “x[1]->b”.will be read by PHP as x[1].->b” and not like “{x[1]->b}”. It is advised to add curly brackets around those structures to make them non-ambiguous.  Command Line Type/StringInterpolation Analyzers Coding Conventions Invalid Constant Name¶ According to PHP’s manual, constant names, ‘ A valid constant name starts with a letter or underscore, followed by any number of letters, numbers, or underscores.’. Constant, when defined using define() function, must follow this regex :: /[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/   Command Line Constants/InvalidName Analyzers Analyze Invalid Octal In String¶ Starting with PHP 7.1, any octal sequence inside a string can’t be beyong 7. Those will be a fatal error at parsing time. In PHP 7.0 and older, those sequences were silently adapted (divided by 0). <?php // Emit no error in PHP 7.1 echo 0; // @ // Emit an error in PHP 7.1 echo 0; // @ ?>   Command Line Type/OctalInString Analyzers CompatibilityPHP71, CompatibilityPHP72 Isset With Constant¶ Until PHP 7, it was possible to use arrays as constants, but it was not possible to test them with isset. <?php const X = [1,2,3]; if (isset(X[4])) {} ?>  This would yield an error : Fatal error: Cannot use isset() on the result of an expression (you can use “null !== expression” instead) in test.php on line 7 This is a backward incompatibility.  Command Line Structures/IssetWithConstant Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Join file()¶ Applying join() or implode() to the result of file() provides the same results than using file_get_contents(), but at a higher cost of memory and processing. <?php // memory and CPU intensive content = join('', file('path/to/file.txt')); // memory intensive content = file_get_contents('path/to/file.txt'); // Consider reading the data line by line and processing it along the way, // to save memory fp = fopen('path/to/file.txt', 'r'); while(line = fget(fp)) { // process a line } fclose(fp); ?>  Always use file_get_contents() to get the content of a file as a string.  Command Line Performances/JoinFile Analyzers Performances List Short Syntax¶ Usage of short syntax version of list(). <?php // PHP 7.1 short list syntax // PHP 7.1 may also use key => value structures with list [a, b, c] = ['2', 3, '4']; // PHP 7.0 list syntax list(a, b, c) = ['2', 3, '4']; ?>   Command Line Php/ListShortSyntax Analyzers CompatibilityPHP53, CompatibilityPHP70, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 List With Appends¶ List() behavior has changed in PHP 7.0 and it has impact on the indexing when list is used with the [] operator. <?php x = array(); list(x[], x[], x[]) = [1, 2, 3]; print_r(x); ?>  In PHP 7.0, results are :: Array ( [0] => 1 [1] => 2 [2] => 3 )  In PHP 5.6, results are :: Array ( [0] => 3 [1] => 2 [2] => 1 )   Command Line Php/ListWithAppends Analyzers Analyze, CompatibilityPHP70, CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP71 List With Keys¶ Setting keys when using list() is a PHP 7.1 feature. <?php // PHP 7.1 and later only list('a' => a, 'b' => b) = ['b' => 1, 'c' => 2, 'a' => 3]; ?>   Command Line Php/ListWithKeys Analyzers CompatibilityPHP53, CompatibilityPHP70, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Locally Unused Property¶ Those properties are defined in a class, and this class doesn’t have any method that makes use of them. While this is syntacticly correct, it is unusual that defined ressources are used in a child class. It may be worth moving the definition to another class, or to move accessing methods to the class.  Command Line Classes/LocallyUnusedProperty Analyzers Analyze, Dead code Logical Mistakes¶ Spot logical mistakes within logical expressions. Sometimes, the logic is not what it seems. It is important to check the actual impact of every part of the logical expression. Do not hesitate to make a table with all possible cases. If those cases are too numerous, it may be time to rethink the whole expression. <?php // Always false if (a != 1 || a != 2) { } // a == 1 is useless if (a == 1 || a != 2) {} // Always false if (a == 1 && a == 2) {} // a != 2 is useless if (a == 1 && a != 2) {} ?>  Based on article from Andrey Karpov Logical Expressions in C/C++. Mistakes Made by Professionals  Command Line Structures/LogicalMistakes Analyzers Analyze Logical Should Use Symbolic Operators¶ Logical operators come in two flavors : and / &&, || / or, ^ / xor. However, they are not exchangeable, as && and and have different precedence. It is recommended to use the symbol operators, rather than the letter ones.  Command Line Php/LogicalInLetters clearPHP no-letter-logical Analyzers Analyze Lone Blocks¶ Blocks are compulsory when defining a structure, such as a class or a function. They are most often used with flow control instructions, like if then or switch. Blocks are also valid syntax that group several instructions together, though they have no effect at all, except confuse the reader. Most often, it is a ruin from a previous flow control instruction, whose condition was removed or commented. They should be removed. <?php //foreach(a as b) { b++; } ?>   Command Line Structures/LoneBlock Analyzers Analyze Long Arguments¶ Long arguments should be put in variable, to preserve readability. When literal arguments are too long, they break the hosting structure by moving the next argument too far on the right. Whenever possible, long arguments should be set in a local variable to keep the readability. <?php // Now the call to foo() is easier to read. reallyBigNumber = <<<BIGNUMBER 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 BIGNUMBER foo(reallyBigNumber, 2, '12345678901234567890123456789012345678901234567890'); // where are the next arguments ? foo('123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890', 2, '123456789012345678901234567890123456789012345678901234567890'); // This is still difficult to read foo(<<<BIGNUMBER 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 BIGNUMBER , 2, '123456789012345678901234567890123456789012345678901234567890'); ?>  Literal strings and heredoc strings, including variables, that are over 50 chars longs are reported here.  Command Line Structures/LongArguments Analyzers Analyze Lost References¶ Either avoid references, or propagate them correctly. When assigning a referenced variable with another reference, the initial reference is lost, while the intend was to transfer the content. <?php function foo(&lostReference, &keptReference) { c = 'c'; // lostReference was a reference, but now, it is another lostReference =& c; // keptReference was a reference : now it contains the actual value keptReference = c; } bar = 'bar'; bar2 = 'bar'; foo(bar, bar2); //displays bar c, instead of bar bar print bar. ' '.bar2; ?>  Do not reassign a reference with another reference. Assign new content to the reference to change its value.  Command Line Variables/LostReferences Analyzers Analyze Magic Visibility¶ The magic methods must have public visibility and cannot be static. <?php class foo{ // magic method must bt public and non-static public static function __clone(name) { } // magic method can't be private private function __get(name) { } // magic method can't be protected private function __set(name, value) { } // magic method can't be static public static function __isset(name) { } } See Magic. ?>   Command Line Classes/toStringPss Analyzers Analyze, CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP70, CompatibilityPHP71, CompatibilityPHP72 Make Global A Property¶ Calling global (or GLOBALS) in methods is slower and less testable than setting the global to a property, and using this property. Using properties is slightly faster than calling global or GLOBALS, though the gain is not important. Setting the property in the constructor (or in a factory), makes the class easier to test, as there is now a simple point of configuration. <?php // Wrong way class fooBad { function x() { global a; a->do(); // Or GLOBALS['a']->do(); } } class fooGood { private bar = null; function __construct() { global bar; this->bar = bar; // Even better, do this via arguments } function x() { this->a->do(); } } ?>   Command Line Classes/MakeGlobalAProperty Analyzers Analyze Make One Call With Array¶ Call preg_replace_call() and str_replace() with an array. once with preg_replace_callback_array(). Calling the same function to chain modifications tends to be slower than calling the same function with all the transformations at the same time. Some PHP functions accept scalars or arrays, and using the later is more efficient. <?php string = 'abcdef'; //str_replace() accepts arrays as arguments string = str_replace( ['a', 'b', 'c'], ['A', 'B', 'C'], string); // Too many calls to str_replace string = str_replace( 'a', 'A'); string = str_replace( 'b', 'B'); string = str_replace( 'c', 'C'); ?>  Potential replacements : <?php subject = 'Aaaaaa Bbb'; //preg_replace_callback_array() is better than multiple preg_replace_callback : preg_replace_callback_array( [ '~[a]+~i' => function (match) { echo strlen(match[0]), ' matches for a found', PHP_EOL; }, '~[b]+~i' => function (match) { echo strlen(match[0]), ' matches for b found', PHP_EOL; } ], subject ); result = preg_replace_callback('~[a]+~i', function (match) { echo strlen(match[0]), ' matches for a found', PHP_EOL; }, subject); result = preg_replace_callback('~[b]+~i', function (match) { echo strlen(match[0]), ' matches for b found', PHP_EOL; }, subject); //str_replace() accepts arrays as arguments string = str_replace( ['a', 'b', 'c'], ['A', 'B', 'C'], string); // Too many calls to str_replace string = str_replace( 'a', 'A'); string = str_replace( 'b', 'B'); string = str_replace( 'c', 'C'); ?>   Command Line Performances/MakeOneCall Analyzers Performances Malformed Octal¶ Those numbers starts with a 0, so they are using the PHP octal convention. Therefore, one can’t use 8 or 9 figures in those numbers, as they don’t belong to the octal base. The resulting number will be truncated at the first erroneous figure. For example, 090 is actually 0, and 02689 is actually 22. <?php // A long way to write 0 in PHP 5 a = 0890; // A fatal error since PHP 7 ?>  Also, note that very large octal, usually with more than 21 figures, will be turned into a real number and undergo a reduction in precision.  Command Line Type/MalformedOctal Analyzers Analyze Methodcall On New¶ This was added in PHP 5.4+  Command Line Php/MethodCallOnNew Analyzers CompatibilityPHP53 Mixed Keys Arrays¶ Avoid mixing constants and literals in array keys. When defining default values in arrays, it is recommended to avoid mixing constants and literals, as PHP may mistake them and overwrite the previous with the latter. Either switch to a newer version of PHP (5.5 or newer), or make sure the resulting array is the one you expect. If not, reorder the definitions. <?php const ONE = 1; a = [ 1 => 2, ONE => 3]; ?>   Command Line Arrays/MixedKeys Analyzers CompatibilityPHP53, CompatibilityPHP54 Modernize Empty With Expression¶ empty() accept expressions since PHP 5.5. There is no need to store the expression in a variable before testing, unless it is reused later. <?php // PHP 5.5+ empty() usage if (empty(strtolower(b . c))) { doSomethingWithoutA(); } // Compatible empty() usage a = strtolower(b . c); if (empty(a)) { doSomethingWithoutA(); } // a2 is reused, storage is legit a2 = strtolower(b . c); if (empty(a2)) { doSomething(); } else { echo a2; } ?>   Command Line Structures/ModernEmpty Analyzers Analyze Multiple Alias Definitions¶ Some aliases are representing differents classes across the repository. This leads to potential confusion. Across an application, it is recommended to use the same namespace for one alias. Failing to do this lead to the same keyword to represent different values in different files, with different behavior. Those are hard to find bugs. <?php namespace A { use d\d; // aka D } // Those are usually in different files, rather than just different namespaces. namespace B { use b\c as D; // also D. This could be named something else } ?>   Command Line Namespaces/MultipleAliasDefinitions Analyzers Analyze Multiple Alias Definitions Per File¶ Avoid aliasing the same name with different aliases. This leads to confusion. <?php // first occurrence use name\space\ClasseName; // when this happens, several other uses are mentionned // name\space\ClasseName has now two names use name\space\ClasseName as anotherName; ?>  See also Multiple Alias Definitions.  Command Line Namespaces/MultipleAliasDefinitionPerFile Analyzers Analyze Multiple Class Declarations¶ It is possible to declare several times the same class in the code. PHP will not mention it until execution time, since declarations may be conditional. <?php a = 1; // Conditional declaration if (a == 1) { class foo { function method() { echo 'class 1';} } } else { class foo { function method() { echo 'class 2';} } } (new foo())->method(); ?>  It is recommended to avoid declaring several times the same class in the code. The best practice is to separate them with namespaces, they are for here for that purpose. In case those two classes are to be used interchangeably, the best is to use an abstract class or an interface.  Command Line Classes/MultipleDeclarations Analyzers Analyze Multiple Classes In One File¶ It is regarded as a bad practice to cram more than one class per file. This is usually done to make life of __autoload() easier. It is often difficult to find class foo in the bar.php file. This is also the case for interfaces and traits. One good reason to have multiple classes in one file is to reduce include time by providing everything into one nice include.  Command Line Classes/MultipleClassesInFile Analyzers Coding Conventions Multiple Constant Definition¶ Some constants are defined several times in your code. This will lead to a fatal error, if they are defined during the same execution.  Command Line Constants/MultipleConstantDefinition Analyzers Analyze Multiple Definition Of The Same Argument¶ A method’s signature is holding twice (or more) the same argument. For example, function x (a, a) { ... }. This is accepted as is by PHP, and the last parameter’s value will be assigned to the variable : function x (a, a) { print a; }; x(1,2); => will display 2 However, this is not common programming practise : all arguments should be named differently.  Command Line Functions/MultipleSameArguments clearPHP all-unique-arguments Analyzers Analyze, CompatibilityPHP70, CompatibilityPHP71 Multiple Exceptions Catch()¶ Starting with PHP 7.1, it is possible to have several distinct exceptions class caught by the same catch, preventing code repetition. <?php // PHP 7.1 and more recent try { throw new someException(); } catch (Single s) { doSomething(); } catch (oneType | anotherType s) { processIdentically(); } finally { } // PHP 7.0 and older try { throw new someException(); } catch (Single s) { doSomething(); } catch (oneType s) { processIdentically(); } catch (anotherType s) { processIdentically(); } finally { } ?>  This is a backward incompabitible feature of PHP 7.1.  Command Line Exceptions/MultipleCatch Analyzers CompatibilityPHP53, CompatibilityPHP70, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Multiple Identical Trait Or Interface¶ There is no need to use the same trait, or implements the same interface more than once. Up to PHP 7.1 (at least), this doesn’t raise any warning. Traits are only imported once, and interfaces may be implemented as many times as wanted. <?php class foo { use t3,t3,t3; } class bar implements i,i,i { } ?>   Command Line Classes/MultipleTraitOrInterface Analyzers Analyze Multiple Index Definition¶ Indexes that are defined multiple times in the same array. <?php // Multiple identical keys x = array(1 => 2, 2 => 3, 1 => 3); // Multiple identical keys (sneaky version) x = array(1 => 2, 1.1 => 3, true => 4); // Multiple identical keys (automated version) x = array(1 => 2, 3, // This will be index 2 2 => 4); // this index is overwritten ?>  They are indeed overwriting each other. This is most probably a typo.  Command Line Arrays/MultipleIdenticalKeys Analyzers Analyze Multiples Identical Case¶ Some cases are defined multiple times, but only one will be processed. Check the list of cases, and remove the extra one. Exakat tries to find the value of the case as much as possible, and ignore any dynamic cases (using variables). <?php case (x) { case 1 : break; case true: // This is a duplicate of the previous break; case 1 + 0: // This is a duplicate of the previous break; case 1.0 : // This is a duplicate of the previous break; case y : // This is not reported. break; default: } ?>   Command Line Structures/MultipleDefinedCase clearPHP no-duplicate-case Analyzers Analyze Multiply By One¶ Multiplying by 1 is useless. If it is used to type cast a value to number, then casting (integer) or (real) is clearer. This behavior may change with PHP 7.1, which has unified the behavior of all hidden casts. <?php // Still the same value than m, but now cast to integer or real m = m * 1; // Still the same value than m, but now cast to integer or real n *= 1; // make typecasting clear, and merge it with the producing call. n = (int) n; ?>   Command Line Structures/MultiplyByOne clearPHP no-useless-math Analyzers Analyze Must Return Methods¶ The following methods are expected to return a value that will be used later. Without return, they are useless. Methods that must return are : __get(), __isset(), __sleep(), __toString(), __set_state(), __invoke(), __debugInfo(). Methods that may not return, but are often expected to : __call(), __callStatic(). <?php class foo { public function __isset(a) { // returning something useful return isset(this->var[a]); } public function __get(a) { this->a++; // not returning... } public function __call(name, args) { this->name(...args); // not returning anything, but that's OK } } ?>   Command Line Functions/MustReturn Analyzers Analyze Negative Power¶ The power operator ** has higher precedence than the sign operators + and -. This means that -2 ** 2 == -4. It is in fact, -(2 ** 2). When using negative power, it is clearer to add parenthesis or to use the pow() function, which has no such ambiguity : <?php // -2 to the power of 2 (a square) pow(-2, 2) == 4; // minus 2 to the power of 2 (a negative square) -2 ** 2 == -(2 ** 2) == 4; ?>   Command Line Structures/NegativePow Analyzers Analyze Nested Ifthen¶ Three levels of ifthen is too much. The method should be split into smaller functions. <?php function foo(a, b) { if (a == 1) { // Second level, possibly too much already if (b == 2) { } } } function bar(a, b, c) { if (a == 1) { // Second level. if (b == 2) { // Third level level. if (c == 3) { // Too much } } } } ?>   Command Line Structures/NestedIfthen Analyzers Analyze Nested Ternary¶ Ternary operators ?...: are a convenient instruction to apply some condition, and avoid a if() structure. It works best when it is simple, like in a one liner. However, ternary operators tends to make the syntax very difficult to read when they are nested. It is then recommended to use an if() structure, and make the whole code readable. <?php // Simple ternary expression echo (a == 1 ? b : c) ; // Nested ternary expressions echo (a === 1 ? d === 2 ? b : d : d === 3 ? e : c) ; echo (a === 1 ? d === 2 ? f ===4 ? g : h : d : d === 3 ? e : i === 5 ? j : k) ; //Previous expressions, written as a if / Then expression if (a === 1) { if (d === 2) { echo b; } else { echo d; } } else { if (d === 3) { echo e; } else { echo c; } } if (a === 1) { if (d === 2) { if (f === 4) { echo g; } else { echo h; } } else { echo d; } } else { if (d === 3) { echo e; } else { if (i === 5) { echo j; } else { echo k; } } } ?>   Command Line Structures/NestedTernary clearPHP no-nested-ternary Analyzers Analyze Never Used Properties¶ Properties that are never used. They are defined, but never actually used. <?php class foo { public usedProperty = 1; // Never used anywhere public unusedProperty = 2; function bar() { // Used internally ++this->usedProperty; } } class foo2 extends foo { function bar2() { // Used in child class ++this->usedProperty; } } // Used externally ++this->usedProperty; ?>   Command Line Classes/PropertyNeverUsed Analyzers Analyze New Functions In PHP 5.4¶ PHP introduced new functions in PHP 5.4. If you have already defined functions with such names, you will get a conflict when trying to upgrade. It is advised to change those functions’ name.  Command Line Php/Php54NewFunctions Analyzers CompatibilityPHP53, CompatibilityPHP71 New Functions In PHP 5.5¶ PHP introduced new functions in PHP 5.5. If you have already defined functions with such names, you will get a conflict when trying to upgrade. It is advised to change those functions’ name.  Command Line Php/Php55NewFunctions Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP71 New Functions In PHP 5.6¶ PHP introduced new functions in PHP 5.6. If you have already defined functions with such names, you will get a conflict when trying to upgrade. It is advised to change those functions’ name.  Command Line Php/Php56NewFunctions Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 New Functions In PHP 7.0¶ The following functions are now native functions in PHP 7.0. It is advised to change them before moving to this new version. • get_resources • gc_mem_caches • preg_replace_callback_array • posix_setrlimit • random_bytes • random_int • intdiv • error_clear_last  Command Line Php/Php70NewFunctions Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP71 New Functions In PHP 7.1¶ The following functions are now native functions in PHP 7.1. It is advised to change them before moving to this new version. • curl_share_strerror() • curl_multi_errno() • curl_share_errno() • mb_ord() • mb_chr() • mb_scrub() • is_iterable()  Command Line Php/Php71NewFunctions Analyzers CompatibilityPHP71, CompatibilityPHP72 No Boolean As Default¶ Default values should always be set up with constants. Class constants or constants improve readability when calling the methods. <?php const CASE_INSENSITIVE = true; const CASE_SENSITIVE = false; function foo(case_insensitive = true) { // doSomething() } // Readable code foo(CASE_INSENSITIVE); foo(CASE_SENSITIVE); // unreadable code : is true case insensitive or case sensitive ? foo(true); foo(false); ?>   Command Line Functions/NoBooleanAsDefault Analyzers Analyze No Choice¶ A conditional structure is being used, but both alternatives are the same, leading to the illusion of choice. Either the condition is useless, and may be removed, or the alternatives needs to be distinguished. <?php if (condition == 2) { doSomething(); } else { doSomething(); } condition == 2 ? doSomething() : doSomething(); ?>   Command Line Structures/NoChoice Analyzers Analyze No Count With 0¶ Comparing count() and strlen() to 0 is a waste of resources. There are three distinct situations situations. When comparing count() with 0, with ===, ==, !==, !=, it is more efficient to use empty(). Empty() is a language constructs that checks if a value is present, while count() actually load the number of element. <?php // Checking if an array is empty if (count(array) == 0) { // doSomething(); } // This may be replaced with if (empty(array)) { // doSomething(); } ?>  When comparing count() strictly with 0 (>) it is more efficient to use !(empty()) <?php // Checking if an array is empty if (count(array) > 0) { // doSomething(); } // This may be replaced with if (!empty(array)) { // doSomething(); } Of course comparing count() with negative values, or with >= is useless. <?php // Checking if an array is empty if (count(array) < 0) { // This never happens // doSomething(); } ?>  Comparing count() and strlen() with other values than 0 cannot be replaced with a comparison with empty(). Note that this is a micro-optimisation : since PHP keeps track of the number of elements in arrays (or number of chars in strings), the total computing time of both operations is often lower than a ms. However, both functions tends to be heavily used, and may even be used inside loops.  Command Line Performances/NotCountNull Analyzers Performances No Direct Call To Magic Method¶ PHP magic methods, such as __get(), __set(), ... are supposed to be used in an object environnement, and not with direct call. For example, <?php print x->__get('a'); //should be written print x->a; ?>  Accessing those methods in a static way is also discouraged.  Command Line Classes/DirectCallToMagicMethod Analyzers Analyze No Direct Usage¶ The results of the following functions shouldn’t be used directly, but checked first. For example, glob() returns an array, unless some error happens, in which case it returns a boolean (false). In such case, however rare it is, plugging glob() directly in a foreach() loops will yield errors. <?php // Used without check : foreach(glob('.') as file) { /* do Something */ }. // Used without check : files = glob('.'); if (!is_array(files)) { foreach(files as file) { /* do Something */ }. } ?>   Command Line Structures/NoDirectUsage Analyzers Analyze No Global Modification¶ Avoid modifying directly Wordpress global variables. It is recommended to use the function API instead. <?php my_hook() { // Avoid changing those variables, as Wordpress handles them GLOBALS['is_safari'] = true; } ?>  See also Global Variables  Command Line Wordpress/NoGlobalModification Analyzers Wordpress No Hardcoded Hash¶ Hash should never be hardcoded. Hashes may be MD5, SHA1, SHA512, Bcrypt or any other. Such values must be easily changed, for security reasons, and the source code is not the safest place to hide it. <?php // Those strings may be sha512 hashes. // it is recomemdned to check if they are static or should be put into configuration init512 = array( // initial values for SHA512 '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', ); ?>   Command Line Structures/NoHardcodedHash Analyzers Analyze, Security No Hardcoded Ip¶ Do not leave hard coded IP in your code. It is recommended to move such configuration in external files or databases, for each update. This may also come handy when testing. <?php // This IPv4 is hardcoded. ip = '183.207.224.50'; // This IPv6 is hardcoded. ip = '2001:0db8:85a3:0000:0000:8a2e:0370:7334'; // This looks like an IP thisIsNotAnIP = '213.187.99.50'; thisIsNotAnIP = '2133:1387:9393:5330'; ?>  127.0.0.1, ::1 and ::0 are omitted, and not considered as a violation.  Command Line Structures/NoHardcodedIp Analyzers Analyze, Security No Hardcoded Path¶ It is not recommended to have literals when accessing files. Either use __FILE__ and __DIR__ to make the path relative to the current file; use a DOC_ROOT as a configuration constant that will allow you to move your script later or rely on functions likes sys_get_temp_dir(), to reach special folders. <?php // This depends on the current executed script file_get_contents('token.txt'); // Exotic protocols are ignored file_get_contents('jackalope://file.txt'); // Some protocols are ignored : http, https, ftp, ssh2, php (with memory) file_get_contents('http://www.php.net/'); file_get_contents('php://memory/'); // glob() with special chars * and ? are not reported glob('./*/foo/bar?.txt'); // glob() without special chars * and ? are reported glob('/foo/bar/'); ?>   Command Line Structures/NoHardcodedPath clearPHP no-hardcoded-path Analyzers Analyze No Hardcoded Port¶ When connecting to a remove serve, port is an important information. It is recommended to make this configurable (with constant or configuration), to as to be able to change this value without changing the code.  Command Line Structures/NoHardcodedPort Analyzers Analyze, Security No Implied If¶ It is possible to emulate a ‘if...then’ structure by using the operators ‘and’ and ‘or’. Since optimizations will be applied to them : when the left operand of ‘and’ is false, the right one is not executed, as its result is useless; when the left operand of ‘or’ is true, the right one is not executed, as its result is useless; However, such structures are confusing. It is easy to misread them as conditions, and ignore an important logic step. <?php // Either connect, or die mysql_connect('localhost', user, pass) or die(); // Defines a constant if not found. defined('SOME_CONSTANT') and define('SOME_CONSTANT', 1); ?>  It is recommended to use a real ‘if then’ structures, to make the condition readable.  Command Line Structures/ImpliedIf clearPHP no-implied-if Analyzers Analyze No Isset With Empty¶ Empty() actually does the job of Isset() too. From the manual : No warning is generated if the variable does not exist. That means empty() is essentially the concise equivalent to !isset( <http://www.php.net/isset>_var) || var == false. <?php // Enough tests if (i!empty(a)) { doSomething(); } // Too many tests if (isset(a) && !empty(a)) { doSomething(); } ?>   Command Line Structures/NoIssetWithEmpty Analyzers Analyze No List With String¶ list() can’t be used anymore to access particular offset in a string. This should be done with substr() or string[offset] syntax.  Command Line Php/NoListWithString Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 No Need For Else¶ Else is not needed when the Then ends with a break. A break may be the following keywords : break, continue, return, goto. Any of these send the execution somewhere in the code. The else block is then executed as the main sequence, only if the condition fails. <?php function foo() { // Else may be in the main sequence. if (a1) { return a1; } else { a++; } // Same as above, but negate the condition : if (!a2) { return a2; } if (a2) { a++; } else { return a2; } // This is OK if (a3) { return; } // This has no break if (a4) { a++; } else { b++; } // This has no else if (a5) { a++; } } ?>  See also Object Calisthenics, rule number 2.  Command Line Structures/NoNeedForElse Analyzers Analyze No Parenthesis For Language Construct¶ Some PHP language constructs, such are include, print, echo don’t need parenthesis. They will handle parenthesis, but it is may lead to strange situations. It it better to avoid using parenthesis with echo, print, return, throw, include and require (and _once).  Command Line Structures/NoParenthesisForLanguageConstruct clearPHP no-parenthesis-for-language-construct Analyzers Analyze No Plus One¶ Incrementing a variable should be done with the ++ or – operators. Any other way, may be avoided. <?php // Best way to increment ++x; --y; // Second best way to increment, if the current value is needed : echo x++, y--; // Good but slow x += 1; x -= -1; y += -1; y -= 1; // even slower x = x + 1; y = y - 1; ?>   Command Line Structures/PlusEgalOne Analyzers Coding Conventions No Public Access¶ The properties below are declared with public access, but are never used publicly. They can be made protected or private. <?php class foo { public bar = 1; // Public, and used in public space public neverInPublic = 3; // Public, but never used in outside the class function bar() { neverInPublic++; } } x = new foo(); x->bar = 3; x->bar(); ?>   Command Line Classes/NoPublicAccess Analyzers Analyze No Real Comparison¶ Avoid comparing decimal numbers with ==, ===, !==, !=. Real numbers have an error margin which is random, and makes it very difficult to match even if the compared value is a literal. PHP uses an internal representation in base 2 : any number difficult to represent with this base (like 0.1 or 0.7) will have a margin of error. <?php a = 1/7; b = 2.0; // 7 * a is a real, not an integer var_dump( 7 * a === 1); // rounding error leads to wrong comparison var_dump( (0.1 + 0.7) * 10 == 8); // although var_dump( (0.1 + 0.7) * 10); // displays 8 // precision formula to use with reals. Adapt 0.0001 to your precision needs var_dump( abs(((0.1 + 0.7) * 10) - 8) < 0.0001); ?>  Use precision formulas with abs() to approximate values with a given precision, or avoid reals altogether.  Command Line Type/NoRealComparison clearPHP no-real-comparison Analyzers Analyze No Self Referencing Constant¶ It is not possible to use ‘self’ when defining a constant in a class. It will yield a fatal error at runtime. <?php class a { const C1 = 1; const C2 = self::C1; const C3 = a::C3; } ?>  The code needs to reference the full class’s name to do so, without using the current class’s name. <?php class a { const C1 = 1; const C2 = a::C1; } ?>   Command Line Classes/NoSelfReferencingConstant Analyzers Analyze No String With Append¶ PHP 7 doesn’t allow the usage of [] with strings. [] is an array-only oeprator. <?php string = 'abc'; // Not possible in PHP 7 string[] = 'd'; ?>  This was possible in PHP 5.*, but is now forbidden in PHP 7.  Command Line Php/NoStringWithAppend Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 No Substr() One¶ Use array notation string[position] to reach a single byte in a string. There are two ways to access a byte in a string : substr() and v[pos]; The second one is more readable. It may be up to four times faster, though it is a micro-optimization. It is recommended to use it. PHP 7.1 also introduces the support of negative offsets as string index : negative offset are also reported here. <?php string = ab人cde; echo substr(string, pos, 1); echo string[pos]; echo mb_substr(string, pos, 1); // pos = 1 // bbb // pos = 2 // ??人 ?>  Beware that substr() and v[pos] are similar, while mb_substr() is not. The first functions works on bytes, while the latter works on characters.  Command Line Structures/NoSubstrOne Analyzers Analyze, Performances, CompatibilityPHP71 No array_merge() In Loops¶ array_merge() is memory intensive : every call will duplicate the arguments in memory, before merging them. Since arrays may be quite big, it is recommended to avoid using array_merge() in a loop. Instead, one should use array_merge() with as many arguments as possible, making the merge a on time call. <?php // Creating a large multidimensional array source = ['a' => ['a', 'b', /*...*/], 'b' => ['b', 'c', 'd', /*...*/], /*...*/ ]; // Slow way b = array(); foreach(source as key => values) { b = array_merge(b, values); } // Faster way b = array(); foreach(source as key => values) { //Collect in an array b[] = values; } // One call to array_merge b = call_user_func_array('array_merge', b); // or with variadic b = call_user_func('array_merge', ..b); // Fastest way (with above example, without checking nor data pulling) b = call_user_func_array('array_merge', array_values(source)) // or b = call_user_func('array_merge', ...array_values(source)) ?>  Note that array_merge_recursive() and file_put_contents() are also affected and reported.  Command Line Performances/ArrayMergeInLoops clearPHP no-array_merge-in-loop Analyzers Analyze, Performances Non Ascii Variables¶ PHP supports variables with certain characters.: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*  In practice, letters outside the scope of a-zA-Z0-9 are rare, and require more care when editing the code or passing it from OS to OS. <?php class 人 { // An actual working class in PHP. public function __construct() { echo __CLASS__; } } people = new 人(); ?>   Command Line Variables/VariableNonascii Analyzers Analyze Non Static Methods Called In A Static¶ Static methods have to be declared as such (using the static keyword). Then, one may call them without instantiating the object. However, PHP doesn’t check that a method is static or not : at any point, you may call one method statically : <?php class x { static public function sm( ) { echo __METHOD__.\n; } public public sm( ) { echo __METHOD__.\n; } } x::sm( ); // echo x::sm ?>  It is a bad idea to call non-static method statically. Such method may make use of special variable this, which will be undefined. PHP will not check those calls at compile time, nor at running time. It is recommended to update this situation : make the method actually static, or use it only in object context. Note that this analysis reports all static method call made on a non-static method, even within the same class or class hierarchy. PHP silently accepts static call to any in-family method. <?php class x { public function foo( ) { self::bar() } public function bar( ) { echo __METHOD__.\n; } } ?>   Command Line Classes/NonStaticMethodsCalledStatic Analyzers Analyze, CompatibilityPHP56, CompatibilityPHP70, CompatibilityPHP71 Non-constant Index In Array¶ In ‘array[index]’, PHP cannot find index as a constant, but, as a default behavior, turns it into the string ‘index’. This default behavior raise concerns when a corresponding constant is defined, either using define() or the const keyword (outside a class). The definition of the index constant will modify the behavior of the index, as it will now use the constant definition, and not the ‘index’ string. array[index] = 1; // assign 1 to the element index in array define(‘index’, 2); array[index] = 1; // now 1 to the element 2 in array It is recommended to make index a real string (with ‘ or ”), or to define the corresponding constant to avoid any future surprise.  Command Line Arrays/NonConstantArray Analyzers Analyze Non-lowercase Keywords¶ Usual convention is to write PHP keywords (like as, foreach, switch, case, break, etc.) all in lowercase. <?php // usual PHP convention foreach(array as element) { echo element; } // unusual PHP conventions Foreach(array AS element) { eCHo element; } ?>  PHP do understand them in lowercase, UPPERCASE or WilDCase, so there is nothing compulsory here. Although, it will look strange to many.  Command Line Php/UpperCaseKeyword Analyzers Coding Conventions Nonce Creation¶ Mark the creation of nonce by Wordpress. Nonce may be created with the Wordpress functions wp_nonce_field(), wp_nonce_url() and wp_nonce_create(). <?php // Create an nonce for a link. nonce = wp_create_nonce( 'my-nonce' ); echo '<a href="myplugin.php?do_something=some_action&_wpnonce='.nonce.'">Do some action</a>'; ?>  See also Wordpress Nonce.  Command Line Wordpress/NonceCreation Analyzers Wordpress Not Definitions Only¶ Files should only include definitions (class, functions, traits, interfaces, constants), or global instructions, but not both. Within this context, globals, use, and namespaces instructions are not considered a warning.  Command Line Files/NotDefinitionsOnly Analyzers Analyze Not Not¶ Double not makes a boolean, not a true. This is a wrongly done casting to boolean. PHP supports (boolean) to do the same, faster and cleaner. <?php // Wrong type casting b = !!x; // Explicit code b = (boolean) x; ?>   Command Line Structures/NotNot clearPHP no-implied-cast Analyzers Analyze Null On New¶ The following classes used to have a very specific behavior during instantiation : they were able to return NULL on new. After issuing a ‘new’ with those classes, it was important to check if the returned object were null (sic) or not. No exception were thrown. <?php // Example extracted from the wiki below mf = new MessageFormatter('en_US', '{this was made intentionally incorrect}'); if (mf === null) { echo 'Surprise!'; } ?>  This inconsistency has been cleaned in PHP 7 : see See Internal Constructor Behavior  Command Line Classes/NullOnNew Analyzers Analyze, CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Objects Don’t Need References¶ There is no need to create references for objects, as those are always passed by reference when used as arguments.  Command Line Structures/ObjectReferences clearPHP no-references-on-objects Analyzers Analyze Old Style Constructor¶ A long time ago, PHP classes used to have the method bearing the same name as the class acts as the constructor. <?php namespace { // Global namespace is important class foo { function foo() { // This acts as the old-style constructor, and is reported by PHP } } class bar { function __construct() { } function bar() { // This doesn't act as constructor, as bar has a __construct() method } } } namespace Foo\Bar{ class foo { function foo() { // This doesn't act as constructor, as bar is not in the global namespace } } } ?>  This is no more the case in PHP 5, which relies on __construct() to do so. Having this old style constructor may bring in confusion, unless you are also supporting old time PHP 4. Note that classes with methods bearing the class name, but inside a namespace are not following this convention, as this is not breaking backward compatibility. Those are excluded from the analyze.  Command Line Classes/OldStyleConstructor clearPHP no-php4-class-syntax Analyzers Analyze Old Style __autoload()¶ Avoid __autoload(). Only use spl_register_autoload(). __autoload() will be deprecated in PHP 7.2 and possibly removed in later version. __autoload() may only be declared once, and cannot be modified later. This creates potential conflicts between libraries that try to set up their own autoloading schema. On the other hand, spl_register_autoload() allows registering and de-registering multiple autoloading functions or methods. <?php // Modern autoloading. function myAutoload(class){} spl_register_autoload('myAutoload'); // Old style autoloading. function __autoload(class){} ?>  Do not use the old __autoload() function, but rather the new spl_register_autoload() function. See also Autoloading Classe.  Command Line Php/oldAutoloadUsage clearPHP use-smart-autoload Analyzers Analyze One Letter Functions¶ One letter functions seems to be really short for a meaningful name. This may happens for very high usage functions, so as to keep code short, but such functions should be rare. <?php // One letter functions are rarely meaningful function f(a, b) { return a + b; } ?>   Command Line Functions/OneLetterFunctions Analyzers Analyze One Variable String¶ These strings only contains one variable or property or array. <?php a = 0; b = a; // This is a one-variable string // Better way to write the above b = (string) a; // Alternatives : b2 = a[1]; // This is a one-variable string b3 = a->b; // This is a one-variable string c = d; d = D; b4 = "{$$c}";
$b5 = "{$a->foo()}";

?>


If the goal is to convert it to a string, use the type casting (string) operator : it is then clearer to understand the conversion. It is also marginally faster, though very little.

 Command Line Type/OneVariableStrings Analyzers Analyze

Only Variable Returned By Reference¶

Function can’t return literals by reference.

When a function returns a reference, it is only possible to return variables, properties or static properties.

Anything else, like literals or static expressions, yield a warning at execution time.

<?php

// Can't return a literal number
function &foo() {
return 3 + rand();
}

// bar must return values that are stored in a
function &bar() {
$a = 3 + rand(); return$a;
}

?>

 Command Line Structures/OnlyVariableReturnedByReference Analyzers Analyze

Or Die¶

Classic old style failed error management.

<?php

// In case the connexion fails, this kills the current script
mysql_connect('localhost', $user,$pass) or die();

?>


Interrupting a script will leave the application with a blank page, will make your life miserable for testing. Just don’t do that.

 Command Line Structures/OrDie clearPHP no-implied-if Analyzers Analyze

Replacing the content of a variable by something different is prone to errors. For example, it is not obvious if the $text variable is plain text or HTML text. <?php // Confusing$text = htmlentities($text); // Better$textHTML = htmlentities($text); ?>  Besides, it is possible that the source is needed later, for extra processing. Note that accumulators, like += .= or [] etc., that are meant to collect lots of values with consistent type are OK.  Command Line Variables/Overwriting Analyzers Analyze Overwritten Exceptions¶ In catch blocks, it is good practice not to overwrite the incoming exception, as information about the exception will be lost.  Command Line Exceptions/OverwriteException Analyzers Analyze Overwritten Literals¶ In those methods, the same variable is assigned a literal twice. One of them is too much.  Command Line Variables/OverwrittenLiterals Analyzers Analyze PHP 7.0 New Classes¶ Those classes are now declared natively in PHP 7.0 and should not be declared in custom code.  Command Line Php/Php70NewClasses Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP71 PHP 7.0 New Interfaces¶ The following interfaces are introduced in PHP 7.0. They shouldn’t be defined in custom code.  Command Line Php/Php70NewInterfaces Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP71 PHP 7.0 Removed Directives¶ List of directives that are removed in PHP 7.0.  Command Line Php/Php70RemovedDirective Analyzers CompatibilityPHP70, CompatibilityPHP71 PHP 7.1 Microseconds¶ PHP 7.1 supports microseconds in DateTime class and date_create() function. In previous PHP versions, those dates only used seconds, leading to lazy comparisons : <?php$now = date_create();
usleep(10);              // wait for 0.001 ms
var_dump($now == date_create()); ?>  This code displays true in PHP 7.0 and older, (unless the code was run too close from the next second). In PHP 7.1, this is always false. This is also true with Datetime : <?php$now = new DateTime();
usleep(10);              // wait for 0.001 ms
var_dump((new DateTime())->format('u') == $now->format('u')); ?>  This evolution impacts mostly exact comparisons (== and ===). Non-equality (!= and !==) will probably be always true, and should be reviewed.  Command Line Php/Php71microseconds Analyzers CompatibilityPHP71, CompatibilityPHP72 PHP 7.1 Removed Directives¶ List of directives that are removed in PHP 7.1.  Command Line Php/Php71RemovedDirective Analyzers CompatibilityPHP71, CompatibilityPHP72 PHP 7.2 Deprecations¶ PHP 7.2 deprecates several features of the language. Deprecated functions and extensions are reported in a separate analysis.  Command Line Php/Php72Deprecation Analyzers CompatibilityPHP72 PHP 7.2 Removed Functions¶ The following PHP native functions were removed in PHP 7.2. • png2wbmp • jpeg2wbmp  Command Line Php/Php72RemovedFunctions Analyzers CompatibilityPHP72 PHP 70 Removed Functions¶ The following PHP native functions were removed in PHP 7.0. • ereg • ereg_replace • eregi • eregi_replace • split • spliti • sql_regcase • magic_quotes_runtime • set_magic_quotes_runtime • call_user_method • call_user_method_array • set_socket_blocking • mcrypt_ecb • mcrypt_cbc • mcrypt_cfb • mcrypt_ofb • datefmt_set_timezone_id • imagepsbbox • imagepsencodefont • imagepsextendfont • imagepsfreefont • imagepsloadfont • imagepsslantfont • imagepstext  Command Line Php/Php70RemovedFunctions Analyzers CompatibilityPHP70, CompatibilityPHP71 PHP Keywords As Names¶ PHP has a set of reserved keywords. It is recommended not to use those keywords for names structures. PHP does check that a number of structures, such as classes, methods, interfaces... can’t be named or called using one of the keywords. However, in a few other situations, no check are enforced. Using keywords in such situation is confusing.  Command Line Php/ReservedNames Analyzers Analyze, CompatibilityPHP71 PHP5 Indirect Variable Expression¶ Indirect variable expressions changes between PHP 5 an 7. The following structures are evaluated differently in PHP 5 and 7. It is recommended to review them or switch to a less ambiguous syntax. <?php // PHP 7$foo = 'bar';
$bar['bar']['baz'] = 'foobarbarbaz'; echo $$foo['bar']['baz']; echo ($$foo)['bar']['baz']; // PHP 5$foo['bar']['baz'] = 'bar';
$bar = 'foobarbazbar'; echo $$foo['bar']['baz']; echo {foo['bar']['baz']}; ?>   Expression PHP 5 interpretation PHP 7 interpretation$$foo[‘bar’][‘baz’]$foo->$bar[‘baz’]$foo->$bar[‘baz’]() Foo::$bar[‘baz’]() ${$foo[‘bar’][‘baz’]} $foo->{$bar[‘baz’]} $foo->{$bar[‘baz’]}() Foo::{$bar[‘baz’]}() ($$foo)[‘bar’][‘baz’] (foo->bar)[‘baz’] (foo->bar)[‘baz’]() (Foo::bar)[‘baz’]()  Command Line Variables/Php5IndirectExpression Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 PHP7 Dirname¶ With PHP 7, dirname has a second argument that represents the number of parent folder to follow. This prevent us from using nested dirname() calls to reach an grand-parent direct. <?php path = '/a/b/c/d/e/f'; // PHP 7 syntax threeFoldersUp = dirname(path, 3); // PHP 5 syntax threeFoldersUp = dirname(dirname(dirname(path))); ?>   Command Line Structures/PHP7Dirname Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Parent, Static Or Self Outside Class¶ Parent, static and self keywords must be used within a class or a trait. They make no sens outside a class or trait scope, as self and static refers to the current class and parent refers to one of parent above. Static may be used in a function or a closure, but not globally.  Command Line Classes/PssWithoutClass Analyzers Analyze Parenthesis As Parameter¶ Using parenthesis around parameters used to silent some internal check. This is not the case anymore in PHP 7, and should be fixed by removing the parenthesis and making the value a real reference. <?php // PHP 7 sees through parenthesis d = foo(1, 2, c); // Avoid parenthesis in arguments d = foo(1, 2, (c)); ?>   Command Line Php/ParenthesisAsParameter Analyzers CompatibilityPHP70, CompatibilityPHP71 Performances/NoGlob¶ glob() and scandir() sorts results by default. If you don’t need that sorting, save some time by requesting NOSORT with those functions. Besides, whenever possible, use scandir() instead of glob(). <?php // Scandir without sorting is the fastest. scandir('docs/', SCANDIR_SORT_NONE); // Scandir sorts files by default. Same as above, but with sorting scandir('docs/'); // glob sorts files by default. Same as below, but no sorting glob('docs/*', GLOB_NOSORT); // glob sorts files by default. This is the slowest version glob('docs/*'); ?>  Using opendir() and a while loop may be even faster. This analysis skips scandir() and glob() if they are explicitely configured with flags (aka, sorting is explicitely needed). Glob() accepts wildchar, that may not easily replaced with scandir() or opendir().  Command Line Performances/NoGlob Analyzers Performances Performances/timeVsstrtotime¶ time() is actually faster than strtotime(‘now’). <?php // Faster version a = time(); // Slower version b = strtotime('now'); ?>  This is a micro-optimisation. Gain is real, but small unless the function is used many times.  Command Line Performances/timeVsstrtotime Analyzers Performances Php 7 Indirect Expression¶ Those are variable indirect expressions that are interpreted differently between PHP 5 and PHP 7. You should check them so they don’t behave strangely.  Command Line Variables/Php7IndirectExpression Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP70 Php 71 New Classes¶ New classes, introduced in PHP 7.1. If classes where created with the same name, in current code, they have to be moved in a namespace, or removed from code to migrate safely to PHP 7.1. The new class is : ReflectionClassConstant. The other class is ‘Void’ : this is forbidden as a classname, as Void is used for return type hint. <?php class ReflectionClassConstant { // Move to a namespace, do not leave in global // or, remove this class } ?>   Command Line Php/Php71NewClasses Analyzers CompatibilityPHP53, CompatibilityPHP70, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56, CompatibilityPHP71 Php7 Relaxed Keyword¶ Most of the traditionnal PHP keywords may be used inside classes, trait or interfaces. <?php // Compatible with PHP 7.0 + class foo { // as is a PHP 5 keyword public function as() { } } ?>  This was not the case in PHP 5, and will yield parse errors.  Command Line Php/Php7RelaxedKeyword Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Phpinfo¶ phpinfo() is a great function to learn about the current configuration of the server. <?php if (DEBUG) { phpinfo(); } ?>  If left in the production code, it may lead to a critical leak, as any attacker gaining access to this data will know a lot about the server configuration. It is advised to never leave that kind of instruction in a production code.  Command Line Structures/PhpinfoUsage Analyzers Analyze Pre-increment¶ When possible, use the pre-increment operator (++i or –i) instead of the post-increment operator (i++ or i–). The latter needs an extra memory allocation that costs about 10% of performances. <?php // ++i should be preferred over i++, as current value is not important for(i = 0; i <10; ++i) { // do Something } // ++b and b++ have different impact here, since a will collect b + 1 or b, respectively. a = b++; ?>   Command Line Performances/PrePostIncrement Analyzers Analyze, Performances Preprocess Arrays¶ Using long list of assignations for initializing arrays is significantly slower than the declaring them as an array. <?php // Slow way a = []; // also with a = array(); a[1] = 2; a[2] = 3; a[3] = 5; a[4] = 7; a[5] = 11; // Faster way a = [1 => 2, 2 => 3, 3 => 5, 4 => 7, 5 => 11]; // Even faster way if indexing is implicit a = [2, 3, 5, 7, 11]; ?>  If the array has to be completed rather than created, it is also faster to use += when there are more than ten elements to add. <?php // Slow way a = []; // also with a = array(); a[1] = 2; a[2] = 3; a[3] = 5; // some expressions to get seven and eleven a[4] = seven; a[5] = eleven; // Faster way a = [1 => 2, 2 => 3, 3 => 5]; // some expressions to get seven and eleven a += [4 => seven, 5 => eleven]; // Even faster way if indexing is implicit a = [2, 3, 5]; // some expressions to get seven and eleven a += [seven, eleven]; ?>   Command Line Arrays/ShouldPreprocess Analyzers none Preprocessable¶ The following expression are made of literals or already known values : they may be fully calculated before running PHP. <?php // Building an array from a string name = 'PHP'.' '.'7.2'; // Building an array from a string list = explode(',', 'a,b,c,d,e,f'); // Calculating a power kbytes = bytes / pow(2, 10); // This will never change name = ucfirst(strtolower('PARIS')); ?>  By doing so, this will reduce the amount of work of PHP.  Command Line Structures/ShouldPreprocess Analyzers Analyze, Analyze Property Could Be Private¶ The following properties are never used outside their class of definition or their children (for the protected). Given the analyzed code, they could be set as private. Note that dynamic properties (such as x->y) are not taken into account.  Command Line Classes/CouldBePrivate Analyzers Analyze Property Used Below¶ Mark properties that are used in children classes. <?php class foo { // This property is used in children protected protectedProperty = 1; // This property is not used in children protected localProtectedProperty = 1; private function foobar() { // protectedProperty is used here, but defined in parent this->localProtectedProperty = 3; } } class foofoo extends foo { private function bar() { // protectedProperty is used here, but defined in parent this->protectedProperty = 3; } } ?>  This doesn’t mark the current class, nor the (grand-)parent ones.  Command Line Classes/PropertyUsedBelow Analyzers Analyze Property Used In One Method Only¶ Properties should be used in several methods. When a property is used in only one method, this should have be of another shape. Properties used in one method only may be used several times, and read only. This may be a class constant. Such properties are meant to be overwritten by an extending class, and that’s possible with class constants. Properties that read and written may be converted into a variable, static to the method. This way, they are kept close to the method, and do not pollute the object’s properties. <?php class foo { private once = 1; const ONCE = 1; private counter = 0; function bar() { // this->once is never used anywhere else. someFunction(this->once); someFunction(self::ONCE); // Make clear that it is a } function bar2() { static localCounter = 0; this->counter++; // this->once is only used here, for distinguising calls to someFunction2 if (this->counter > 10) { // this->counter is used only in bar2, but it may be used several times return false; } someFunction2(this->counter); // localCounter keeps track for all the calls if (localCounter > 10) { return false; } someFunction2(localCounter); } } ?>  Note : properties used only once are not returned by this analysis. They are omitted, and are available in the analysis Used Once Property.  Command Line Classes/PropertyUsedInOneMethodOnly Analyzers Analyze Property/Variable Confusion¶ Within a class, there is both a property and some variables bearing the same name. <?php class Object { private x; function SetData( ) { this->x = x + 2; } } ?>  the property and the variable may easily be confused one for another and lead to a bug. Sometimes, when the property is going to be replaced by the incoming argument, or data based on that argument, this naming schema is made on purpose, indicating that the current argument will eventually end up in the property. When the argument has the same name as the property, no warning is reported.  Command Line Structures/PropertyVariableConfusion Analyzers Analyze Queries In Loops¶ Avoid querying databases in a loop. Querying an external database in a loop usually leads to performances problems. This is also called the ‘n + 1 problem’. It is recommended to reduce the number of queries by making one query, and dispatching the results afterwards. This is true with SQL databases, graph queries, LDAP queries, etc. <?php // Typical N = 1 problem : there will be as many queries as there are elements in array ids = array(1,2,3,5,6,10); db = new SQLite3('mysqlitedb.db'); // all the IDS are merged into the query at once results = db->query('SELECT bar FROM foo WHERE id in ('.implode(',', id).')'); while (row = results->fetchArray()) { var_dump(row); } // Typical N = 1 problem : there will be as many queries as there are elements in array ids = array(1,2,3,5,6,10); db = new SQLite3('mysqlitedb.db'); foreach(ids as id) { results = db->query('SELECT bar FROM foo WHERE id = '.id); while (row = results->fetchArray()) { var_dump(row); } } ?>  This is not always possible.  Command Line Structures/QueriesInLoop Analyzers Analyze Random Without Try¶ random_int() and random_bytes() require a try..catch enclosure. random_int() and random_bytes() emit Exceptions if they meet a problem. This way, failure can’t be mistaken with returning an empty value, which leads to lower security. <?php try { salt = random_bytes(length); } catch (TypeError e) { // Error while reading the provided parameter } catch (Exception e) { // Insufficient randome data generated } catch (Error e) { // Error with the provided parameter : <= 0 } ?>   Command Line Structures/RandomWithoutTry Analyzers Security Redeclared PHP Functions¶ Function that bear the same name as a PHP function, and that are declared. This is possible when managing some backward compatibility, like emulating an old function, or preparing for newer PHP version, like emulating new upcoming function. <?php if (version_compare(PHP_VERSION, 7.0) > 0) { function split(separator, string) { return explode(separator, string); } } print_r( split(' ', '2 3')); ?>   Command Line Functions/RedeclaredPhpFunction Analyzers Analyze Redefined Class Constants¶ Redefined class constants. Class constants may be redefined, though it is prone to errors when using them, as it is now crucial to use the right class name to access the right value. <?php class a { const A = 1; } class b extends a { const A = 2; } class c extends c { } echo a::A, ' ', b::A, ' ', c::A; // 1 2 2 ?>  It is recommended to use distinct names.  Command Line Classes/RedefinedConstants Analyzers Analyze Redefined Default¶ Classes allows properties to be set with a default value. When those properties get, unconditionally, another value at constructor time, then one of the default value are useless. One of those definition should go : it is better to define properties outside the constructor. <?php class foo { public redefined = 1; public function __construct( ) { this->redefined = 2; } } ?>   Command Line Classes/RedefinedDefault Analyzers Analyze Register Globals¶ register_globals was a PHP directive that dumped all incoming variables from GET, POST, COOKIE and FILES as global variables in the called scripts. This lead to security failures, as the variables were often used but not filtered. Though it is less often found in more recent code, register_globals is sometimes needed in legacy code, that haven’t made the move to eradicate this style of coding. Backward compatible pieces of code that mimic the register_globals features usually create even greater security risks by being run after scripts startup. At that point, some important variables are already set, and may be overwritten by the incoming call, creating confusion in the script. Mimicking register_globals is achieved with variables variables, extract(), parse_str() and import_request_variables() (Up to PHP 5.4). <?php // Security warning ! This overwrites existing variables. extract(_POST); // Security warning ! This overwrites existing variables. foreach(_REQUEST as var => value) {$$var =$value;
}

?>

 Command Line Security/RegisterGlobals Analyzers Security

Relay Function¶

Relay function only hand workload to another one.

Relay functions (or methods) are delegating the actual work to another function or method. They do not have any impact on the results, besides exposing another name for the same feature.

<?php

function myStrtolower($string) { return \strtolower($string);
}

?>


Relay functions are typical of transition API, where an old API have to be preserved until it is fully migrated. Then, they may be removed, so as to reduce confusion, and unclutter the API.

 Command Line Functions/RelayFunction Analyzers Analyze

Repeated print()¶

Always merge several print or echo in one call.

It is recommended to use echo with multiple arguments, or a concatenation with print, instead of multiple calls to print echo, when outputting several blob of text.

<?php

//Write :
echo 'a', $b, 'c'; print 'a' .$b . 'c';

//Don't write :
print 'a';
print $b; print 'c'; ?>   Command Line Structures/RepeatedPrint clearPHP no-repeated-print Analyzers Analyze Reserved Keywords In PHP 7¶ Php reserved names for class/trait/interface. They won’t be available anymore in user space starting with PHP 7.  Command Line Php/ReservedKeywords7 Analyzers CompatibilityPHP70, CompatibilityPHP71 Results May Be Missing¶ preg_match() may return empty values, if the search fails. It is important to check for the existence of results before assigning them to another variable, or using it. <?php preg_match('/PHP ([0-9\.]+) /',$res, $r);$s = $r[1]; //$s may end up null if preg_match fails.
?>

 Command Line Structures/ResultMayBeMissing Analyzers Analyze

Rethrown Exceptions¶

Throwing a caught exception is usually useless and dead code.

When exception are caught, they should be processed or transformed, but not rethrown.

Those issues often happen when a catch structure was positioned for debug purposes, but lost its usage later.

<?php

try {
doSomething();
} catch (Exception $e) { throw$e;
}

?>

 Command Line Exceptions/Rethrown Analyzers Dead code

Return True False¶

These conditional expressions return true/false, depending on the condition. This may be simplified by dropping the control structure alltogether.

<?php

if (version_compare($a,$b) >= 0) {
return true;
} else {
return false;
}

?>


This may be simplified with :

<?php

return version_compare($a,$b) >= 0;

?>


This may be applied to assignations and ternary operators too.

<?php

if (version_compare($a,$b) >= 0) {
$a = true; } else {$a = false;
}

$a = version_compare($a, $b) >= 0 ? false : true; ?>   Command Line Structures/ReturnTrueFalse Analyzers Analyze Return With Parenthesis¶ PHP tolerates parenthesis for the argument of a return statement, but it is recommended not to use them.  Command Line Php/ReturnWithParenthesis Analyzers Coding Conventions Safe CurlOptions¶ It is advised to always use CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST when requesting a SSL connexion. With those tests (by default), the certificate is verified, and if it isn’t valided, the connexion fails : this is a safe behavior. <?php$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, https://www.php.net/); // To be safe, always set this to true curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

curl_exec($ch); curl_close($ch);
?>

 Command Line Security/CurlOptions Analyzers Security

Same Conditions¶

Several If then else structures are chained, and some conditions are identical. The latter will be ignored.

<?php

if ($a == 1) { doSomething(); } elseif ($b == 1) { doSomething(); }
elseif ($c == 1) { doSomething(); } elseif ($a == 1) { doSomething(); }
else {}

// Also works on if then else if chains
if ($a == 1) { doSomething(); } else if ($b == 1) { doSomething(); }
else if ($c == 1) { doSomething(); } else if ($a == 1) { doSomething(); }
else {}

?>

 Command Line Structures/SameConditions Analyzers Analyze

Scalar Typehint Usage¶

Spot usage of scalar type hint : int, float, boolean and string.

 Command Line Php/ScalarTypehintUsage Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56

Sequences In For¶

For() instructions allows several instructions in each of its parameters. Then, the instruction separator is comma ‘,’, not semi-colon, which is used for separating the 3 arguments.

<?php
for ($a = 0,$b = 0; $a < 10,$b < 20; $a++,$b += 3) {
// For loop
}
?>


This loop will simultaneously increment $a and$b. It will stop only when the last of the central sequence reach a value of false : here, when $b reach 20 and$a will be 6.

This structure is often unknown, and makes the for instruction quite difficult to read. It is also easy to oversee the multiples instructions, and omit one of them. It is recommended not to use it.

 Command Line Structures/SequenceInFor Analyzers Analyze

Setlocale() Uses Constants¶

setlocal() don’t use strings.

The first argument of setlocale() must be one of the valid constants, LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES.

<?php

// Use constantes for setlocale first argument
setlocale(LC_ALL, 'nl_NL');
setlocale(\LC_ALL, 'nl_NL');

// Don't use string for setlocale first argument
setlocale('LC_ALL', 'nl_NL');
setlocale('LC_'.'ALL', 'nl_NL');

?>


The PHP 5 usage of strings (same name as above, enclosed in ‘ or ”) is not legit anymore in PHP 7 and later.

 Command Line Structures/SetlocaleNeedsConstants Analyzers CompatibilityPHP70, CompatibilityPHP71

Several Instructions On The Same Line¶

Usually, instructions do not share their line : one instruction, one line. This is good for readability, and help at understanding the code. This is especially important when fast-reading the code to find some special situation, where such double-meaning line way have an impact.

 Command Line Structures/OneLineTwoInstructions Analyzers Analyze

Short Open Tags¶

Usage of short open tags is discouraged. The following files were found to be impacted by the short open tag directive at compilation time. They must be reviewed to ensure no &lt;? tags are found in the code.

 Command Line Php/ShortOpenTagRequired Analyzers Analyze

Short Syntax For Arrays¶

Arrays written the new PHP 5.4 short syntax.

<?php

// All PHP versions array
$a = array(1, 2, 3); // PHP 5.4+ arrays$a = [1, 2, 3];

?>


This is mainly important for backward-compatibility.

 Command Line Arrays/ArrayNSUsage Analyzers CompatibilityPHP53

Should Be Single Quote¶

Use single quote for simple strings.

Static content inside a string, that has no single quotes nor escape sequence (such as n or t), should be using single quote delimiter, instead of double quote.

<?php

$a = abc; // This one is using a special sequence$b = cde\n;

// This one is using two special sequences
throw new Exception('Exception 2', 2, $e); // Chaining here. } ?>   Command Line Structures/ShouldChainException Analyzers Analyze Should Make Alias¶ Long names should be aliased. Aliased names are easy to read at the beginning of the script; they may be changed at one point, and update the whole code at the same time. Finally, short names makes the rest of the code readable. <?php namespace x\y\z; use a\b\c\d\e\f\g as Object; // long name, difficult to read, prone to change. new a\b\c\d\e\f\g(); // long name, difficult to read, prone to silent dead code if namespace change. if ($o instanceof a\b\c\d\e\f\g) {

}

// short names Easy to update all at once.
new Object();
if ($o instanceof Object) { } ?>   Command Line Namespaces/ShouldMakeAlias Analyzers Analyze Should Make Ternary¶ Ternary operators are the best when assigning values to a variable. This way, they are less verbose, compatible with assignation and easier to read. <?php // verbose if then structure if ($a == 3) {
$b = 2; } else {$b = 3;
}

// compact ternary call
$b = ($a == 3) ? 2 : 3;

// verbose if then structure
// Works with short assignations and simple expressions
if ($a != 3) {$b += 2 - $a * 4; } else {$b += 3;
}

// compact ternary call
$b += ($a != 3) ? 2 - $a * 4 : 3; ?>   Command Line Structures/ShouldMakeTernary Analyzers Analyze Should Typecast¶ When typecasting, it is better to use the casting operator, such as (int) or (bool). Functions such as intval() or settype() are always slower. <?php$int = intval($_GET['x']); // Quicker version$int = (int) $_GET['x']; ?>  This is a micro-optimisation, although such conversion may be use multiple time, leading to a larger performance increase.  Command Line Type/ShouldTypecast Analyzers Analyze Should Use Coalesce¶ PHP 7 introduced the ?? operator, that replaces longer structures to set default values when a variable is not set. <?php // Fetches the request parameter user and results in 'nobody' if it doesn't exist$username = $_GET['user'] ?? 'nobody'; // equivalent to:$username = isset($_GET['user']) ?$_GET['user'] : 'nobody';

// Calls a hypothetical model-getting function, and uses the provided default if it fails
$model = Model::get($id) ?? $default_model; // equivalent to: if (($model = Model::get($id)) === NULL) {$model = $default_model; } ?>  Sample extracted from PHP docs Isset Ternary  Command Line Php/ShouldUseCoalesce Analyzers Analyze Should Use Constants¶ The following functions have related constants that should be used as arguments, instead of scalar literals, such as integers or strings. For example,$lines = file(‘file.txt’, 2); is less readable than $lines = file(‘file.txt’, FILE_IGNORE_NEW_LINES)  Command Line Functions/ShouldUseConstants Analyzers Analyze Should Use Function Use¶ Functioncalls that fall back to global scope should be using ‘use function’ or be fully namespaced. PHP searches for functions in the local namespaces, and in case it fails, makes the same search in the global scope. Anytime a native function is referenced this way, the search (and fail) happens. This slows down the scripts. The speed bump range from 2 to 8 %, depending on the availability of functions in the local scope. The overall bump is about 1 µs per functioncall, which makes it a micro optimisation until a lot of function calls are made. Based on one of Marco Pivetti tweet and this blog post <?php namespace X { use function strtolower as strtolower_aliased; // PHP searches for strtolower in X, fails, then falls back to global scope, succeeds.$a = strtolower($b); // PHP searches for strtolower in global scope, succeeds.$a = \strtolower($b); // PHP searches for strtolower_aliased in global scope, succeeds.$a = \strtolower_aliased($b); } ?>   Command Line Php/ShouldUseFunction Analyzers Performances Should Use Local Class¶ Methods in a class should use the class, or be functions. Methods should use$this with another method or a property, or call parent::. Static methods should call another static method, or a static property.

<?php

class foo {
public function __construct() {
// This method should do something locally, or be removed.
}
}

class bar extends foo {
private $a = 1; public function __construct() { // Calling parent:: is sufficient parent::__construct(); } public function barbar() { // This is acting on the local object$this->a++;
}

public function barfoo($b) { // This has no action on the local object. It could be a function return 3 +$b;
}
}

?>

 Command Line Classes/ShouldUseThis clearPHP not-a-method Analyzers Analyze

Should Use Prepared Statement¶

Modern databases provides support for prepared statement : it separates the query from the processed data and highten significantly the security.

Building queries with concatenations is not recommended, though not always avoidable. When possible, use prepared statements.

 Command Line Security/ShouldUsePreparedStatement Analyzers Analyze, Security

Should Use array_column()¶

Should use array_column().

array_column() is a native PHP function, that extract a property or a index from a array of object, or a multidimensional array. This prevents the usage of foreach to collect those values.

<?php

$a = array(array('b' => 1), array('b' => 2, 'c' => 3), array( 'c' => 4)); // b doesn't always exists$bColumn = array_column($a, 'b'); // Slow and cumbersome code$bColumn = array();
foreach($a as$k => $v) { if (isset($v['b'])) {
$bColumn[] =$v['b'];
}
}

?>


array_column() is faster than foreach() (with or without the isset() test) with 3 elements or more, and it is significantly faster beyond 5 elements. Memory consumption is the same.

 Command Line Php/ShouldUseArrayColumn Analyzers Analyze, Performances

Should Use session_regenerateid()¶

session_regenerateid() should be used when sessions are used.

When using sessions, a session ID is assigned to the user. It is a random number, used to connect the user and its data on the server. Actually, anyone with the session ID may have access to the data. This is why those session ID are so long and complex.

A good approach to protect the session ID is to reduce its lifespan : the shorter the time of use, the better. While changing the session ID at every hit on the page may no be possible, a more reasonable approach is to change the session id when an important action is about to take place. What important means is left to the application to decide.

Based on this philopsophy, a code source that uses ZendSession but never uses ZendSession::regenerateId() has to be updated.

<?php

session_start();

$id = (int)$_SESSION['id'];
// no usage of session_regenerateid() anywhere triggers the analysis

// basic regeneration every 20 hits on the page.
if (++$_SESSION['count'] > 20) { session_regenerateid(); } ?>   Command Line Security/ShouldUseSessionRegenerateId Analyzers Security Silently Cast Integer¶ Those are integer literals that are cast to a float when running PHP. They are simply too big for the current PHP version, and PHP resorts to cast them into a float, which has a much larger capacity but a lower precision. Compare your literals to PHP_MAX_INT (typically 9223372036854775807) and PHP_MIN_INT (typically -9223372036854775808). This applies to binary (0b10101...), octals (0123123...) and hexadecimals (0xfffff...) too. <?php echo 0b1010101101010110101011010101011010101011010101011010101011010111; //6173123008118052203 echo 0b10101011010101101010110101010110101010110101010110101010110101111; //1.2346246016236E+19 echo 0123123123123123123123; //1498121094048818771 echo 01231231231231231231231; //1.1984968752391E+19 echo 0x12309812311230; //5119979279159856 echo 0x12309812311230fed; //2.0971435127439E+19 echo 9223372036854775807; //PHP_MAX_INT //9223372036854775807 echo 9223372036854775808; 9.2233720368548E+18 ?>   Command Line Type/SilentlyCastInteger Analyzers Analyze Simple Global Variable¶ The global keyword should only be used with simple variables. Since PHP 7, it cannot be used with complex or dynamic structures. <?php // Forbidden in PHP 7 global$normalGlobal;

// Forbidden in PHP 7
global $$variable->global ; // Tolerated in PHP 7 global {variable->global}; ?>   Command Line Php/GlobalWithoutSimpleVariable Analyzers CompatibilityPHP70, CompatibilityPHP71 Simplify Regex¶ PRCE regex are a powerful way to search inside strings, but they also come at the price of performance. When the query is simple enough, try using strpos() or stripos() instead. <?php // simple preg calls if (preg_match('/a/', string)) {} if (preg_match('/b/i', string)) {} // case insensitive // light replacements if( strpos('a', string)) {} if( stripos('b', string)) {} // case insensitive ?>   Command Line Structures/SimplePreg Analyzers Performances Slow Functions¶ Avoid using those slow native PHP functions, and replace them with alternatives. <?php array = source(); // Slow extraction of distinct values array = array_unique(array); // Much faster extraction of distinct values array = array_keys(array_count_values(array)); ?>   Slow Function Faster array_diff() array_intersect() array_key_exists() array_map() array_search() array_udiff() array_uintersect() array_unique() array_unshift() array_walk() in_array() preg_replace() strstr() uasort() uksort() usort() foreach() foreach() isset() foreach() array_flip() and isset() Use another way Use another way array_keys() and array_count_values() Use another way foreach() isset() strpos() strpos() Use another way Use another way Use another way  Command Line Performances/SlowFunctions clearPHP avoid-those-slow-functions Analyzers Performances Static Loop¶ Static loop may be preprocessed. It looks like the following loops are static : the same code is executed each time, without taking into account loop variables. <?php // Static loop total = 0; for(i = 0; i < 10; i++) { total += i; } // Non-Static loop (the loop depends on the size of the array) n = count(array); for(i = 0; i < n; i++) { total += i; } ?>  It is possible to create loops that don’t use any blind variables, though this is fairly rare.  Command Line Structures/StaticLoop Analyzers Analyze Static Methods Called From Object¶ Static methods may be called without instantiating an object. As such, they never interact with the special variable ‘this’, as they do not depend on object existence. Besides this, static methods are normal methods that may be called directly from object context, to perform some utility task. To maintain code readability, it is recommended to call static method in a static way, rather than within object context. <?php class x { static function y( ) {} } z = new x( ); z->y( ); // Readability : no one knows it is a static call x::y( ); // Readability : here we know ?>   Command Line Classes/StaticMethodsCalledFromObject Analyzers Analyze Static Methods Can’t Contain this¶ Static methods are also called ‘class methods’ : they may be called even if the class has no instantiated object. Thus, the local variable this won’t exist, PHP will set it to NULL as usual. <?php class foo { // Static method may access other static methods, or property, or none. static function staticBar() { // This is not possible in a static method return self::otherStaticBar() . static::staticProperty; } static function bar() { // This is not possible in a static method return this->property; } } ?>  Either, this is not a static method (simply remove the static keyword), or replace all this mention by static properties Class::property.  Command Line Classes/StaticContainsThis clearPHP no-static-this Analyzers Analyze Strange Name For Constants¶ Those constants looks like a typo from other names. <?php // This code looks OK : DIRECTORY_SEPARATOR is a native PHP constant path = path . DIRECTORY_SEPARATOR . file; // Strange name DIRECOTRY_SEPARATOR path = path . DIRECOTRY_SEPARATOR . file; ?>   Command Line Constants/StrangeName Analyzers none Strange Name For Variables¶ Those variables looks like a typo from other names. <?php class foo { function bar() { // Strange name tihs return tihs; } } ?>   Command Line Variables/StrangeName Analyzers Wordpress, Analyze, Analyze Strange Names For Methods¶ Those methods should have another name. Ever wondered why the ‘__constructor’ is never called? Or the ‘__consturct’ ? Those errors most often originate from typos, or quick fixes that ‘don’t require testing’. Some other times, they were badly chosen, or ran into PHP’s own reservations. <?php class foo { // The real constructor function __construct() {} // The fake constructor function __constructor() {} // The 'typo'ed' constructor function __consturct() {} // This doesn't clone function clone() {} } ?>   Command Line Classes/StrangeName Analyzers none Strict Comparison With Booleans¶ Booleans may be easily mistaken with other values, especially when the function may return integer or boolean as a normal course of action. It is encouraged to use strict comparison === or !== when booleans are involved in a comparison.  Command Line Structures/BooleanStrictComparison Analyzers Analyze String May Hold A Variable¶ Those strings looks like holding a variable. Single quotes and Nowdoc syntax may include  signs that are treated as literals, and not replaced with a variable value. However, there are some potential variables in those strings, making it possible for an error : the variable was forgotten and will be published as such. It is worth checking the content and make sure those strings are not variables. <?php a = 2; // Explicit variable, but literal effect is needed echo 'a is '.a; // One of the variable has been forgotten echo 'a is a'; // CAD is not a variable, rather a currency unit total = 12; echo total.' CAD'; // CAD is not a variable, rather a currency unit total = 12; // Here, total has been forgotten echo <<<'TEXT' total CAD TEXT; ?>   Command Line Type/StringHoldAVariable Analyzers Analyze Strpos Comparison¶ strpos() returns a string position, starting at 0, or false, in case of failure. <?php // This is the best comparison if (strpos(string, 'a') === false) { } // This is OK, as 2 won't be mistaken with false if (strpos(string, 'a') == 2) { } // strpos is one of the 26 functions that may behave this way if (preg_match(regex, string)) { } // This works like above, catching the value for later reuse if (a = strpos(string, 'a')) { } // This misses the case where 'a' is the first char of the string if (strpos(string, 'a')) { } // This misses the case where 'a' is the first char of the string, just like above if (strpos(string, 'a') == 0) { } ?>  It is recommended to check the reslt of strpos with === or !==, so as to avoid confusing 0 and false. This analyzer list all the strpos() function that are directly compared with == or !=.  Command Line Structures/StrposCompare clearPHP strict-comparisons Analyzers Analyze Switch To Switch¶ The following structures are based on if / elseif / else. Since they have more than three conditions (not withstanding the final else), it is recommended to use the switch structure, so as to make this more readable. On the other hand, switch() structures will less than 3 elements should be expressed as a if / else structure. Note that if condition that uses strict typing (=== or !==) can’t be converted to switch() as the latter only performs == or != comparisons. <?php if (a == 1) { } elseif (a == 2) { } elseif (a == 3) { } elseif (a == 4) { } else { } // Better way to write long if/else lists switch (a) { case 1 : doSomething(1); break 1; case 2 : doSomething(2); break 1; case 3 : doSomething(3); break 1; case 4 : doSomething(4); break 1; default : doSomething(); break 1; } ?>   Command Line Structures/SwitchToSwitch Analyzers Analyze Switch With Too Many Default¶ Switch statements should only hold one default, not more. Check the code and remove the extra default. PHP 7.0 won’t compile a script that allows for several default cases. Multiple default happens often with large switch(). <?php switch(a) { case 1 : break; default : break; case 2 : break; default : // This default is never reached break; } ?>   Command Line Structures/SwitchWithMultipleDefault Analyzers Analyze Switch Without Default¶ Always use a default statement in switch(). Switch statements hold a number of ‘case’ that cover all known situations, and a ‘default’ one which is executed when all other options are exhausted. <?php // Missing default switch(format) { case 'gif' : processGif(); break 1; case 'jpeg' : processJpeg(); break 1; case 'bmp' : throw new UnsupportedFormat(format); } // In case format is not known, then switch is ignored and no processing happens, leading to preparation errors // switch with default switch(format) { case 'text' : processText(); break 1; case 'jpeg' : processJpeg(); break 1; case 'rtf' : throw new UnsupportedFormat(format); default : throw new UnknownFileFormat(format); } // In case format is not known, an exception is thrown for processing ?>  Most of the time, switch() do need a default case, so as to catch the odd situation where the ‘value is not what it was expected’. This is a good place to catch unexpected values, to set a default behavior.  Command Line Structures/SwitchWithoutDefault clearPHP no-switch-without-default Analyzers Analyze Ternary In Concat¶ Ternary operator has higher priority than dot ‘.’ for concatenation. This means that : <?php print 'B'.b.'C'. b > 1 ? 'D' : 'E'; ?>  prints actually ‘E’, instead of the awaited ‘B0CE’. To be safe, always add parenthesis when using ternary operator with concatenation.  Command Line Structures/TernaryInConcat Analyzers Analyze Throw Functioncall¶ The throw keyword is excepted to use an exception. Calling a function to prepare that exception before throwing it is possible, but forgetting the new keyword is also possible. <?php // Forgotten new throw \RuntimeException('error!'); // Code is OK, function returns an exception throw getException(ERROR_TYPE, 'error!'); function getException(ERROR_TYPE, message) { return new \RuntimeException(messsage); } ?>  When the new keyword is forgotten, then the class construtor is used as a functionname, and now exception is emited, but an ‘Undefined function’ fatal error is emited.  Command Line Exceptions/ThrowFunctioncall Analyzers Analyze Throw In Destruct¶ According to the manual, ‘Attempting to throw an exception from a destructor (called in the time of script termination) causes a fatal error.’ The destructor may be called during the lifespan of the script, but it is not certain. If the exception is thrown later, the script may end up with a fatal error. Thus, it is recommended to avoid throwing exceptions within the __destruct method of a class. <?php // No exception thrown class Bar { function __construct() { throw new Exception('__construct'); } function __destruct() { this->cleanObject(); } } // Potential crash class Foo { function __destruct() { throw new Exception('__destruct'); } } ?>   Command Line Classes/ThrowInDestruct Analyzers Analyze Throws An Assignement¶ It is possible to throw an exception, and, in the same time, assign this exception to a variable. <?php // e is useful, though not by much e = new() Exception(); throw e; // e is useless throw e = new() Exception(); ?>  However, e will never be used, as the exception is thrown, and any following code is not executed. The assignement should be removed.  Command Line Structures/ThrowsAndAssign Analyzers Analyze Timestamp Difference¶ time() and microtime() shouldn’t be used to calculate duration or with durations. time() and microtime() are subject to variations, depending on system clock variations, such as daylight saving time difference (every spring and fall, one hour variation), or leap seconds, happening on June, 30th or december 31th, as announcec by IERS. <?php // Calculating tomorow, same hour, the wrong way // tomorrow is not always in 86400s, especially in countries with daylight saving tomorrow = time() + 86400; // Good way to calculate tomorrow datetime = new DateTime('tomorrow'); ?>  When the difference may be rounded to a larger time unit (rounding the difference to days, or several hours), the variation may be ignored safely. When the difference is very small, it requires a better way to mesure time difference, such as ticks, ext/hrtime, or including a check on the actual time zone (ini_get() with ‘date.timezone’).  Command Line Structures/TimestampDifference Analyzers Analyze Too Many Finds¶ Too many methods called ‘find*’ in this class. It is may be time to consider the Specification pattern. <?php // quite a fishy interface interface UserInterface { public function findByEmail(email); public function findByUsername(username); public function findByFirstName(firstname); public function findByLastName(lastname); public function findByName(name); public function findById(id); public function insert(user); public function update(user); } ?>   Command Line Classes/TooManyFinds Analyzers Analyze Too Many Local Variables¶ Too many local variables were found in the methods. When over 15 variables are found in such a method, a violation is reported. Local variables exclude globals (imported with global) and arguments. When too many variables are used in a function, it is a code smells. The function is trying to do too much and needs extra space for juggling. Beyond 15 variables, it becomes difficult to keep track of their name and usage, leading to confusion, overwritting or hijacking. <?php // This function is OK : 3 vars are arguments, 3 others are globals. function a20a3g3(a1, a2, a3) { global a4, a5, a6; a1 = 1; a2 = 2; a3 = 3 ; a4 = 4 ; a5 = 5 ; a6 = 6 ; a7 = 7 ; a8 = 8 ; a9 = 9 ; a10 = 10; a11 = 11; a12 = 12; a13 = 13 ; a14 = 14 ; a15 = 15 ; a16 = 16 ; a17 = 17 ; a18 = 18 ; a19 = 19 ; a20 = 20; } // This function has too many variables function a20() { a1 = 1; a2 = 2; a3 = 3 ; a4 = 4 ; a5 = 5 ; a6 = 6 ; a7 = 7 ; a8 = 8 ; a9 = 9 ; a10 = 10; a11 = 11; a12 = 12; a13 = 13 ; a14 = 14 ; a15 = 15 ; a16 = 16 ; a17 = 17 ; a18 = 18 ; a19 = 19 ; a20 = 20; } ?>   Command Line Functions/TooManyLocalVariables Analyzers Analyze Uncaught Exceptions¶ The following exceptions are thrown in the code, but are never caught. Either they will lead to a fatal error, or they have to be caught by a larger application.  Command Line Exceptions/UncaughtExceptions Analyzers Analyze Unchecked Resources¶ Resources are created, but never checked before being used. This is not safe.  Command Line Structures/UncheckedResources clearPHP no-unchecked-resources Analyzers Analyze Undefined Caught Exceptions¶ Those are exceptions that are caught in the code, but are not defined in the application. They may be externally defined, such as in core PHP, extensions or libraries. Make sure those exceptions are usefull to your application : otherwise, they are dead code.  Command Line Exceptions/CaughtButNotThrown Analyzers Dead code Undefined Class Constants¶ Class constants that are used, but never defined. This should yield a fatal error upon execution, but no feedback at compile level. <?php class foo { const A = 1; define('B', 2); } // here, C is not defined in the code and is reported echo foo::A.foo::B.foo::C; ?>   Command Line Classes/UndefinedConstants Analyzers Analyze, Analyze Undefined Classes¶ Those classes were used in the code, but there is no way to find a definition of that class in the PHP code. This may happens under normal conditions, if the application makes use of an unsupported extension, that defines extra classes; or if some external libraries, such as PEAR, are not provided during the analysis. Otherwise, this should be checked.  Command Line Classes/UndefinedClasses Analyzers Analyze Undefined Constants¶ Constants definition can’t be located. Those constants are not defined in the code, and will raise errors, or use the fallback mechanism of being treated like a string. <?php const A = 1; define('B', 2); // here, C is not defined in the code and is reported echo A.B.C; ?>  It is recommended to define them all, or to avoid using them.  Command Line Constants/UndefinedConstants Analyzers none Undefined Functions¶ Those functions are not defined in the code. This means that the functions are probably defined in a missing library, or in an extension. If not, this will yield a Fatal error at execution.  Command Line Functions/UndefinedFunctions Analyzers Analyze Undefined Interfaces¶ Typehint or instanceof that are relying on undefined interfaces (or classes) : they will always return false. Any condition based upon them are dead code.  Command Line Interfaces/UndefinedInterfaces Analyzers Analyze Undefined Parent¶ List of properties and methods that are accessed using ‘parent’ keyword but are not defined in the parent class. This will be compilable but will yield a fatal error during execution. Note that if the parent is defined (extends someClass) but someClass is not available in the tested code (it may be in composer, another dependency, or just not there) it will not be reported.  Command Line Classes/UndefinedParentMP Analyzers Analyze Undefined Properties¶ List of properties that are not explicitely defined in the class, its parents or traits.  Command Line Classes/UndefinedProperty clearPHP no-undefined-properties Analyzers Analyze Undefined Trait¶ Those traits are undefined. When the using class or trait is instantiated, PHP emits a a fatal error. <?php use Composer/Component/someTrait as externalTrait; trait t { function foo() {} } // This class uses trait that are all known class hasOnlyDefinedTrait { use t, externalTrait; } // This class uses trait that are unknown class hasUndefinedTrait { use unknownTrait, t, externalTrait; } ?>   Command Line Traits/UndefinedTrait Analyzers Analyze Undefined static:: Or self::¶ List of all undefined static and self properties and methods.  Command Line Classes/UndefinedStaticMP Analyzers Analyze Unescaped Variables In Templates¶ Whenever variables are emitted, they are reported as long as they are not escaped. While this is quite a strict rule, it is good to know when variables are not protected at echo time. <?php echo unescapedVariable; echo esc_html(escapedVariable); ?>   Command Line Wordpress/UnescapedVariables Analyzers Wordpress Unicode Escape Partial¶ PHP 7 introduces a new escape sequence for strings : u{hex}. It is backward incompatible with previous PHP versions for two reasons : PHP 7 will recognize en replace those sequences, while PHP 5 keep them intact. PHP 7 will halt on partial Unicode Sequences, as it tries to understand them, but may fail. <?php echo \u{1F418}\n; // PHP 5 displays the same string // PHP 7 displays : an elephant echo \u{NOT A UNICODE CODEPOINT}\n; // PHP 5 displays the same string // PHP 7 emits a fatal error ?>  Is is recommended to check all those strings, and make sure they will behave correctly in PHP 7.  Command Line Php/UnicodeEscapePartial Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Unicode Escape Syntax¶ Usage of the Unicode Escape syntax, with the u{xxxxx} format, available since PHP 7.0. <?php // Produce an elephant icon in PHP 7.0+ echo \u{1F418}; // Produce the raw sequence in PHP 5.0 echo \u{1F418}; ?>   Command Line Php/UnicodeEscapeSyntax Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 Unitialized Properties¶ Properties that are not initialized in the constructor, nor at definition. <?php class X { private i1 = 1, i2; protected u1, u2; function __construct() { this->i2 = 1 + this->u2; } function m() { echo this->i1, this->i2, this->u1, this->u2; } } ?>  With the above class, when m() is accessed right after instantiation, there will be a missing property. Using default values at property definition, or setting default values in the constructor ensures that the created object is consistent.  Command Line Classes/UnitializedProperties Analyzers Analyze Unknown Directive Name¶ Unknown directives names used in the code. The following list has directive mentionned in the code, that are not known from PHP or any extension. If this is due to a mistake, the directive must be fixed to be actually useful. <?php // non-existing directive reporting_error = ini_get('reporting_error'); error_reporting = ini_get('error_reproting'); // Note the inversion if (ini_set('dump_globals')) { // doSomething() } // Correct directives error_reporting = ini_get('reporting_error'); if (ini_set('xdebug.dump_globals')) { // doSomething() } ?>   Command Line Php/DirectiveName Analyzers Analyze Unkown Regex Options¶ PHP’s regex support the following list of options : eimsuxADJSUX. They are detailled in the manual : [http://php.net/manual/en/reference.pcre.pattern.modifiers.php](http://php.net/manual/en/reference.pcre.pattern.modifiers.php). All other options are not supported, may be ignored or raise an error. <?php // all options are available if (preg_match('/\d+/isA', string, results)) { } // p and h are not regex options, p is double if (preg_match('/\d+/php', string, results)) { } ?>   Command Line Structures/UnknownPregOption Analyzers Analyze Unpreprocessed Values¶ PHP is good at manipulating data. However, it is also good to preprocess those values, and put them in the code directly as expected, rather than have PHP go the extra step and do it for you. For example : <?php x = explode(',', 'a,b,c,d'); ?>  could be written <?php x = array('a', 'b', 'c', 'd'); ?>  and avoid preprocessing the string into an array first.  Command Line Structures/Unpreprocessed clearPHP always-preprocess Analyzers Analyze Unreachable Code¶ Code may be unreachable, because other instructions prevent its reaching. For example, it be located after throw, return, exit(), die(), goto, break or continue : this way, it cannot be reached, as the previous instruction will divert the engine to another part of the code. <?php function foo() { a++; return a; b++; // b++ can't be reached; } function bar() { if (a) { return a; } else { return b; } b++; // b++ can't be reached; } foreach(a as b) { c += b; if (c > 10) { continue 1; } else { c--; continue; } d += e; // this can't be reached } a = 1; goto B; class foo {} // Definitions are accessible, but not functioncalls B: echo a; ?>  This is dead code, that may be removed.  Command Line Structures/UnreachableCode clearPHP no-dead-code Analyzers Analyze, Dead code Unresolved Catch¶ Catch clauses do not check for Exception existence. Catch clauses check that the emitted expression is of the requested Class, but if that class doesn’t exist in the code, the catch clause is always false. This is dead code. <?php try { // doSomething() } catch {TypoedExxeption e) { // Do not exist Exception // Fix this exception } catch {Stdclass e) { // Exists, but is not an exception // Fix this exception } catch {Exception e) { // Actual and effective catch // Fix this exception } ?>   Command Line Classes/UnresolvedCatch clearPHP no-unresolved-catch Analyzers Dead code Unresolved Classes¶ The following classes are instantiated in the code, but their definition couldn’t be found. Check for namespaces and aliases and make sure they are correctly configured.  Command Line Classes/UnresolvedClasses Analyzers Analyze Unresolved Instanceof¶ instanceof doesn’t check if compared class exists. It checks if an variable is of a specific class. However, if the referenced class doesn’t exist, because of a bug, a missed inclusion or a typo, the operator always fails, without a warning. <?php namespace X { class C {} // This is OK, as C is defined in X if (o instanceof C) { } // This is not OK, as C is not defined in global // instanceof respects namespaces and use expressions if (o instanceof \C) { } // This is not OK, as undefinedClass if (o instanceof undefinedClass) { } // This is not OK, as class is now a full namespace. It actually refers to \c, which doesn't exist class = 'C'; if (o instanceof class) { } } ?>  Make sure the following classes are well defined.  Command Line Classes/UnresolvedInstanceof clearPHP no-unresolved-instanceof Analyzers Analyze, Dead code Unresolved Use¶ The following use instructions cannot be resolved to a class or a namespace. They should be dropped or fixed.  Command Line Namespaces/UnresolvedUse clearPHP no-unresolved-use Analyzers Analyze Unserialize Second Arg¶ Since PHP 7, unserialize() function has a second argument that limits the classes that may be unserialized. In case of a breach, this is limiting the classes accessible from unserialize(). On way to exploit unserialize, is to make PHP unserialized the data to an available class, may be one that may be auto-loaded. <?php // expected Database object var = unserialize('O:7:dbClass:0:{}'); // unexpected load of debugClass object var = unserialize('O:10:debugClass:0:{}'); // Using the unserialized object var->connect(); ?>   Command Line Security/UnserializeSecondArg Analyzers Security Unset In Foreach¶ Unset applied to the variables of a foreach loop are useless, as they are copies and not the actual value. Even if the value is a reference, unsetting it will not have effect on the original array : the only effect may be on values inside an array, or on properties inside an object. <?php // When unset is useless array = [1, 2, 3]; foreach(array as a) { unset(a); } print_r(array); // still [1, 2, 3] foreach(array as b => &a) { unset(a); } print_r(array); // still [1, 2, 3] // When unset is useful array = [ [ 'c' => 1] ]; // Array in array foreach(array as &a) { unset(&a['c']); } print_r(array); // now [ ['c' => null] ] ?>   Command Line Structures/UnsetInForeach Analyzers Dead code, Analyze Unthrown Exception¶ These are exceptions that are defined in the code but never thrown.  Command Line Exceptions/Unthrown clearPHP no-unthrown-exceptions Analyzers Analyze, Dead code Unused Arguments¶ Those arguments are not used in the method or function. Unused arguments should be removed in functions : they are just dead code. Unused argument may have to stay in methods, as the signature is actually defined in the parent class. <?php // unused is in the signature, but not used. function foo(unused, b, c) { return b + c; } ?>   Command Line Functions/UnusedArguments Analyzers Analyze Unused Classes¶ The following classes are never explicitely used in the code. Note that this may be valid in case the current code is a library or framework, since it defines classes that are used by other (unprovided) codes. Also, this analyzer may find classes that are, in fact, dynamically loaded.  Command Line Classes/UnusedClass Analyzers Analyze, Dead code Unused Constants¶ Those constants are defined in the code but never used. Defining unused constants will slow down the application, has they are executed and stored in PHP hashtables. It is recommended to comment them out, and only define them when it is necessary.  Command Line Constants/UnusedConstants Analyzers Analyze, Dead code Unused Functions¶ The functions below are unused. They look like deadcode.  Command Line Functions/UnusedFunctions Analyzers Analyze, Dead code Unused Global¶ List of global keyword, used in various functions but not actually used in the code. for example : <?php function foo() { global bar; return 1; } ?>   Command Line Structures/UnusedGlobal Analyzers Analyze Unused Interfaces¶ Those interfaces are defined but not used. They should be removed.  Command Line Interfaces/UnusedInterfaces Analyzers Analyze, Dead code Unused Label¶ The following labels have been defined in the code, but they are not used. They may be removed.  Command Line Structures/UnusedLabel Analyzers Dead code, Analyze Unused Methods¶ The following methods are never called as methods. They are probably dead code.  Command Line Classes/UnusedMethods Analyzers Analyze, Dead code Unused Protected Methods¶ The following methods are protected, and may be used in the current class or any of its children. <?php class foo { // This method is not used protected function unusedBar() {} protected function usedInFoo() {} protected function usedInFooFoo() {} public function bar2() { // some code this->usedInFoo(); } } class foofoo extends foo { protected function bar() {} public function bar2() { // some code this->usedInFooFoo(); } } class someOtherClass { protected function bar() { // This is not related to foo. this->unusedbar(); } } ?>  No usage of those methods were found. This analysis is impacted by dynamic method calls.  Command Line Classes/UnusedProtectedMethods Analyzers Dead code Unused Returned Value¶ The function called returns a value, which is ignored. Usually, this is a sign of dead code, or a missed check on the results of the functioncall. At times, it may be a valid call if the function has voluntarily no return value. It is recommended to add a check on the return value, or remove the call. <?php // simplest form function foo() { return 1; } foo(); // In case of multiple return, any one that returns something means that return value is meaningful function bar() { if (rand(0, 1)) { return 1; } else { return ; } } bar(); ?>  Note that this analysis ignores functions that return void (same meaning that PHP 7.1 : return ; or no return in the function body).  Command Line Functions/UnusedReturnedValue Analyzers Analyze, Dead code Unused Static Methods¶ List of all static methods that are not used. This looks like dead code.  Command Line Classes/UnusedPrivateMethod Analyzers Analyze, Dead code Unused Static Properties¶ List of all static properties that are not used. This looks like dead code.  Command Line Classes/UnusedPrivateProperty Analyzers Analyze, Dead code Unused Traits¶ Those traits are not used in a class or another trait. They may be dead code. <?php // unused trait trait unusedTrait { /**/ } // used trait trait tUsedInTrait { /**/ } trait tUsedInClass { use tUsedInTrait; /**/ } class foo { use tUsedInClass; } ?>   Command Line Traits/UnusedTrait Analyzers Analyze Unused Use¶ Unused use statements. They may be removed, as they clutter the code and slows PHP by forcing it to search in this list for nothing. <?php use A as B; // Used in a new call. use Unused; // Never used. May be removed a = new B(); ?>   Command Line Namespaces/UnusedUse clearPHP no-useless-use Analyzers Analyze, Dead code Unusual Case For PHP Functions¶ Usually, PHP functions are written all in lower case.  Command Line Php/UpperCaseFunction Analyzers Coding Conventions Unverified Nonce¶ Those nonces are never checked. Nonces were created in the code with wp_nonce_field(), wp_nonce_url() and wp_nonce_create() functions, but they are not verified with wp_verify_nonce() nor check_ajax_referer() <?php nonce = wp_create_nonce( 'my-nonce' ); if ( ! wp_verify_nonce( nonce, 'my-other-nonce' ) ) { } else { } ?>   Command Line Wordpress/UnverifiedNonce Analyzers Wordpress Use wpdb Api¶ It is recommended to use the Wordpress Database API, instead of using query. This is especially true for UPDATE, REPLACE, INSERT and DELETE queries. <?php // Generic query wpdb->query('DELETE FROM ' . table . ' WHERE id=' . id . ' LIMIT 1'); // Wordpress query wpdb->delete( table, array( 'id' => id ), array('id' => '%d')); ?>   Command Line Wordpress/UseWpdbApi Analyzers Wordpress Use === null¶ It is faster to use === null instead of is_null(). <?php // Operator === is fast if (a === null) { } // Function call is slow if (is_null(a)) { } ?>   Command Line Php/IsnullVsEqualNull clearPHP avoid-those-slow-functions Analyzers Analyze Use Class Operator¶ Use ::class to hardcode class names, instead of strings. This is actually faster than strings, which are parsed at executio time, while ::class is compiled, making it faster to execute. It is also capable to handle aliases, making the code easier to maintain. <?php namespace foo\bar; use foo\bar\X as B; class X {} className = '\foo\bar\X'; className = foo\bar\X::class; className = B\X; object = new className; ?>  This is not possible when building the name of the class with concatenation. This is a micro-optimization.  Command Line Classes/UseClassOperator Analyzers Analyze, Performances Use Const And Functions¶ Since PHP 5.6 it is possible to import specific functions or constants from other namespaces.  Command Line Namespaces/UseFunctionsConstants Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 Use Constant As Arguments¶ Some methods and functions are defined to be used with constants as arguments. Those constants are made to be meaningful and readable, keeping the code maintenable. It is recommended to use such constants as soon as they are documented.  Command Line Functions/UseConstantAsArguments Analyzers Analyze Use Instanceof¶ The instanceof operator is a faster alternative to is_object(). instanceof checks for an variable to be of a class or its parents or the interfaces it implements. Once instanceof has been used, the actual attributes available (properties, constants, methods) are known, unlike with is_object(). Last, instanceof may be upgraded to Typehint, by moving it to the method signature. <?php class Foo { // Don't use is_object public function bar(o) { if (!is_object(o)) { return false; } // Classic argument check return o->method(); } // use instanceof public function bar(o) { if (o instanceof myClass) { // Now, we know which methods are available return o->method(); } return false; } // Default behavior } // use of typehinting // in case o is not of the right type, exception is raised automatically public function bar(myClass o) { return o->method(); } } ?>  instanceof and is_object() may not be always interchangeable. Consider using isset on a known property for a simple check on object. You may also consider is_string(), is_integer() or is_scalar(), in particular instead of !is_object() <http://www.php.net/is_object>_. The instanceof operator is also faster than the is_object() functioncall.  Command Line Classes/UseInstanceof Analyzers Analyze, Analyze Use Lower Case For Parent, Static And Self¶ Until PHP 5.5, the special Parent, Static and Self keywords needed to be lowercase to be useable. Otherwise, they would yield a ‘PHP Fatal error: Class ‘PARENT’ not found’. parent, static and self are traditionally written in lowercase only. Mixed case and Upper case are both valid, though. <?php class foo { const aConstante = 233; function method() { // Wrong case, error with PHP 5.4.* and older echo SELF::aConstante; // Always right. echo self::aConstante; } } ?>  Until PHP 5.5, non-lowercase version of those keywords are generating a bug.  Command Line Php/CaseForPSS Analyzers Analyze, CompatibilityPHP54, CompatibilityPHP53 Use Nullable Type¶ The code uses nullable type, available since PHP 7.1. <?php function foo(?string a = abc) : ?string { return a.b; } ?>   Command Line Php/UseNullableType Analyzers CompatibilityPHP71, CompatibilityPHP72 Use Object Api¶ When PHP offers the alternative between procedural and OOP api for the same features, it is recommended to sue the OOP API. Often, this least to more compact code, as methods are shorter, and there is no need to bring the resource around. Lots of new extensions are directly written in OOP form too.  Command Line Php/UseObjectApi clearPHP use-object-api Analyzers Analyze Use Pathinfo¶ Use pathinfo() function instead of string manipulations. pathinfo() is more efficient and readable and string functions. <?php filename = '/path/to/file.php'; // With pathinfo(); details = pathinfo(filename); print details['extension']; // also capture php // With string functions (other solutions possible) ext = substr(filename, - strpos(strreverse(filename), '.')); // Capture php ?>  When the path contains UTF-8 characters, pathinfo() may strip them. There, string functions are necessary.  Command Line Php/UsePathinfo Analyzers Analyze Use Positive Condition¶ Whenever possible, use a positive condition. Positive conditions are easier to understand, and lead to less understanding problems. Negative conditions are not reported when else is not present. <?php // This is a positive condition if (a == 'b') { doSomething(); } else { doSomethingElse(); } if (!empty(a)) { doSomething(); } else { doSomethingElse(); } // This is a negative condition if (a == 'b') { doSomethingElse(); } else { doSomething(); } // No need to force a == 'b' with empty else if (a != 'b') { doSomethingElse(); } ?>   Command Line Structures/UsePositiveCondition Analyzers Analyze Use System Tmp¶ It is recommended to avoid hardcoding the tmp file. It is better to rely on the system’s tmp folder, which is accessible with sys_get_temp_dir(). <?php // Where the tmp is : file_put_contents(sys_get_temp_dir().'/tempFile.txt', content); // Avoid hard-coding tmp folder : // On Linux-like systems file_put_contents('/tmp/tempFile.txt', content); // On Windows systems file_put_contents('C:\WINDOWS\TEMP\tempFile.txt', content); ?>   Command Line Structures/UseSystemTmp Analyzers Analyze Use With Fully Qualified Name¶ Use statement doesn’t require a fully qualified name. PHP manual recommends not to use fully qualified name (starting with ) when using the ‘use’ statement : they are “the leading backslash is unnecessary and not recommended, as import names must be fully qualified, and are not processed relative to the current namespace”. <?php // Recommended way to write a use statement. use A\B\C\D as E; // No need to use the initial \ use \A\B\C\D as F; ?>   Command Line Namespaces/UseWithFullyQualifiedNS Analyzers Analyze, Coding Conventions Use Wordpress Functions¶ Always use Wordpress functions instead of native PHP ones. Wordpress provides a lot of functions, that replace PHP natives one. It is recommended to used them. Here is a table of conversion :  PHP Wordpress mail() header() header() exit() die() rand() mt_rand() wp_mail() wp_redirect() wp_safe_redirect() wp_die() wp_die() wp_rand() wp_rand() <?php // use Wordpress Mail wp_mail('to@exakat.io', 'Mail subject', 'Mail message'); // do not use PHP mail mail('to@exakat.io', 'Mail subject', 'Mail message'); ?>   Command Line Wordpress/UseWpFunctions Analyzers Wordpress Use const¶ The const keyword may be used to define constant, just like the define() function. When defining a constant, it is recommended to use ‘const’ when the features of the constant are not dynamical (name or value are known at compile time). This way, constant will be defined at compile time, and not at execution time. <?php //Do const A = 1; // Don't define('A', 1); ?>  define() function is useful when the constant is not known at compile time, or when case sensitivity is necessary. <?php // Read a in database or config file define('A', a); // Read a in database or config file define('B', 1, true); echo b; ?>   Command Line Constants/ConstRecommended Analyzers Analyze, Coding Conventions Use password_hash()¶ PHP 5.5 introduced password_hash() and password_check() to replace the use of crypt() to check password.  Command Line Php/Password55 Analyzers CompatibilityPHP55, CompatibilityPHP70, CompatibilityPHP56, CompatibilityPHP71 Use random_int()¶ rand() and mt_rand() should be replaced with random_int(). At worse, rand() should be replaced with mt_rand(), which is a drop-in replacement and srand() by mt_srand(). random_int() replaces rand(), and has no seeding function like srand(). <?php // Avoid using this random = rand(0, 10); // Drop-in replacement random = mt_rand(0, 10); // Even better but different : // valid with PHP 7.0+ try { random = random_int(0, 10); } catch (\Exception e) { // process case of not enoug random values } ?>  Since PHP 7, random_int() along with random_bytes(), provides cryptographically secure pseudo-random bytes, which are good to be used when security is involved. openssl_random_pseudo_bytes() may be used when the OpenSSL extension is available.  Command Line Php/BetterRand Analyzers Analyze, Security, CompatibilityPHP71, CompatibilityPHP72 Used Once Property¶ Property used once in their defining class. Properties used in one method only may be used several times, and read only. This may be a class constant. Such properties are meant to be overwritten by an extending class, and that’s possible with class constants. Setting properties with default values is a good way to avoid literring the code with literal values, and provide a single point of update (by extension, or by hardcoding) for all those situations. A constant is definitely better suited for this task. <?php class foo { private defaultCols = '*'; cont DEFAULT_COLUMNS = '*'; // this->defaultCols holds a default value. Should be a constant. function bar(table, cols) { // This is necessary to activate usage of default values if (empty(cols)) { cols = this->defaultCols; } res = this->query('SELECT '.cols.' FROM '.table); // .... } // Upgraded version of bar, with default values function bar2(table, cols = self::DEFAULT_COLUMNS) { res = this->query('SELECT '.cols.' FROM '.table); // ..... } } ?>   Command Line Classes/UsedOnceProperty Analyzers Analyze Used Once Variables¶ This is the list of used once variables. <?php // The variables below never appear again in the code writtenOnce = 1; foo(readOnce); ?>  Such variables are useless. Variables must be used at least twice : once for writing, once for reading, at least. It is recommended to remove them. In special situations, variables may be used once : • PHP predefined variables, as they are already initialized. They are omitted in this analyze. • Interface function’s arguments, since the function has no body; They are omitted in this analyze. • Dynamically created variables ($$x, ${$this->y} or also using extract), as they are runtime values and can’t be determined at static code time. They are reported for manual review.
• Dynamically included files will provide in-scope extra variables.

The current analyzer count variables at the application level, and not at a method scope level.

 Command Line Variables/VariableUsedOnce Analyzers Analyze

Used Once Variables (In Scope)¶

This is the list of used once variables, scope by scope. Those variables are used once in a function, a method, a class or a namespace. In any case, this means the variable is read or written, while it should be used at least twice.

<?php

function foo() {
// The variables below never appear twice, inside foo()
$writtenOnce = 1; foo($readOnce);
// They do appear again in other functions, or in global space.
}

function bar() {
$writtenOnce = 1; foo($readOnce);
}

?>

 Command Line Variables/VariableUsedOnceByContext Analyzers Analyze

Used Protected Method¶

Marks methods being used in the current class or its children classes.

 Command Line Classes/UsedProtectedMethod Analyzers Dead code

Useless Abstract Class¶

Those classes are marked ‘abstract’ and they are never extended. This way, they won’t be instantiated nor used.

Abstract classes that have only static methods are omitted here : one usage of such classes are Utilities classes, which only offer static methods.

<?php

// Never extended class : this is useless
abstract class foo {}

// Extended class
abstract class bar {
public function barbar() {}
}

class bar2 extends bar {}

// Utility class : omitted here
abstract class bar {
public static function barbar() {}
}

?>

 Command Line Classes/UselessAbstract Analyzers Analyze

Useless Brackets¶

Those brackets have no use here.

They may be a left over of an old instruction, or a misunderstanding of the alternative syntax.

<?php

// The following brackets are useless : they are a leftover from an older instruction
// if (DEBUG)
{
$a = 1; } // Here, the extra brackets are useless for($a = 2; $a < 5;$a++) : {
$b++; } endfor; ?>   Command Line Structures/UselessBrackets Analyzers Analyze Useless Casting¶ There is no need to overcast returned values. <?php // trim always returns a string : cast is useless$a = (string) trim($b); // strpos doesn't always returns an integer : cast is useful$a = (boolean) strpos($b,$c);

// comparison don't need casting, nor parenthesis
$c = (bool) ($b > 2);

?>

 Command Line Structures/UselessCasting Analyzers Analyze

Useless Check¶

Situation where the condition is useless.

<?php

// Checking for type is good.
if (is_array($array)) { foreach($array as $a) { doSomething($a);
}
}

// Foreach on empty arrays doesn't start. Checking is useless
if (!empty($array)) { foreach($array as $a) { doSomething($a);
}
}

?>

 Command Line Structures/UselessCheck Analyzers Analyze

Useless Constructor¶

Class constructor that have empty bodies are useless. They may be removed.

 Command Line Classes/UselessConstructor Analyzers Analyze

Useless Final¶

When a class is declared final, all of its methods are also final by default.

There is no need to declare them individually final.

<?php

final class foo {
// Useless final, as the whole class is final
final function method() { }
}

class bar {
// Usefule final, as the whole class is not final
final function method() { }
}

?>

 Command Line Classes/UselessFinal clearPHP no-useless-final Analyzers Analyze

Useless Global¶

Global are useless in two cases. First, on super-globals, which are always globals, like $_GET. Secondly, on variables that are not used. <?php //$_POST is already a global : it is in fact a global everywhere
global $_POST; //$unused is useless
function foo() {
global $used,$unused;

++$used; } ?>  Also, PHP has superglobals, a special team of variables that are always available, whatever the context. They are :$GLOBALS, $_SERVER,$_GET, $_POST,$_FILES, $_COOKIE,$_SESSION, $_REQUEST and$_ENV.

 Command Line Structures/UselessGlobal Analyzers Analyze

Useless Instructions¶

Those instructions are useless, or contains useless parts.

For example, running ‘&lt;?php 1 + 1; ?&gt;’ does nothing : the addition is actually performed, but not used : not displayed, not stored, not set. Just plain lost.

Here the useless instructions that are spotted :

<?php

// This is a typo, that PHP turns into a constant, then a string.
conitnue;

// Empty string in a concatenation
$a = 'abc' . ''; // Returning expression, whose result is not used (additions, comparisons, properties, closures, new without =, ...) 1 + 2; // Returning post-incrementation function foo($a) {
return $a++; } // array_replace() with only one argument$replaced = array_replace($array); // array_replace() is OK with ...$replaced = array_replace(...$array); // @ operator on source array, in foreach, or when assigning literals$array = @array(1,2,3);

// Multiple comparisons in a for loop : only the last is actually used.
for($i = 0;$j = 0; $j < 10,$i < 20; ++$j, ++$i) {
print $i.' '.$j.PHP_EOL;
}

?>

 Command Line Structures/UselessInstruction clearPHP no-useless-instruction Analyzers Analyze

Useless Interfaces¶

The interfaces below are defined and are implemented by some classes. However, they are never used to enforce objects’s class in the code, using instanceof or a typehint. As they are currently used, those interfaces may be removed without change in behavior.

<?php
// only defined interface but never enforced
interface i {};
class c implements i {}
?>


Interfaces should be used in Typehint or with the instanceof operator.

<?php
interface i {};

function foo(i $arg) { // Now,$arg is always an 'i'
}

function bar($arg) { if (!($arg instanceof i)) {
// Now, $arg is always an 'i' } } ?>   Command Line Interfaces/UselessInterfaces clearPHP no-useless-interfaces Analyzers Analyze Useless Parenthesis¶ Situations where parenthesis are not necessary, and may be removed. <?php if ( ($condition) ) {}
while( ($condition) ) {} do$a++; while ( ($condition) ); switch ( ($a) ) {}
$y = (1); ($y) == (1);

f(($x)); // = has precedence over == ($a = $b) ==$c;

($a++); // No need for parenthesis in default values function foo($c = ( 1 + 2) ) {}
?>

 Command Line Structures/UselessParenthesis Analyzers Analyze

Useless Return¶

The spotted functions or methods have a return statement, but this statement is useless. This is the case for constructor and destructors, whose return value are ignored or inaccessible.

When return is void, and the last element in a function, it is also useless.

<?php

class foo {
function __construct() {
// return is not used by PHP
return 2;
}
}

function bar(&$a) {$a++;
// The last return, when empty, is useless
return;
}

?>

 Command Line Functions/UselessReturn Analyzers Analyze

Useless Switch¶

This switch has only one case. It may very well be replaced by a ifthen structure.

<?php
switch($a) { case 1: doSomething(); break; } // Same as if ($a == 1) {
doSomething();
}
?>

 Command Line Structures/UselessSwitch Analyzers Analyze

Useless Unset¶

Unsetting variables may not be applicable with a certain type of variables. This is the list of such cases.

<?php

function foo($a) { // unsetting arguments is useless unset($a);

global $b; // unsetting global variable has no effect unset($b);

static $c; // unsetting static variable has no effect unset($c);

foreach($d as$e){
// unsetting a blind variable is useless
(unset) $e; } } ?>   Command Line Structures/UselessUnset clearPHP no-useless-unset Analyzers Analyze Uses Default Values¶ Default values are provided to methods so as to make it convenient to use. However, with new versions, those values may change. For example, in PHP 5.4, htmlentities() switched from Latin1 to UTF-8 default encoding. <?php$string = Eu não sou o pão;

echo htmlentities($string); // PHP 5.3 : Eu n&Atilde;&pound;o sou o p&Atilde;&pound;o // PHP 5.4 : Eu n&atilde;o sou o p&atilde;o // Stable across versions echo htmlentities($string, 'UTF8');

?>


As much as possible, it is recommended to use explicit values in those methods, so as to prevent from being surprise at a future PHP evolution.

This analyzer tend to report a lot of false positives, including usage of count(). Count() indeed has a second argument for recursive counts, and a default value. This may be ignored safely.

 Command Line Functions/UsesDefaultArguments Analyzers Analyze

Using $this Outside A Class¶$this is a special variable, that should only be used in a class context.

Until PHP 7.1, $this may be used as an argument in a function (or a method), a global, a static : while this is legit, it sounds confusing enough to avoid it. <?php function foo($this) {
echo $this; } ?>  Starting with PHP 7.1, the PHP engine check thouroughly that$this is used in an appropriate manner, and raise fatal errors in case it isn’t.

 Command Line Classes/UsingThisOutsideAClass Analyzers Analyze, CompatibilityPHP71, CompatibilityPHP72

Usort Sorting In PHP 7.0¶

Usort(), uksort() and uasort() behavior has changed in PHP 7. Values that are equals (based on the user-provided method) may be sorted differently than in PHP 5.

If this sorting is important, it is advised to add extra comparison in the user-function and avoid returning 0 (thus, depending on default implementation).

<?php

$a = [ 2, 4, 3, 6]; function noSort($a) { return $a > 5; } usort($a, 'noSort');
// Avoid var
//var $bar = 1; } ?>   Command Line Classes/OldStyleVar clearPHP no-php4-class-syntax Analyzers Analyze Variable Global¶ Variable global such are valid in PHP 5.6, but no in PHP 7.0. They should be replaced with${$foo->bar}. <?php // Forbidden in PHP 7 global$normalGlobal;

// Forbidden in PHP 7
global variable->global ;

// Tolerated in PHP 7
global ${$variable->global};

?>

 Command Line Structures/VariableGlobal Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56

While(List() = Each())¶

This code structure is quite old : it should be replace by the more modern and efficient foreach.

<?php
foreach($array as$key => $value) { doSomethingWith($key) and $value; } ?>   Command Line Structures/WhileListEach Analyzers Analyze, Performances Wpdb Best Usage¶ Use the adapted API with$wpdb.

Wordpress database API ($wpdb) offers several eponymous methods to safely handle insert, delete, replace and update. It is recommended to use them, instead of writing queries with concatenations. <?php // Example from Wordpress Manual$user_count = $wpdb->get_var( "SELECT COUNT(*) FROM$wpdb->users" );
echo <p>User count is {$user_count}</p>; ?>   Command Line Wordpress/WpdbBestUsage Analyzers Wordpress Wpdb Prepare Or Not¶ Always use$wpdb->prepare() when variables are used in the SQL query.

When using $wpdb, it is recommended to use directly the query() method when the SQL is not using variables. <?php // No need to prepare this query : it is all known at coding time.$wpdb->prepare('INSERT INTO table VALUES (1,2,3)');

// No need to prepare this query : $wpdb->prefix is safe$wpdb->prepare('INSERT INTO {$wpdb->prefix}table values (1,2,3)'); // Don't use query when variable are involved : always use prepare$wpdb->query('INSERT INTO TABLE values (1,2,'.$var.')'); ?>   Command Line Wordpress/WpdbPrepareOrNot Analyzers Wordpress Written Only Variables¶ Those variables are being written, but never read. This way, they are useless and should be removed, or read at some point.  Command Line Variables/WrittenOnlyVariable clearPHP no-unused-variable Analyzers Analyze Wrong Number Of Arguments¶ Those functioncalls are made with too many or too few arguments. Some of them will be dropped, or PHP will raise errors when values are missing. It is recommended to check the signature of the methods, and fix the arguments.  Command Line Functions/WrongNumberOfArguments clearPHP no-missing-argument.md Analyzers Analyze Wrong Optional Parameter¶ Wrong placement of optional parameters. PHP parameters are optional when they defined with a default value, like this : <?php function x($arg = 1) {
// PHP code here
}
?>


When a function have both compulsory and optional parameters, the compulsory ones should appear first, and the optional should appear last :

<?php
function x($arg,$arg2 = 2) {
// PHP code here
}
?>


PHP will solve this problem at runtime, assign values in the same other, but will miss some of the default values and emits warnings.

It is better to put all the optional parameters at the end of the method’s signature.

 Command Line Functions/WrongOptionalParameter Analyzers Analyze

Wrong Parameter Type¶

The expected parameter is not of the correct type. Check PHP documentation to know which is the right format to be used.

<?php

// substr() shouldn't work on integers.
// the first argument is first converted to string, and it is 123456.
echo substr(123456, 0, 4); // display 1234

// substr() shouldn't work on boolean
// the first argument is first converted to string, and it is 1, and not t
echo substr(true, 0, 1); // displays 1

// substr() works correctly on strings.
echo substr(123456, 0, 4);

?>

 Command Line Php/InternalParameterType Analyzers Analyze

Wrong fopen() Mode¶

Wrong file opening for fopen().

fopen() has a few modes, as described in the documentation : ‘r’, ‘r+’, for reading; ‘w’, ‘w+’ for writing; ‘a’, ‘a+’ for appending; ‘x’, ‘x+’ for modifying; ‘c’, ‘c+’ for writing and locking, ‘t’ for text files and windows only. An optional ‘b’ may be used to make the fopen() call more portable and binary safe.

<?php

// open the file for reading, in binary mode
$fp = fopen('/tmp/php.txt', 'rb'); // New option e in PHP 7.0.16 and 7.1.2 (beware of compatibility)$fp = fopen('/tmp/php.txt', 'rbe');

// Unknown option x
$fp = fopen('/tmp/php.txt', 'rbx'); ?>  Any other values are not understood by PHP.  Command Line Php/FopenMode Analyzers Analyze Yoda Comparison¶ Yoda comparison is a way to write conditions which places literal values on the left side. <?php if (1 ==$a) {
// Then condition
}
?>


The objective is to avoid mistaking a comparison to an assignation. If the comparison operateur is mistaken, but the literal is on the left, then an error will be triggered, instead of a silent bug.

<?php
// error in comparison!
if ($a = 1) { // Then condition } ?>   Command Line Structures/YodaComparison Analyzers Coding Conventions __DIR__ Then Slash¶ __DIR__ must be concatenated with a string starting with /. The magic constant __DIR__ holds the name of the current directory, without final /. When it is used to build path, then the following path fragment must start with /. Otherwise, two directories names will be merged together. <?php // __DIR__ = /a/b/c //$filePath = /a/b/c/g.php

// /a/b/c/d/e/f.txt : correct path
echo __DIR__.'/d/e/f.txt';
echo dirname($filePath).'/d/e/f.txt'; // /a/b/cd/e/f.txt : most probably incorrect path echo __DIR__.'d/e/f.txt'; echo dirname($filePath).'d/e/f.txt';

?>

 Command Line Structures/DirThenSlash Analyzers Analyze

__debugInfo() usage¶

The magic function __debugInfo() has been introduced in PHP 5.6. In the previous versions of PHP, this method is ignored and won’t be called when debugging.

<?php

// PHP 5.6 or later
class foo {
private $bar = 1; private$reallyHidden = 2;

function __debugInfo() {
return ['bar' => $this->bar, 'reallyHidden' => 'Secret']; } }$f = new Foo();
var_dump($f); ?>  This ends up with :: object(foo)#1 (2) { [bar]=> int(1) [reallyHidden]=> string(6) Secret }   Command Line Php/debugInfoUsage Analyzers CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55 __toString() Throws Exception¶ Magical method __toString() can’t throw exceptions, according to the world.  Command Line Structures/toStringThrowsException Analyzers Analyze crypt() Without Salt¶ PHP 5.6 and later require a salt, while previous versions didn’t require it. Salt is a simple string, that is usually only known by the application.  Command Line Structures/CryptWithoutSalt Analyzers Analyze, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP70, CompatibilityPHP56, CompatibilityPHP71 error_reporting() With Integers¶ Using named constants with error_reporting is strongly encouraged to ensure compatibility for future versions. As error levels are added, the range of integers increases, so older integer-based error levels will not always behave as expected. (Adapted from the documentation). <?php // This is ready for PHP next version error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE & ~E_WARNING); // This is not ready for PHP next version error_reporting(2047); // -1 and 0 are omitted, as they will be valid even is constants changes. error_reporting(-1); error_reporting(0); ?>   Command Line Structures/ErrorReportingWithInteger Analyzers Analyze eval() Without Try¶ eval() emits a ParseError exception with PHP 7 and later. Catching this exception is the recommended way to handle errors when using the eval() function. <?php$code = 'This is no PHP code.';

//PHP 5 style
eval($code); // Ends up with a Fatal error, at execution time //PHP 7 style try { eval($code);
} catch (ParseError $e) { cleanUpAfterEval(); } ?>  Note that it will catch situations where eval() is provided with code that can’t be used, but it will not catch security problems. Avoid using eval() with incoming data.  Command Line Structures/EvalWithoutTry Analyzers Analyze, CompatibilityPHP53, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP56 ext/apc¶ Extension Alternative PHP Cache. <?php$bar = 'BAR';
apc_add('foo', $bar); var_dump(apc_fetch('foo')); echo \n;$bar = 'NEVER GETS SET';
} else {
$a++; print func_get_arg(0); } x(0); ?>  This code will display 1 in PHP 7, and 0 in PHP 5.  Command Line Functions/funcGetArgModified Analyzers Analyze, CompatibilityPHP70, CompatibilityPHP71 include_once() Usage¶ include_once() and require_once() functions should be avoided for performances reasons. <?php // Including a library. include 'lib/helpers.inc'; // Including a library, and avoiding double inclusion include_once 'lib/helpers.inc'; ?>  Try using autoload for loading classes, or use include() or require() and make it possible to include several times the same file without errors.  Command Line Structures/OnceUsage Analyzers Analyze list() May Omit Variables¶ list() is the only PHP function that accepts to have omitted arguments. If the following code makes no usage of a listed variable, just omit it. <?php list ($a, , $b) = array(1, 2, 3); ?> $b will be 3, and the 2 value will be omitted. This is cleaner, and save some memory.

 Command Line Structures/ListOmissions Analyzers Analyze

mcrypt_create_iv() With Default Values¶

mcrypt_create_iv used to have MCRYPT_DEV_RANDOM as default values, and in PHP 5.6, it now uses MCRYPT_DEV_URANDOM.

If the code doesn’t have a second argument, it relies on the default value. It is recommended to set explicitely the value, so has to avoid problems while migrating.

 Command Line Structures/McryptcreateivWithoutOption Analyzers Analyze, CompatibilityPHP54, CompatibilityPHP55, CompatibilityPHP70, CompatibilityPHP56, CompatibilityPHP71

parse_str() Warning¶

The parse_str() function parses a query string and assigns the resulting variables to the local scope. This may create a unexpected number of variables, and even overwrite the existing one.

<?php
function foo( ) {
global $a; echo$a;
}

parse_str('a=1'); // No second parameter
foo( );
// displays 1
?>


Always use an empty variable a second parameter to parse_str(), so as to collect the incoming values, and then, filter them in that array.

 Command Line Security/parseUrlWithoutParameters clearPHP know-your-variables Analyzers Security

preg_match_all() Flag¶

preg_match_all() has an option to configure the structure of the results : it is either by capturing parenthesis (by default), or by result sets.

The second option is the most interesting when the following foreach() loop has to manipulate several captured strings at the same time. No need to use an index in the first array and use it in the other arrays.

<?php
$string = 'ababab'; // default behavior preg_match_all('/(a)(b)/',$string, $r);$found = '';
foreach($r[1] as$id => $s) {$found .= $s.$r[2][$id]; } // better behavior preg_match_all('/(a)(b)/',$string, $r, PREG_SET_ORDER);$found = '';
foreach($r as$s) {
$found .=$s[1].$s[2]; } ?>  The second syntax is easier to read and may be marginally faster to execute (preg_match_all and foreach).  Command Line Php/PregMatchAllFlag Analyzers Analyze preg_replace With Option e¶ preg_replace() supported the /e option until PHP 7.0. It allowed the use of eval()‘ed expression as replacement. This has been dropped in PHP 7.0, for security reasons. preg_replace() with /e option may be replaced with preg_replace_callback() and a closure, or preg_replace_callback_array() and an array of closures. <?php // preg_replace with /e$string = 'abcde';

// PHP 5.6 and older usage of /e
$replaced = preg_replace('/c/e', 'strtoupper($0)', $string); // PHP 7.0 and more recent // With one replacement$replaced = preg_replace_callback('/c/', function ($x) { return strtoupper($x[0]); }, $string); // With several replacements, preventing multiple calls to preg_replace_callback$replaced = preg_replace_callback_array(array('/c/' => function ($x) { return strtoupper($x[0]); },
'/[a-b]/' => function ($x) { return strtolower($x[0]); }), $string); ?>   Command Line Structures/pregOptionE Analyzers Analyze, CompatibilityPHP70, Security, CompatibilityPHP71, CompatibilityPHP72 self, parent, static Outside Class¶ self, parent and static should be called inside a class or trait. PHP lint won’t report those situations. self, parent and static may be used in a trait : their actual value will be only known at execution time, when the trait is used. <?php // In the examples, self, parent and static may be used interchangeably // This raises a Fatal error //Fatal error: Uncaught Error: Cannot access static:: when no class scope is active new static(); // static calls echo self::CONSTANTE; echo self::$property;
echo self::method();

// as a type hint
function foo(static $x) { doSomething(); } // as a instanceof if ($x instanceof static) {
doSomething();
}

?>


Such syntax problem is only revealed at execution time : PHP raises a Fatal error.

The origin of the problem is usually a method that was moved outside a class, at least temporarily.

 Command Line Classes/NoPSSOutsideClass Analyzers Analyze

set_exception_handler() Warning¶

The set_exception_handler() callable function has to be adapted to PHP 7 : Exception is not the right typehint, it is now Throwable.

When in doubt about backward compatibility, just drop the Typehint. Otherwise, use Throwable.

<?php

// PHP 5.6- typehint
class foo { function bar(\Exception $e) {} } // PHP 7+ typehint class foo { function bar(Throwable$e) {} }

// PHP 5 and PHP 7 compatible typehint (note : there is none)
class foo { function bar($e) {} } set_exception_handler(foo); ?>   Command Line Php/SetExceptionHandlerPHP7 Analyzers CompatibilityPHP70, CompatibilityPHP71 var_dump()... Usage¶ var_dump(), print_r() or var_export() should not be left in any production code. They are debugging functions. <?php if ($error) {
// Debugging usage of var_dump
// And major security problem
var_dump($query); // This is OK : the$query is logged, and not displayed
$this->log(print_r($query, true));
}

?>


They may be tolerated during development time, but must be removed so as not to have any chance to be run in production.

 Command Line Structures/VardumpUsage clearPHP no-debug-code Analyzers Analyze, Security