-1

I have a server but it only has PHP 5 on it at the moment I have a broken arm so moving (just typing this) is a killer.

I thought all the class_exists and function_exists functions built into PHP would at least be backward compatible however as PHP seems to just remove functionality unlike other languages without handling it nicely I am running into problems with the removal of the \e modifier in regular expressions.

For example I had this regular expression to decapitalise words after full stops if they are single words e.g "Hello Rob Reid. Said the bar man" would be "Hello Rob Reid. said the bar man" - do not worry about grammar the dots are used later as placeholders.

So this was working in PHP 5

$content = preg_replace("/(\.[”’\"]?\s*[A-Z][a-z]+\s[a-z])/e","strtolower('$1')",$content);

But in PHP 7 it doesn't and \e modifier has been removed.

So in PHP 7 I have to do this.

$content = preg_replace_callback("@(\.[”’\"]?\s*[A-Z][a-z]+\s[a-z])@",
                        function ($matches) {
                        return strtolower($matches[0]); 
                        },
                        $content);

However I need code that will work whether the user has PHP5 or PHP7 and I cannot force them to upgrade I just need to determine which branch to use without the parser throwing errors.

I thought a simple error_reporting(0); and function_exists("preg_replace_callback"); would work but it doesn't seem to.

I have tried online PHP testers like this one that evaluates the code.

However I get parse errors, even if I put error_reporting(0); at the top of the script.

I thought a function to see if a function exists and is callable would work like the one below but to no avail.

I thought a combo of function_exists and is_callable would work.

function is_function($name)
{
    $ret = true;

if(function_exists($name) && is_callable($name)){
    return $ret;
}else{
    $ret = false;
}

echo "return " . intval($ret) . " from is_function\n";
return $ret;
}`

So how can I branch the code in the main function depending on what functions (or PHP version) is supported?

You can copy this whole bit of code into the sandbox tester and run it...

<?php
error_reporting(0);
echo "start\n";
$content = "Hello Rob Reid said the bar man. He walked away.\n\n";

echo $content;

if(is_function("preg_replace_callback")){
    echo "function does exist\n";
    @$content = preg_replace_callback("@(\.[”’\"]?\s*[A-Z][a-z]+\s[a-z])@",
                        function ($matches) {
                        return strtolower($matches[0]);
                        },
                        $content);
}else{
    echo "function does not exist\n";
    $content = preg_replace("/(\.[”’\"]?\s*[A-Z][a-z]+\s[a-z])/e","strtolower('$1')",$content);
}

function is_function($name)
{
    $ret = true;

    if(function_exists($name) && is_callable($name)){
        return $ret;
    }else{
       $ret = false;
    }

    echo "return " . intval($ret) . " from is_function\n";
    return $ret;
}


echo "new content\n\n";
echo $content . "\n\n";
echo "stopped";

and watch the output change as it hits PHP 5.217 then you get errors e.g


Parse error: syntax error, unexpected T_FUNCTION in [...][...] on line 11

So any ideas how to branch versions of PHP in the same class file seeing they couldn't keep the /e modifier or handle the new callbacks>

Much thanks for any help.

MonkeyMagix
  • 677
  • 2
  • 10
  • 30
  • Get rid of the anonymous function and it will work. https://3v4l.org/MNDak – chris85 Jun 25 '17 at 21:12
  • but i need the anon function for it to work in PHP7 I need it to work in both in PHP5 and PHP7 or whatever version of the language. I know people with PHP7 replace the old code with the new anon callback code to get it to work however people with PHP5 still need it to work so it has it work with both sets of code. It should work with an is_function function to test if it will run but for some reason it doesn't unless I need to put in that variable something else e.g is_function("callback"); – MonkeyMagix Jun 25 '17 at 21:44
  • PHP7 doesn't require the anonymous function. That page is testing PHP 7.2 - 4.3. – chris85 Jun 25 '17 at 21:46

1 Answers1

0

You have two options:

  1. Create a normal function and pass it to preg_replace_callback.
  2. Use create_function to create an anonymous function:
$content = preg_replace_callback("@(\.[”’\"]?\s*[A-Z][a-z]+\s[a-z])@",
                        create_function('$matches', 'return strtolower($matches[0]);'),
                        "Hello Rob Reid. Said the bar man");

Live demo

However by the latter you'll risk using a deprecated function as of PHP 7.2 comes.

revo
  • 47,783
  • 14
  • 74
  • 117
  • Just creating a function should work in every version. I would stay away from `create_function`. Additional note from the manual about that function `This function internally performs an eval() and as such has the same security issues as eval(). Additionally it has bad performance and memory usage characteristics.` – chris85 Jun 25 '17 at 22:38
  • It brings vulnerabilities on rare cases not within a strict data verification but if you care you'll see I'm warning OP about not going with it too. It's an option however. – revo Jun 25 '17 at 22:50
  • Yes, I see deprecation warning, I think a note about security and performance issues would also be good though.. or a link (http://php.net/manual/en/function.create-function.php) and a note to note the notes there. – chris85 Jun 25 '17 at 23:00
  • Ok generic question. In JavaScript you test for the function existance first before using it. In the old days to add events you might have a function that tests both IE and MOZ e.g you would always handle the differences by branching and testing that the function exists before using e.g if document.addEventListener { .... } else if document.addEvent { ... } else { ... } before using it knowing that if the function exists it won't use it. How can you future proof PHP code so you are not constantly changing it when major versions come out where functions have been added or removed. – MonkeyMagix Jun 26 '17 at 23:53