Home / Section index
 www.icosaedro.it 

 PHPLint FAQ

Last updated: 2010-06-26

Index

Installation
Usage
Licensing
Programming issues

Installation

The figure below illustrates the building process of the PHPLint executable program. The original source of PHPLint is written using the M2 programming language, which is a simple and yet effective language similar to Pascal, but with automatic memory allocation, dynamic arrays and garbage collector. Then, the M2-to-C cross-compiler translates these sources into the corresponding C source, and finally this C source can be compiled to generate the executable program for the target machine.

Then, the different distributed packages come from different stages of this building process. Those that want to partecipate into the developement of PHPLint will be interested to the M2 sources, whereas those that are interested only to use the program can download only the C source (that must be compiled using a C compiler) or can download the executable program for Windows.


Scheme of the PHPLint building process.


I have Microsoft Windows here: is there a binary version of PHPLint ready to install?

Yes, check this page: download-windows.html.


I have Linux here: is there a binary version of PHPLint ready to install?

Short response: no. Longer response: the simplest way to get PHPLint running on Linux is to download the pure-C version then compile it as indicated inside the INSTALL file included with the package.


I have the [SOME_OPERATING_SYSTEM] here, can I get PHPLint running there?

Provided that a C compiler be available on your system, the reply is "maybe", but probably there is some work to do, and you need some knowledge of the C programming. You can start trying to compile the pure-C version of PHPLint, which has been tested on several Linux distribution for the x86_32 and for the x86_64, so chances are that the same source can be made easily compatible with minor changes or no changes at all on several Unix and Unix-like systems. If this fails, you can try the longer path starting from the installation of the M2 development system, and then to generate the C source of the program from there.

Usage


I'm not interested in writing "PHPLint-compliant" programs, what I'm interested to is only to generate the documentation about my programs. Can this be made without being bored by all that PHPLint paranoia about types/clean programming/whatever?

PHPLint cannot be used as a pure "documentation generator". The tutorial provides some examples you can follow in order to satisfy the requirements of PHPLint. Only after this works has been made, the documentation so generated will be accurate and will reflect the actual behavior of the source. If your intention is only to generate the documentation from the source, better to use phpDocumentor in the meanwhile: PHPLint can parse the DocBlocks, so it can be applied afterward once the project is more mature, if you want.


PHPLint supports two documentation formats: its own Documentator format, and the phpDocumentor format. Which should I use, then? Which is the best?

phpDocumentor is certainly the most used and better known decumentation format for PHP sources. The custom Documentator format is mostly for internal use by PHPLint as it offers less features but it allows to freely inserts any HTML tag you want: in fact, phpDocumentor's DocBlocks are internally translated into the Documentator format. You may also use Documentator if you want to insert special formatting HTML code, like tables or images.


My source requires external non PHPLint-compliant sources (for example downloaded from PEAR). Can I still validate my source with PHPLint?

Unfortunately, PEAR sources cannot be validated by PHPLint, as they are not "clean" enough. Trying to fix these sources typically requires to rewrite most of the code, and often requires also to change their design. For example, PEAR classes are still mostly for PHP 4, and use variable name classes ($obj = new $class_name()) rather than to use proper interfaces or abstract classes.

Still, you can parse your PHPLint-compliant pieces of sources, with more of less success and with some drawbacks, also if they require external non-compliant sources. Basically, the trick consists in parsing the "alien" source with all the error reporting flags turned off, then re-enabling error flags and finally parsing your own source. There may be also some minor things to adjust, as you can see in the following example (Unix shell script):

M=src/phplint/modules

phplint \
	--modules-path $M \
	--php-version 4 \
	--no-report-unused \
	$M/standard \
	$M/pcre \
	$M/hash \
	--no-print-errors --no-print-warnings --no-print-notices \
	ALIEN_SOURCE.PHP \
	ALIEN_SOURCE2.PHP \
	--print-errors --print-warnings --print-notices \
	--report-unused \
	--print-context \
	--doc \
	COMPLIANT_SOURCE.PHP

Naturally, you don't have to type-in all that at the terminal prompt every time. Instead you can write some Makefile or some shell script that will do that for you. Note that:

Drawbacks:

  1. Required extension modules are erroneously reported in the generated document as "required packages" rather than proper "required modules".
  2. PHPLint stops parsing the alien code if it contains constructs it cannot understand at all. In these cases PHPLint raises a fatal error and terminates.
  3. PHPLint will grab consts/vars/funcs/classes declarations from all the alien sources, either by guessing or by parsing phpDocumentor DocBlocks. Unfortunately, these guesses may fail, some DocBlocks are missing or are incomplete or are simply wrong, and PHPLint has no way to report these inconsistencies because error reporting is turned off.
  4. Usually the overall test result (the last line) will report an unusual number of errors, mostly due to the alien code rather than to your code.
  5. Because of point 3, also if our compliant source passed the validation, still its formal validity is questionable.

