Get actual PHP runtime programmatically - php

I have a script which would need to understand whether it runs under HHVM or the standard Zend engine.
Using zend_version() outputs different version tags - 2.5 for PHP5 and 2.4.99 for HHVM master as of current, and I don't feel safe using this method at all due to potential overlaps.
Using phpversion() just gives me the supported PHP version, again I don't see this as safe due to potential overlaps.
What would be the best way to safely determine exactly which runtime the script is executing on?

I might suggest testing for the actual behavior itself, not what platform you're using. Even if you can determine whether you're running PHP or HHVM, you'll end up needing to know the precise version once either PHP or HHVM fixes / changes this behavior. You can use e.g. the code in this GitHub comment and compare its output to test which type of behavior your platform exhibits.
This is the code which can distinguish the behaviors:
<?php
function start_elem($parser,$name,$attribs) {
echo "<$name>";
}
function end_elem($parser,$name)
{
echo "</$name>";
}
$parser=xml_parser_create();
xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
xml_set_element_handler($parser,"start_elem","end_elem");
$buf = '<F>';
echo xml_parse($parser,$buf,strlen($buf)==0);
Alternatively, you could also just use the answer to this question, which indicates that HHVM defines HHVM_VERSION whereas PHP (obviously) does not, so you can use that to determine the runtime.

Related

Does PHP have a built-in means of determining the oldest PHP version compatible with a given PHP script? Or will it ever?

I wish to be able to do something like:
php --determine-oldest-supported-php-version test.php
And get this output:
7.2
That is, the php binary checks test.php for all function calls or syntax used, and then spits out the oldest version of PHP which would be able to run the script.
The purpose would be for me to create a script which goes through all the .php files in my library/framework and figures out which version of PHP I should consider to be the "oldest supported version".
Currently, I'm doing this manually. Whenever I knowingly use a new feature, function or syntax, I bump up a variable to "7.4" or whatever, and then compare the currently used PHP version against that on runtime. This is not ideal, as you can imagine, and I could very well forget to bump up this value or bump it up too much, or too little, etc.
It would be much nicer to be able to determine this automatically, with such a feature in PHP itself.
I have of course looked through the list of options and PHP has no such feature as far as I can tell. Since I basically answered my own question right away, are there any plans on such a feature in the future?
The only guarantee given is that PHP will remain compatible within the same major version.
You may be interested in looking at the article
Why You Should Be Using Supported PHP Versions.
The tool you are looking for is the GitHub project
PHP_CodeSniffer,
further described in the article
PHPCompatibility update.
You may run it using a command such as:
phpcs --standard=PHPCompatibility --runtime-set testVersion 5.4 <path-of-your-php-files>

Parsing php code conditionally to avoid parse errors on older php versions

I have scripts that must be run with PHP 5.1.0 or higher (because using PDO class, for instance).
If not, they bring parse errors.
I'm talking of scripts that anonymous visitors are invited to download, install on their server (on which I can't have any information) and run to demonstrate how easy php scripts can communicate with a system of ours.
Of course, running any of these scripts and getting a "parse error at line xxx" won't really give a good image of the solution...
I tried echoing a neat "you need PHP 5.1.0 or higher to run this script" error message, using if (version_compare(PHP_VERSION, '5.1.0') < 0) { die(...); } but, of course, this doesn't work, as PHP first parses the whole script before starting executing it and having a chance to die on this test.
So my question is:
Is there a way in PHP to do some tests on php version BEFORE actually parsing?
I mean something like C/C++ #if or #ifdef PRE-processor directives.
Or any other type of workaround?
One constraint beeing: the solution to the issue should not make the whole scripts look unreadable or complex to understand (like massive calling of eval() which breaks syntax coloration) nor uncomprehensibly contrived (like having each script conditionaly included in a "container script"), because the global purpose is to demonstrate how SIMPLE it is to communicate with our system...
All solutions found googling around were about maintaining compatibility, using arrays of alternative functions to call depending on php version, comined with eval everywhere where something could go wrong for php parser... I would need something really simpler like "if php version not ok, don't parse"...

PHP: svn_update and shell_exec("svn up ".DIR)

Whats the difference between a svn_update and doing a echo shell_exec("svn up ".DIR);
My guess is the big block of text that says:
This function is EXPERIMENTAL. The behaviour of this function, its name, and surrounding documentation may change without notice in a future release of PHP. This function should be used at your own risk.
I would expect the 2 operations to be the same as the svn php module tries to be a "native" svn client.
There could be differences in the versions of the 2 clients (php client versus command line client).
You may want to check if the svn user used for both commands is the same. In the php client you must use svn_auth_set_parameter to setup the credentials of the svn user
I hope this will help you,
Jerome Wagner

Is the exit status in PHP only useful when running from the command line?

