Including conditional syntax in PHP based on PHP version - php

I am writing a function in PHP, and in this function, I'm trying to set this up so that I can have the script call the function one way if the server is using PHP 5.6, and another way if it is on an older version. However, when I attempt this on a lower version of PHP, it results in a syntax error. I was wondering if there was any way to force PHP to ignore the new syntax entirely rather than throwing an error if it is using an older version so that I can use this script between versions. Here is the code that I am trying to do this with:
if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
// This function requires PHP 5.6+
$stmt->bind_param($type, ...$args);
} else {
// For older versions (slower)
call_user_func_array([$stmt, 'bind_param'], array_merge(array($type), $args));
}

Syntax parsing runs on a different level than runtime parsing. PHP will detect the syntax error before the script even gets to run and your if be evaluated.
A possible solution would be as Ja͢ck suggests, use two script files and conditionally include one based on the version.

Related

foreach on null throws error since migration to Symfony 3

I migrated my web application from Symfony 2 to 3. Since then whenever a foreach loop is executed on null, an error is thrown ("Invalid argument").
Example:
$myResults = null;
foreach ($myResults as $item) {
// do something
}
How do I achieve that as before no error is thrown?
This is a bug introduced by an upgrade to a newer PHP version (7.1+).
You can verify this by executing your code sample in an interactive php shell without any Symfony code being loaded:
$ php -a
Interactive shell
php > $var = null;
php > foreach ($var as $v) {}
PHP Warning: Invalid argument supplied for foreach() in php shell code on line 1
You can also verify this on 3v4l.org
In order to fix this you have to check for null before looping or (temporarily) go back to an older (unsupported!) PHP version. Depending on how well your code is typed there are some static code analysis tools, that will help you finding the loops you will have to safeguard.

Emulating PHP Include Statement Using Code From HTTP Requests

I have a primary "driver" script written in PHP, and based on certain criteria, I'd like this script to pull code from one or more supporting servers via HTTP in order to load functions into memory as though I had done so using the PHP include statement.
Is it possible to use HTTP requests in PHP to pull data that is actually interpreted as PHP code when it is returned?
For example, suppose I used cURL or a web service to return the following text that was stored in a variable, say $URLResponse:
function userKeyGet() {
return (isset($_SESSION['user_key']) ? $_SESSION['user_key'] : '-1');
}
If I then used something such as eval($URLResponse), would that create the function for use during the current execution of the calling PHP script? I've used cURL and Buzz to return JSON or similarly structured data that I've converted into an array, but not a function or class. Is this possible? Thanks.
You can load remote PHP codes with include(),include_once(),require() and require_once() functions, It requires allow_url_include enabled in php.ini.
require_once("http://www.yourserver.com/function.php");
Included file should contain codes and not interpreted by server as executable, so if you are using php supported web server maybe you can give another extension to remote file.
eval() will work too. If you use eval/include and declare same function two times it will raise fatal error since it is already declared. You can use object or anonymous functions to override the function.
$code="function userKeyGet() {
return (isset(\$_SESSION['user_key']) ? \$_SESSION['user_key'] : '-1');
}";
eval($code);
eval($code); # Second time using eval on $code with "Fatal error: Cannot redeclare"
# This will work
echo userKeyGet();
# An example for anonymous function way
$code="\$userKeyGet = function() {
return (isset(\$_SESSION['user_key']) ? \$_SESSION['user_key'] : '-1');
};";
eval($code); # this wont raise redeclare error
echo $userKeyGet();

suppress parse errors in PHP

