PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

php_strip_whitespace> <pack
Last updated: Fri, 10 Oct 2008

view this page in

php_check_syntax

(PHP 5 <= 5.0.4)

php_check_syntax 指定したファイルの文法チェック(と実行)を行う

説明

bool php_check_syntax ( string $filename [, string &$error_message ] )

指定したファイル filename に対して文法チェック (lint) を行い、スクリプトにエラーがないかどうかを調べます。

これは コマンドライン から php -l を利用するのと似ていますが、 php_check_syntax() は実際に filename を実行します (結果は出力しません)。

たとえば、もし filename の中で関数が 定義されていた場合に php_check_syntax() はそれを実行しますが、filename の 結果は表示されません。

注意: 技術的な理由により、この関数は廃止され、PHP から削除されました。 かわりに、コマンドライン から php -l somefile.php を利用してください。

パラメータ

filename

調べるファイルの名前。

error_message

error_message パラメータが指定された場合、 文法チェックの際に生成されたエラーメッセージがここに格納されます。 error_message参照で渡されます。

返り値

文法チェックが成功した場合に TRUE 、チェックが失敗したり file_name がオープンできなかった場合に FALSE を返します。

変更履歴

バージョン 説明
5.0.5 この関数は PHP から削除されました。
5.0.3 php_check_syntax() の後に exit() をコールするとセグメンテーションフォールトが発生します。
5.0.1 error_message が参照渡しになりました。

php -l somefile.php

上の例の出力は、たとえば 以下のようになります。

PHP Parse error: unexpected T_STRING in /tmp/somefile.php on line 81

参考



php_strip_whitespace> <pack
Last updated: Fri, 10 Oct 2008
 
add a note add a note User Contributed Notes
php_check_syntax
Daniel Tome
25-Jul-2008 05:37
Hi,

All functions that I have tested still fail to report this as an error:
Even the exec('php -l filename.php')

<?php

DELIBERTE PHP ERROR
;

?>

That will return as correct syntax but when you run it you get:
Parse error: syntax error, unexpected T_STRING in filename.php on line 2
kevin at metalaxe dot com
27-Apr-2008 07:01
Sorry, I'm retarded. I did a little more testing and found big issues. I've fixed them in the following code. This example is now dependant on http://us3.php.net/manual/en/function.token-get-all.php#80335 for a bugfix workaround with token_get_all(); So be sure to include that function in your script when you run this function.

<?php
/**
*    Check Eval
*    Performs a Syntax check without killing the parser (hopefully)
*
*    @params        string        PHP to be evaluated
*    @return        array        Parse error info or true for success
**/
function checkEval( $php )
{
   
$evalStr = 'return;';

   
# Get the string tokens
   
$crack = token_get_all( "<?php\n".$php );
   
   
# Drop our manually entered opening tag
   
array_shift( $crack );
   
token_fix( $crack );
   
   
# Check to see how we need to proceed
    # prepare the string for parsing
   
if( isset( $crack[0][0] ) &&
        (
           
$crack[0][0] === T_CONSTANT_ENCAPSED_STRING ||
           
$crack[0][0] === T_STRING ||
           
$crack[0][0] === T_OPEN_TAG
       
)
    ){
       
$evalStr .= '?>';
    }

   
# Make sure syntax reporting is on...probably only need E_PARSE...but I'm anal
   
$oldErr = error_reporting( E_ALL | E_STRICT );

   
# Prevent output
   
ob_start();
    eval(
$evalStr.$php );
   
$evaluput = ob_get_clean();

   
# Reset error reporting
   
error_reporting( $oldErr );

   
# Only do this if there was output
   
if( $evaluput !== '' )
    {
       
# Strip annoying html tags, in case html reporting is enabled in php.ini
       
$evaluput = strip_tags( $evaluput );

       
# Fancy Regex to pull the error that killed us
       
$pattern    = '/Parse error:\s*syntax error,(.+?)\s+in\s+.+?\s*line\s+(\d+)/';
       
$parse_fail    = (bool)preg_match( $pattern, $evaluput, $match );

       
# Parse error to report?
       
if( $parse_fail === true )
        {
            return array(
               
'line'    =>    (int)$match[2],
               
'msg'    =>    $match[1]
            );
        }
    }
    return
true;
}
?>
alx at inbox dot lv
25-Apr-2008 08:20
2: kevin at metalaxe dot com
Hm.. i think your function didnt work...

try this:
$php = 'asfvsd <? echo \'\'aaa\'; ?> asvsdgb';
checkEval( $php );
it returns actual error... from eval(); and not expected array..

but i liked the idea about return after function.. and pattern of error, thanx :) I will complete my function
kevin at metalaxe dot com
23-Apr-2008 04:43
alx at inbox dot lv says: "Nope guys.. to check the valid php you must do the followed..."
Actually that will fail when anything fatal occurs because the code will actually be executed! :)

nicolas dot grekas+php at gmail dot com says: "I can't find a way to break the dead code sandbox. Who can ?"
Why all the complications just to protect braces? Further, unbalanced braces is something we want to syntaxually check isn't it? Let's make this useful :)