I was just reading the docs for PHP's exit construct.
It says you can pass an integer (0-254) which will become the exit code...
exit(5);
Is this only useful when running from PHP under CLI? Can Apache use the error code for anything? Will PHP running normally always use exit code 0?
Thanks
While hardly an authoritative answer, I'm not aware of any purpose that it (passing an integer to exit) serves outside the CLI environment. Web servers traditionally just report the HTTP status code, and there's not any reason for them to look elsewhere for status codes.
You could take a look at PHP's source in the sapi directory. For example, in php_cli.c, you'll see exit(exit_status); near the end of the file. I assume the generic cgi interface uses it too. I doubt any of the web server interfaces use it.

PHP: Code checker since PHP is a loose type / dynamic language?

I have a small PHP web-based application that is beginning to grow moderately in size.
I'm starting to become concerned with managing my PHP code base, given PHP is a loosely/weak typed, dynamic language.
How do others manage their code based for loosely/weak typed, dynamic languages?
Do pre-parsers exist for PHP that allow me to runs checks on my code base to identity such things like below?
$var1 = 'data';
// vr1 doesn't exist, it's a typo of $var1, but PHP would allow for this and not complain
echo $vr1;
UPDATE:
The example above might not be the best example but essentially, what I'm trying to convey is that certain errors in a dynamically weak typed language would only be found when the code is run in production at RUN TIME; whereas, some of these issues would typically be found in strongly typed static languages at COMPILE time.
How can I also find these non-algorithm type of errors in PHP prior to moving my code into production without having to create an insane number of Unit Tests?
As such, does anything exist where I can run my PHP code through it, prior to moving into production, and this pre-processor parses my code to ensure I'm only using defined variables, etc. Essentially, check my code for validation for non-algorithmic type of uses. E.g. not trying perform algebra on a string, etc.
UPDATE 2
Please note, this question is still not answered because I'm looking for a way to identity these type of non-algorithmic errors in PHP at "compile" type, not RUN TIME.
You can lint your PHP with php -l filename.php. This would show any syntax errors.
There is IDEs out there that will lint while you write the code. Those usually can also detect issues like shown in your question in addition to linting.
Apart from this, consider writing UnitTests for your code to ensure functionality and have a look at http://phpqatools.org for a number of other tools that can assist you in increasing code quality.
Make sure you have error_reporting(-1); set during development to enable all errors, in addition to enable display_errors and display_startup_errors in php.ini. Disable the latter two on your production system to prevent exposure of server information.
Edit after update: PHP source code is compiled on-the-fly. PHP's compile time is effectively at run time. If you want compiled PHP, you have to use Facebook's HipHop.
PHP will definitely complain about that with either a warning or a notice if you set your error_reporting config directive appropriately.
See:
http://us2.php.net/manual/en/errorfunc.configuration.php#ini.error-reporting
Runtime Errors
Uninitialized variables are runtime errors (of level E_NOTICE) in PHP, so you can only see them at runtime. The example you gave may or may not end up erroring, depending on how the code is executed. For instance, it could be that $vr1 is defined in a conditional include() that is sometimes included and sometimes not.
Additionally, it's possible to dynamically create variables at runtime using variable variables ($$var), so again that $vr1 may actually be defined somewhere. If the PHP interpreter failed to run valid syntax, or gave compiler errors on valid syntax, that would be a different sort of problem.
You might compare the uninitialized variable circumstance to a divide by zero error. It's not an error unless it actually happens.
Compiletime errors are E_PARSE, E_COMPILE_ERROR, or E_COMPILE_WARNING (not fatal) in PHP. These include things like missing files, functions, or classes, i.e. trying to execute code that isn't there—something PHP can't possibly do. If PHP may be able to, it will try.
Detection and Prevention
At the very least, you should make sure that your development and testing environments have all of the PHP error junk turned on in the ini:
error_reporting = E_ALL|E_STRICT
display_errors = On
Or at runtime:
error_reporting(-1);
Self Discipline
A few tips for working with PHP that might help:
Use functional programming
Establish code smells and write clean syntax
Do your own type checking (OOP and functional programming can make this easier)
Avoid the global scope and include()-based control structures
Use an IDE with code awareness aids, like Netbeans.
For instance, in your example above, if you have to pass your variable into a function or method that checks that the parameter isset() or !== nullbefore using it, you can avoid or mitigate the problem of uninitialized variables.
Resources
Comparison operators (see Identity, specifically)
Type comparison tables
is_int(), is_float(), etc.
That type of error would be caught if you set error reporting to the max. It would give a Notice indicating that $vr1 wasn't set.
You can set error reporting in your php.ini file, or on individual pages using the ini_set() function.
The closest thing is php's lint checker, but that's more of a syntax checker. You can run lint from a command line:
php -l path/to/file.php
You could build this into your file repository system by setting up a pre-commit check.
As PHP is not usually considered to go through a separate COMPILE process perhaps you could explain at what point you consider your code to be COMPILED?
Here's another SO question that focuses on PHP code analysis tools.
Hack is a statically typed language created by Facebook which is essentially PHP with many features added and removed.
PhpStorm is an IDE which provides "inspections" which catch many things that would be caught by a static type checker, such as the undefined variable in your example.
I started writing a static type checker for PHP here based on PHP7 type hints and PHPDoc annotations. I never finished it but there are some passing tests and the design so far seems to be sound.

Categories