If all this does not look satisfactory, there are two choices: 1. dedicate your spare time fixing the alien sources and then send them to the author; or 2. do not use non-compliant sources at all and write instead your own compliant alternative.


My source uses a PHP extension module or a PECL module which is not currently supported by PHPLint.

You should write a module similar to those that comes with the PHPLint package in the modules/ directory, and then add this stub to the same directory.


Some errors are not signaled.

PHPLint avoids to raise redundant error messages when these errors are the consequence of some other error already detected and signaled. For example, if the type of a variable cannot be determined, PHPLint raises an error, but from here on PHPLint avoids to raise other errors every time this undefined variable will be used, making the report shorter and more readable. Then, programmers should be aware that their program is "correct" only when the total number of errors and warnings detected is just zero.

Licensing


I'm the developer of the [XYZ] PHP development IDE. Can I integrate PHPLint under my program?

Yes, this is allowed by the BSD-style license under which PHPLint is distributed. You can also simply call PHPLint as an external process, since it generates error messages similar to those of most compilers that are easily parsable by programs.


Programming issues


I'm testing my beautiful PHP programs that already run quite well, but in spite of that PHPLint raises a lot of errors and warnings.

Your PHP program is probably good, the problem is PHPLint: it is not clever enough to understand some shortlands PHP programmers are used to write, and it pretends a clean, simple style. The types, for example: numbers go with numbers, strings go with strings, booleans go with booleans and so on. In a word, don't mix apples with pears, or you will get PHPLint confused. Other "strange" limitations of PHPLint are intended to make sources easy to be understand, both by programs (like PHPLint) and humans. You should definitely read first the tutorial (www.icosaedro.it/phplint/tutorial.html) and then the manual of PHPLint.


PHPLint does not pass neither the simplest examples I found in a typical, basic manual of the language. Things as simple as

1.  $fd = fopen("mydata.txt", "r") or die("error");
2.  define("MYPATH", $_SERVER['SCRIPT_NAME']);
3.  function f() {  define("X", 1);  }
4.  $fn="f";   $fn();

are rejected, although being perfectly valid PHP statements!

PHPLint imposes several restrictions to the otherwise too "liberal" features of the PHP language. These restrictions are due to the strong-typed nature of PHPLint, to the static source analysis, to the safety and securityi restrictions, and to source readability considerations. The tutorial examines several common cases and illustrates alternative solutions that are PHPLint-compliant. In the sample of code above, for example, we have in the order:
1. die() is a statement, not a function, and cannot be used inside an expression because it does not generate values.
2. Constants must be really constant under PHPLint, that is their value must be statically determinable. Instead, $_SERVER[] can be evaluated only at runtime and then it is not statically evaluable.
3. Constants should never be defined inside functions because the existance of these constants at runtime is not garanteed. In fact in PHP constants always have global scope also if defined inside a function; but the "X" constant will exists only if the function f() gets called, then PHPLint cannot garantee that function will be actually called before the constant be used. Moreover, calling that function twice would produce a PHP error because constants cannot be re-defined. That's why PHPLint imposes this restriction.
4. "Variable functions", that is functions whose name is calculated at runtime and made available in a variable, are not allowed in PHPLint. Period.


What about recursive functions/ classes/ methods?

See the chapter Recursive declarations of the reference manual, where the prototypes are explained.


My source is organized defining every single class in its own file, for example class A in A.php and class B in B.php. How to handle the case of classes recursively defined? for example the class A needs B and B needs A.

The chapter Recursive declarations of the reference manual explains how such a probleam can be resolved in a clear, effective way using a feature of PHPLint named class prototypes.


I'm overriding a method inherited from another class, but PHPLint complains my code is throwing more exceptions than the original method, and this is forbidden by the strict exception handling of PHPLint. Unfortunately my new implementation of the old method really needs to throw new exceptions. How can this be made?

According to the strict inheritance model of PHPLint, checked exceptions are part of the signature of a method, just like the return type and its arguments. So, overriding methods MUST comply with the interface the original method exhibits. The Exceptions chapter of the reference manual suggests several possible design solutions to the problem.


Umberto Salsi

Contact
Site map
Home / Section index