I’m looking for some tool that would do basic testing of PHP script.
This time I’m not interested in complex testing solution that requires writing tests for each and every piece of code. I’m neither interested in functional tests.
What I expect this tool to do is to point out code fragments that might result in invalid usage of:
- variables;
- function arguments;
- function return values.
Invalid usage would be, for example, using NULL as an object or as an array or passing boolean as an arguent that is required to be an array or an object (or NULL).
Additionally, it might also check if “good practices” are used, i.e., it might warn that it’s not safe to use if ( $condition ) $doSomething;, if it finds something like that.
To illustrate what the tool should detect as “unsafe” code fragments, here are couple of examples.
In this case, $filter may be NULL, but it’s used as an array:
<?php
function getList(array $filter = null) {
$sql = '...';
// ...
foreach ( $filter as $field => $value ) {
// ...
}
// ...
}
In this case, $res might be false, but it’s used as a resource.
<?php
$res = mysql_query('...');
while ( $row = mysql_fetch_assoc($res) ) {
// ...
}
mysql_free_result($res);
And here are correspondent “safe” code fragments:
// $filter is used only if it's non-empty; as list of arguments describes, it may be only NULL or array
function getList(array $filter = null) {
$sql = '...';
// ...
if ( $filter ) {
foreach ( $filter as $field => $value ) {
// ...
}
}
// ...
}
…
// $filter is forced to be an array
function getList(array $filter = null) {
$filter = (array)$filter;
$sql = '...';
// ...
foreach ( $filter as $field => $value ) {
// ...
}
// ...
}
…
// if $res is false, mysql_fetch_assoc() and mysql_free_result() never executes
$res = mysql_query('...');
if ( $res === false ) {
trigger_error('...');
return;
}
while ( $row = mysql_fetch_assoc($res) ) {
// ...
}
mysql_free_result($res);
…
// if $res is false, mysql_fetch_assoc() and mysql_free_result() are skipped
$res = mysql_query('...');
if ( $res !== false ) {
while ( $row = mysql_fetch_assoc($res) ) {
// ...
}
mysql_free_result($res);
}
This is not basic testing, but requires non-trivial analysis of the token stream.
You can either use
phpmd
phpcs
or – if that doesn’t suffice – look at the bytecode level with
bytekit-cli
You will have to write you own sniffs for that.
Further tools and resources: