2

I want to do:

$str = "<? echo 'abcd'; ?>";
if (is_valid_php($str)){
   echo "{$str} is valid";
} else {
   echo "{$str} is not valid PHP code";
}

Is there a simple way to do the is_valid_php check?

All I can find is online php syntax checkers and command-line ways to check syntax, or php_check_syntax which only works for a file, and I don't want to have to write to a file to check if the string is valid.

I'd rather not use system()/exec() or eval()

Related Question - It's old, so I'm hoping there's something new

Other Related Question - all the options (as far as I could tell) either are no longer supported or use command line or have to check files (not strings)

I don't need a full-fledged compiler or anything. I literally only need to know if the string is valid PHP code.

EDIT: By valid php code, I mean that it can be executed, has no compiler/syntax errors, and should contain only PHP code. It could have runtime errors and still be valid, like $y = 33/0;. And it should contain only PHP... Such as, <div>stuff</div><? echo "str"; ?> would be invalid, but <? echo "str"; ?> and echo "$str"; would be valid

Community
  • 1
  • 1
Reed
  • 14,703
  • 8
  • 66
  • 110
  • 1
    What about posting curl requests to those online syntax checkers? I don't know the sites, so I'm not sure if its possible, but you could observer the network requests and see if you can emulate it with cURL – Dan Nov 04 '15 at 19:50
  • Can you clarify "valid"? Does that mean free of both compile time and run time errors? Or works as expected? – HPierce Nov 04 '15 at 19:56
  • All I can find is the same as you did. I checked a REST service, but that one also takes a file. Writing (and deleting) a file is quite a trivial task - so I am curious, why don't you want to write to a file to use php_check_syntax? – Tobias Beuving Nov 04 '15 at 19:56
  • Best I could find: https://github.com/nikic/PHP-Parser – Jorge Campos Nov 04 '15 at 20:00
  • Maybe you can use [`phc`](http://www.phpcompiler.org/) to compile the code into an executable? I have never used this software but I would imagine that if the script is not valid PHP code then the build should fail. – MonkeyZeus Nov 04 '15 at 20:01
  • @dan08, That could work, but for performance reasons, I do not want to send curl requests, since I'm going to be checking 10+ separate strings in a single request (granted, that's only while my site is in development mode, so I guess it's not a big deal). – Reed Nov 05 '15 at 16:10
  • @TobiasBeuving, performance reasons and laziness. But obviously, I could wrap it in a function and write to a temporary file and make it easy to use. It's probably the route that I will go, but just checking the string would be preferred, if that were an option. – Reed Nov 05 '15 at 16:12
  • 1
    @HPierce, I updated my question to explain... The php-parser or phc seem like good options. – Reed Nov 05 '15 at 16:20
  • 1
    @Jakar I understand that checking string would be way nicer, and writing to and deleting a file and stuff is just a silly redundant job. Depending on how many times you want to check that code, writing to a file does not easily affect performance. If I were you I start doing the write to file thing right away before trying anything else, but thats me :) – Tobias Beuving Nov 05 '15 at 17:36

3 Answers3

7

You could pipe the string to php -l and call it using shell_exec:

$str1 = "<?php echo 'hello world';";
$str2 = "<?php echo 'hello world'";
echo isValidPHP($str1) ? "Valid" : "Invalid"; //Valid
echo isValidPHP($str2) ? "Valid" : "Invalid"; //Inalid

function isValidPHP($str) {
    return trim(shell_exec("echo " . escapeshellarg($str) . " | php -l")) == "No syntax errors detected in -";
}

Just had another idea... this time using eval but safely:

test_code.php

$code = "return; " . $_GET['code'];
//eval is safe here because it won't do anything
//since the first thing we do is return
//but we still get parse errors if it's not valid
//If that happens, it will crash the whole script, 
//so we need it to be in a separate request
eval($code); 
return "1";

elsewhere in your code:

echo isValidPHP("<?php echo \"It works!\";");

function isValidPHP($code) {
    $valid = file_get_contents("http://www.yoursite.com/test_code.php?" . http_build_query(['code' => $code]));
    return !!$valid;
}
dave
  • 62,300
  • 5
  • 72
  • 93
1

Off the top of my head, this is easiest.

$str = "<? echo 'abcd'; ?>";
file_put_contents("/some/temp/path", $str);
exec("php -l /some/temp/path", $output, $result);
if ($result == 0){
   echo "{$str} is valid";
} else {
   echo "{$str} is not valid PHP code";
}
unlink("/some/temp/path");

The reason I didn't use php_check_syntax is because:

  1. it's deprecated
  2. it actually executes the code
Legionar
  • 7,472
  • 2
  • 41
  • 70
miken32
  • 42,008
  • 16
  • 111
  • 154
1

Edit: Just saw that you want to rather refrain from using exec(). I think this is going to be very hard without it though, php removed the check_syntax function for a reason. Maybe ( and I really am just guessing here when it comes to the effort you want to invest ) running the php -l in a container ( docker pretty much these days ) and passing the code via a http call to the docker daemon ( just a run command against the standard php cli would do it here ). Then you could use something like below code example without worries ( provided you don't give any permissions to your container obv ).

You could use exec and the php commandline like this:

$ret = exec( 'echo "<?php echo \"bla\";" | php -l 2> /dev/null' );

echo strpos( $ret, 'Errors parsing' ) !== false ? "\nerror" : "\nno error";

$ret = exec( 'echo "<?php eccho \"bla\";" | php -l 2> /dev/null' );

echo strpos( $ret, 'Errors parsing' ) !== false ? "\nerror" : "\nno error";

which returns:

no error
error

No file needed thanks to piping the output. Also using the redirection to dev null we get no unwanted output elsewhere. Still surely a little dirty, but the shortest I can come up with.

Armin Braun
  • 3,645
  • 1
  • 17
  • 33