Here's what I've discovered to use without any issues over the years. From nicolas and alx's examples I remodeled it a little bit to hopefully catch any case now. By all means tell me if it is broken in some way :) Remember though that it is ONLY a syntax check!

P.S. I couldn't seem to get this to work properly in CLI interactive even with the function below as separate file include. It appears that the CLI always outputs and that OB doesn't get buffred. Makes no sense...

<?php
/**
*    Check Eval
*    Performs a Syntax check without killing the parser (hopefully)
*
*    @params        string        PHP to be evaluated
*    @return        array        Parse error info or true for success
**/
function checkEval( $php )
{
   
$evalStr = 'return;';

   
# Get the string tokens
   
$crack = token_get_all( $php );

   
# Parser tokens to check for
    # we are only checking the first token because anything else
    # would result in an expected syntax error
   
$tokens = array( T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO );

   
# Check to see how we need to proceed
    # prepare the string for parsing
   
if( isset( $crack[0] ) && in_array( $crack[0][0], $tokens, true ) )
       
$evalStr .= '?>';

   
# Make sure syntax reporting is on...probably only need E_PARSE...but I'm anal
   
$oldErr = error_reporting( E_ALL | E_STRICT );

   
# Prevent output
   
ob_start();
   
$test = eval( $evalStr.$php );
   
$evaluput = ob_get_clean();

   
# Reset error reporting
   
error_reporting( $oldErr );

   
# Only do this if there was output
   
if( $evaluput !== '' )
    {
       
# Strip annoying html tags, in case html reporting is enabled in php.ini
       
$evaluput = strip_tags( $evaluput );

       
# Fancy Regex to pull the error that killed us
       
$pattern    = '/Parse error:\s*syntax error,(.+?)\s+in\s+.+?\s*line\s+(\d+)/';
       
$parse_fail    = (bool)preg_match( $pattern, $evaluput, $match );

       
# Parse error to report?
       
if( $parse_fail === true )
        {
            return array(
               
'line'    =>    (int)$match[2],
               
'msg'    =>    $match[1]
            );
        }
    }
    return
true;
}
?>
alx at inbox dot lv
11-Apr-2008 05:38
Nope guys.. to check the valid php you must do the followed:

<?
function checkPHP($source) {
ob_start();
$sowhat = @eval('?>'.$source);
$GLOBALS['sowhat'] = ob_get_contents();
ob_end_clean();
return
$sowhat === NULL ? true : false;
}

$source = '
bla bla <?=$foo?> some stuff <?
foreach ($somethins as $somethig) {
 // whatever
}'
;

if (
checkPHP($source)) {
echo
'PHP code is correct';
} else {
echo
'there are errors in your php: '.$GLOBALS['sowhat'];
}
matt dot nospam at pryor dot org dot uk
05-Feb-2008 10:35
While developing an app where I have to include PHP files written by a user, I came across the following problem:

I used "php -l somefile.php" to check the syntax of the file I was about to include and if it passed, I would include it - so far so good. But in some test cases, the file I was including would have other includes/requires inside it. If one of these was invalid, then I would still get the parse error that I was trying to avoid.

I got round it using this:

<?php
   
function CheckSyntax($fileName, $checkIncludes = true)
    {
       
// If it is not a file or we can't read it throw an exception
       
if(!is_file($fileName) || !is_readable($fileName))
           
throw new Exception("Cannot read file ".$fileName);
       
       
// Sort out the formatting of the filename
       
$fileName = realpath($fileName);
       
       
// Get the shell output from the syntax check command
       
$output = shell_exec('php -l "'.$fileName.'"');
       
       
// Try to find the parse error text and chop it off
       
$syntaxError = preg_replace("/Errors parsing.*$/", "", $output, -1, $count);
       
       
// If the error text above was matched, throw an exception containing the syntax error
       
if($count > 0)
           
throw new Exception(trim($syntaxError));
       
       
// If we are going to check the files includes
       
if($checkIncludes)
        {
            foreach(
GetIncludes($fileName) as $include)
            {
               
// Check the syntax for each include
               
CheckSyntax($include);
            }
        }
    }
   
    function
GetIncludes($fileName)
    {
       
// NOTE that any file coming into this function has already passed the syntax check, so
        // we can assume things like proper line terminations
           
       
$includes = array();
       
// Get the directory name of the file so we can prepend it to relative paths
       
$dir = dirname($fileName);
       
       
// Split the contents of $fileName about requires and includes
        // We need to slice off the first element since that is the text up to the first include/require
       
$requireSplit = array_slice(preg_split('/require|include/i', file_get_contents($fileName)), 1);
       
       
// For each match
       
foreach($requireSplit as $string)
        {
           
// Substring up to the end of the first line, i.e. the line that the require is on
           
$string = substr($string, 0, strpos($string, ";"));
           
           
// If the line contains a reference to a variable, then we cannot analyse it
            // so skip this iteration
           
if(strpos($string, "$") !== false)
                continue;
           
           
// Split the string about single and double quotes
           
$quoteSplit = preg_split('/[\'"]/', $string);
           
           
// The value of the include is the second element of the array
            // Putting this in an if statement enforces the presence of '' or "" somewhere in the include
            // includes with any kind of run-time variable in have been excluded earlier
            // this just leaves includes with constants in, which we can't do much about
           
if($include = $quoteSplit[1])
            {
               
// If the path is not absolute, add the dir and separator
                // Then call realpath to chop out extra separators
               
if(strpos($include, ':') === FALSE)
                   
$include = realpath($dir.DIRECTORY_SEPARATOR.$include);
           
               
array_push($includes, $include);
            }
        }
       
        return
$includes;
    }
