admin 管理员组

文章数量: 887021

php check syntax,php

php_check_syntax()

(PHP 5 < 5.0.5)

检查PHP的语法(并执行)指定的文件

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

对指定的$filename进行语法检查,检测脚本的错误。

此函数除了会执行(但不会输出)$filename,其他与命令行中使用php -l相似。

例如,如果函数在文件$filename中被定义了,则该函数在执行php_check_syntax()后可用。但是$filename输出内容不会被输出。Note:

因为某些技术原因,该函数已被弃用,并且从PHP中移除了。请以commandline使用php -l somefile.php取而代之。

参数$filename需要被检测的文件。$error_message如果使用了参数$error_message,它会包含语法检测出的错误信息。$error_message以引用方式传递。

返回值

如果语法检测通过返回TRUE,未通过或者文件无法打开则返回FALSE。

更新日志版本说明5.0.5函数从PHP中移除。

5.0.3php_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

参见include- includeI've given it some thought and rewritten my function to take full advantage of the CLI -l option (that's lower L). It requires that you enable error reporting via your own php.ini file (which you should edit the function to apply) otherwise the return result is a worthless "Error parsing".

Anyway, I hope this is useful for someone. I'm sure it could use improvement, so use at your own risk. Demo here:

.php

/**

* Check Syntax

* Performs a Syntax check within a php script, without killing the parser (hopefully)

* Do not use this with PHP 5 <= PHP 5.0.4, or rename this function.

*

* @params string PHP to be evaluated

* @return array Parse error info or true for success

**/

function php_check_syntax( $php, $isFile=false )

{

# Get the string tokens

$tokens = token_get_all( '<?php '.trim( $php ));

# Drop our manually entered opening tag

array_shift( $tokens );

token_fix( $tokens );

# Check to see how we need to proceed

# prepare the string for parsing

if( isset( $tokens[0][0] ) && $tokens[0][0] === T_OPEN_TAG )

$evalStr = $php;

else

$evalStr = "<?php \n{$php}?>";

if( $isFile OR ( $tf = tempnam( NULL, 'parse-') AND file_put_contents( $tf, $php ) !== FALSE ) AND $tf = $php )

{

# Prevent output

ob_start();

system( 'C:\inetpub\PHP\5.2.6\php -c "'.dirname(__FILE__).'/php.ini" -l < '.$php, $ret );

$output = ob_get_clean();

if( $ret !== 0 )

{

# Parse error to report?

if( (bool)preg_match( '/Parse error:\s*syntax error,(.+?)\s+in\s+.+?\s*line\s+(\d+)/', $output, $match ) )

{

return array(

'line'=> (int)$match[2],

'msg'=> $match[1]

);

}

}

return true;

}

return false;

}

//fixes related bugs: 29761, 34782 => token_get_all returns <?php NOT as T_OPEN_TAG

function token_fix( &$tokens ) {

if (!is_array($tokens) || (count($tokens)<2)) {

return;

}

//return of no fixing needed

if (is_array($tokens[0]) && (($tokens[0][0]==T_OPEN_TAG) || ($tokens[0][0]==T_OPEN_TAG_WITH_ECHO)) ) {

return;

}

//continue

$p1 = (is_array($tokens[0])?$tokens[0][1]:$tokens[0]);

$p2 = (is_array($tokens[1])?$tokens[1][1]:$tokens[1]);

$p3 = '';

if (($p1.$p2 == '') || ($p1.$p2 == '

$type = ($p2=='?')?T_OPEN_TAG:T_OPEN_TAG_WITH_ECHO;

$del = 2;

//update token type for 3rd part?

if (count($tokens)>2) {

$p3 = is_array($tokens[2])?$tokens[2][1]:$tokens[2];

$del = (($p3=='php') || ($p3=='='))?3:2;

$type = ($p3=='=')?T_OPEN_TAG_WITH_ECHO:$type;

}

//rebuild erroneous token

$temp = array($type, $p1.$p2.$p3);

if (version_compare(phpversion(), '5.2.2', '

$temp[] = isset($tokens[0][2])?$tokens[0][2]:'unknown';

//rebuild

$tokens[1] = '';

if ($del==3) $tokens[2]='';

$tokens[0] = $temp;

}

return;

}

?>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:

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.

本文标签: php check syntax php