so I'm trying to prevent fatal errors from stopping my script from running
so I set error report to 0:
error_reporting(0);
then I added some junk code afterwards..
junk code~~~~trololololololol
However, PHP ends up returning parse error nonetheless:
Parse error: syntax error, unexpected 'require_once' (T_REQUIRE_ONCE) in etc
is there a way to prevent PHP from ceasing to execute when there are parse errors or is this a hopeless endeavor?
is there a way to prevent PHP from ceasing to execute when there are parse errors or is this a hopeless endeavor?
Yes, that's hopeless. It's impossible to resume execution after junk was found, there just isn't any predictable state left for the compiler to adhere to. It might be missing random functions, variable definitions and what not, so all it can logically do is stop working.
You can suppress the error but not force it to continue working after the digital equivalent of a violent heart attack.
You can't. PHP first reads the text in your script from beginning to end (parses it) and converts it into some form of low-level bytecode that can be executed. If it fails to parse, then there's no executable code at all and it can only fail.
With runtime errors, your code is already executing and PHP already knows if you've got some way to handle that error. But with a parse error, there's no program there to begin with.
Yes, you can handle parsing errors. Take a look at this example:
index.php
<?php
ini_set('display_errors', '0');
register_shutdown_function('err_handler');
$modules = array('module1.php', 'module2.php', 'module3.php');
load_modules($modules);
function load_modules(&$modules) {
foreach ($modules as $key => $module) {
unset($modules[$key]);
include $module;
}
}
function err_handler() {
global $modules;
load_modules($modules);
}
module1.php
<?php junk code~~~~trololololololol;
module2.php
<?php junk code~~~~trololololololol;
module3.php
<?php echo "Surprise!\n";
Wisely using the register_shutdown_function(), set_error_handler() and set_exception_handler() you can make your script absolutely immune to all type of PHP errors. This code can be treated as an example of defensive programming technique in PHP.
If there is a parse error then php can't execute the script at all, so it won't run the error_reporting(0);, and so it will fall back to whatever the setting was for error_reporting and display_errors in the php.ini file. So you CAN prevent the parsing error being shown by editing the php.ini file, but then that will switch it off globally.
If you want the display of errors to be on by default globally (not good for production!), then you might be able to switch them off locally with a .htaccess setting, since this is read before parsing the php script.

Symfony Task Unexpected Memory

I am using Symfony task php5.2. Here is a portion of my code:
array of images
foreach($array as $k=>$v)
{
abc(); // function call which will cope images from one server to another
// by using file_get_content in a php variable and using api(wso).
echo memory_get_usage();
}
problem is memory_get_usage(); always returning same value but when i am using top command memory is increasing nonstop.
Is there any bug in symfony task or php5.2 or wso.
Have you tried memory_get_usage(true)?
Also, have you considered that it might not be PHP that is using the memory? But some other library you are using?

Modx Evo with PHP 5.4 and eval

Got a bit of an issue with Modx and latest version of PHP.
It's a very old version of Modx (don't ask - I have exactly the same thoughts, wasn't in my control). The site is working fine on PHP 5.2.
The problem is the web host is upgrading to PHP 5.4 - as a result the site breaks completely. The one issue I can't get a solution for is the use of eval within manager/includes/document.parser.class.inc.php under "evalSnippet()" function where it calls depreciated eval() function.
I've looked at possibliity of upgrading Modx to latest which is 1.0.9, however this still uses eval() -> even though it explicity states this version supports PHP 5.4. Below is the code:
function evalSnippet($snippet, $params) {
$etomite= $modx= & $this;
$modx->event->params= & $params; // store params inside event object
if (is_array($params)) {
extract($params, EXTR_SKIP);
}
ob_start();
$snip= eval ($snippet);
$msg= ob_get_contents();
ob_end_clean();
if ((0<$this->config['error_reporting']) && isset($php_errormsg))
{
$error_info = error_get_last();
if($error_info['type']===2048 || $error_info['type']===8192) $error_type = 2;
else $error_type = 3;
if(1<$this->config['error_reporting'] || 2<$error_type)
{
extract($error_info);
if($msg===false) $msg = 'ob_get_contents() error';
$result = $this->messageQuit('PHP Parse Error', '', true, $type, $file, 'Snippet', $text, $line, $msg);
if ($this->isBackend())
{
$this->event->alert("An error occurred while loading. Please see the event log for more information<p>{$msg}{$snip}</p>");
}
}
}
unset ($modx->event->params);
return $msg . $snip;
}
Is there away around this? Has anyone managed to get Modx Evo working with PHP 5.4?
Continued from comments on original post...
session_is_registered() is deprecated as of PHP 5.3. You'll need to check through your snippets and find out which one is using this function, then replace it with isset($_SESSION['name_of_variable']).
Quickest way to find it would be to run a %LIKE% search in phpMyAdmin for session_is_registered on the modx_site_snippets table

Categories