?>

This checks as many of the includes inside the file as it possibly can without executing anything.
nicolas dot grekas+php at gmail dot com
26-Jan-2008 03:16
My previous code was buggy sorry, here is an update (thanks phprockstheworld). I can't find a way to break the dead code sandbox. Who can ?

<?php

function eval_syntax($code)
{
   
$braces = 0;
   
$inString = 0;

   
// We need to know if braces are correctly balanced.
    // This is not trivial due to variable interpolation
    // which occurs in heredoc, backticked and double quoted strings
   
foreach (token_get_all('<?php ' . $code) as $token)
    {
        if (
is_array($token))
        {
            switch (
$token[0])
            {
            case
T_CURLY_OPEN:
            case
T_DOLLAR_OPEN_CURLY_BRACES:
            case
T_START_HEREDOC: ++$inString; break;
            case
T_END_HEREDOC:   --$inString; break;
            }
        }
        else if (
$inString & 1)
        {
            switch (
$token)
            {
            case
'`':
            case
'"': --$inString; break;
            }
        }
        else
        {
            switch (
$token)
            {
            case
'`':
            case
'"': ++$inString; break;

            case
'{': ++$braces; break;
            case
'}':
                if (
$inString) --$inString;
                else
                {
                    --
$braces;
                    if (
$braces < 0) return false;
                }

                break;
            }
        }
    }

    if (
$braces) return false; // Unbalanced braces would break the eval below
   
else
    {
       
ob_start(); // Catch potential parse error messages
       
$code = eval('if(0){' . $code . '}'); // Put $code in a dead code sandbox to prevent its execution
       
ob_end_clean();

        return
false !== $code;
    }
}
oyejorge at googlesemail dot com
12-Jan-2008 04:51
Nicolas' code is great! Just another check to make sure a } doesn't come before { and it's much more secure. Still wouldn't trust just anyones code with it though.

<?php
   
function eval_syntax($code){
       
$b = 0;
       
        foreach (
token_get_all($code) as $token){
            if(
'{' == $token){
                ++
$b;
            }elseif(
'}' == $token){
                --
$b;
                if(
$b < 0 ){
                    return
false; // } came before {
               
}
            }
        }
       
       
// Unbalanced braces would break the eval below
       
if( $b !== 0){
            return
false;
        }
       
// Catch potential parse error messages
       
ob_start();
       
$code = eval('if(0){' . $code . '}'); // Put $code in a dead code sandbox to prevent its execution
       
ob_end_clean();
       
        return
false !== $code;
    }
phprockstheworld at gmail dot com
21-Dec-2007 10:57
The code posted by nicolas dot grekas is very clever but don't use it on anything other than code you know is safe because if the code was "} delete_everything(); {" it could do anything it likes.

Just wanted to warn anyone incase they were going to put it on their website to check PHP.
nicolas dot grekas+php at gmail dot com
24-Aug-2007 08:23
This detects parse errors without executing the code:

<?php

function eval_syntax($code)
{
   
$b = 0;

    foreach (
token_get_all($code) as $token)
    {
             if (
'{' == $token) ++$b;
        else if (
'}' == $token) --$b;
    }

    if (
$b) return false; // Unbalanced braces would break the eval below
   
else
    {
       
ob_start(); // Catch potential parse error messages
       
$code = eval('if(0){' . $code . '}'); // Put $code in a dead code sandbox to prevent its execution
       
ob_end_clean();

        return
false !== $code;
    }
}

?>
Quis at IVEGOTspamENOUGHomicidio dot nl
25-Mar-2007 08:42
<?PHP
// Think about shell-command escaping if you`re using user-input
function php_check_syntax($file,&$error) {
 
exec("php -l $file",$error,$code);
  if(
$code==0)
    return
true;
  return
false;
}
?>

Note: This is UNIX
Note: If your environment-variable PATH is not set correctly, you will need to insert the path to php (like /usr/local/bin/php)
phpdoc at michaeldouma dot com
16-Feb-2005 01:38
PROBLEM: Your page is blank, or you can not define any functions in an include.

As mentioned below, the php_check_syntax function will include your file. So you may not be able to include it again. If you have an include later in your code, and you define any functions, you will get an error, or in some cases a blank page.

php_strip_whitespace> <pack
Last updated: Fri, 10 Oct 2008
 
 
show source | credits | sitemap | contact | advertising | mirror sites