如何检查一个字是否被PHP保留?

disho6za  于 11个月前  发布在  PHP
关注(0)|答案(7)|浏览(60)

在PHP中是否有一些功能可以检查一个单词是否是reserved,或者我可以自己使用它?我可以手动检查:只要使用它并看到错误或警告,但我需要自动进行此检查。有什么办法可以做到这一点吗?

disbfnqx

disbfnqx1#

您可以创建自己的自动化功能。要做到这一点,请使用一个包含所有保留字的数组。Check out for more information

epfja78i

epfja78i2#

in_array()是一个糟糕的解决方案,as this iterates over every single element within the array, taking O(n) time,,而使用查找散列可以在O(1)时间内完成。
为了清楚起见,下面的解决方案使用[php.net上的四个列表:][2]

  • 关键词列表- 71个关键词
  • 预定义类- 18个关键字
  • 预定义常量- 57个关键词
  • 其他保留字列表&mdash13关键字

Full Working Demo Online

class PHPReservedWords {
        public function isWordReserved($args) {
            $word = $args['word'];
            
            if($this->GetPHPReservedWordsHash()[$word]) {
                return TRUE;
            }
            
            return FALSE;
        }
        
        public function GetPHPReservedWordsHash() {
            if($this->word_hash) {
                return $this->word_hash;
            }
            
            $hash = [];
            
            foreach($this->GetPHPReservedWords() as $word) {
                $hash[$word] = TRUE;
            }
            
            return $this->word_hash = $hash;
        }
        public function GetPHPReservedWords() {
            return [
                        # Primary Source: https://www.php.net/manual/en/reserved.php
                        # ----------------------------------------------------------
                        
                    # List 1 of 4: https://www.php.net/manual/en/reserved.keywords.php
                    # ----------------------------------------------------------------
            
                '__halt_compiler',
                'abstract',
                'and',
                'array',
                'as',
                'break',
                'callable',
                'case',
                'catch',
                'class',
                'clone',
                'const',
                'continue',
                'declare',
                'default',
                'die',
                'do',
                'echo',
                'else',
                'elseif',
                'empty',
                'enddeclare',
                'endfor',
                'endforeach',
                'endif',
                'endswitch',
                'endwhile',
                'eval',
                'exit',
                'extends',
                'final',
                'finally',
                'fn',           # (as of PHP 7.4)
                'for',
                'foreach',
                'function',
                'global',
                'goto',
                'if',
                'implements',
                'include',
                'include_once',
                'instanceof',
                'insteadof',
                'interface',
                'isset',
                'list',
                'match',        # (as of PHP 8.0)
                'namespace',
                'new',
                'or',
                'print',
                'private',
                'protected',
                'public',
                'readonly',     # (as of PHP 8.1.0)
                'require',
                'require_once',
                'return',
                'static',
                'switch',
                'throw',
                'trait',
                'try',
                'unset()',
                'use',
                'var',
                'while',
                'xor',
                'yield',
                'yield from',
                        
                    # List 2 of 4: https://www.php.net/manual/en/reserved.classes.php
                    # ---------------------------------------------------------------
                
                'Directory',
                'stdClass',
                '__PHP_Incomplete_Class',
                'Exception',
                'ErrorException',
                'php_user_filter',
                'Closure',
                'Generator',
                'ArithmeticError',
                'AssertionError',
                'DivisionByZeroError',
                'Error',
                'Throwable',
                'ParseError',
                'TypeError',
                'self',
                'static',
                'parent',
                        
                    # List 3 of 4: https://www.php.net/manual/en/reserved.constants.php
                    # ---------------------------------------------------------------
                    
                'PHP_VERSION',
                'PHP_MAJOR_VERSION',
                'PHP_MINOR_VERSION',
                'PHP_RELEASE_VERSION',
                'PHP_VERSION_ID',
                'PHP_EXTRA_VERSION',
                'PHP_ZTS',
                'PHP_DEBUG',
                'PHP_MAXPATHLEN',
                'PHP_OS',
                'PHP_OS_FAMILY',
                'PHP_SAPI',
                'PHP_EOL',
                'PHP_INT_MAX',
                'PHP_INT_MIN',
                'PHP_INT_SIZE',
                'PHP_FLOAT_DIG',
                'PHP_FLOAT_EPSILON',
                'PHP_FLOAT_MIN',
                'PHP_FLOAT_MAX',
                'DEFAULT_INCLUDE_PATH',
                'PEAR_INSTALL_DIR',
                'PEAR_EXTENSION_DIR',
                'PHP_EXTENSION_DIR',
                'PHP_PREFIX',
                'PHP_BINDIR',
                'PHP_BINARY',
                'PHP_MANDIR',
                'PHP_LIBDIR',
                'PHP_DATADIR',
                'PHP_SYSCONFDIR',
                'PHP_LOCALSTATEDIR',
                'PHP_CONFIG_FILE_PATH',
                'PHP_CONFIG_FILE_SCAN_DIR',
                'PHP_SHLIB_SUFFIX',
                'PHP_FD_SETSIZE',
                'E_ERROR',
                'E_WARNING',
                'E_PARSE',
                'E_NOTICE',
                'E_CORE_ERROR',
                'E_CORE_WARNING',
                'E_COMPILE_ERROR',
                'E_COMPILE_WARNING',
                'E_USER_ERROR',
                'E_USER_WARNING',
                'E_USER_NOTICE',
                'E_RECOVERABLE_ERROR',
                'E_DEPRECATED',
                'E_USER_DEPRECATED',
                'E_ALL',
                'E_STRICT',
                'true',
                'false',
                'null',
                'PHP_WINDOWS_EVENT_CTRL_C',
                'PHP_WINDOWS_EVENT_CTRL_BREAK',
                        
                    # List 4 of 4: https://www.php.net/manual/en/reserved.other-reserved-words.php
                    # ---------------------------------------------------------------
                    
                'int',
                'float',
                'bool',
                'string',
                'true',
                'false',
                'null',
                'void',         # (as of PHP 7.1)
                'iterable',     # (as of PHP 7.1)
                'object',       # (as of PHP 7.2)
                'resource',
                'mixed',
                'numeric',
            ];
        }
    }
    
    $reserved_words = new PHPReservedWords();
    print($reserved_words->isWordReserved(['word'=>'new']));

字符串

ep6jt1vc

ep6jt1vc3#

http://www.php.net/manual/en/reserved.keywords.php借用的阵列
您可以很容易地修改它,使其适用于预定义的常量数组。

  • 这很有效 *
<?php
$keywords = array('__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor');

$predefined_constants = array('__CLASS__', '__DIR__', '__FILE__', '__FUNCTION__', '__LINE__', '__METHOD__', '__NAMESPACE__', '__TRAIT__');

$checkWord='break'; // <- the word to check for.
if (in_array($checkWord, $keywords)) {
    echo "Found.";
}

else {
echo "Not found.";
}

?>

字符串
您还可以通过替换以下内容与表单一起实现此功能:

$checkWord='break';


$checkWord=$_POST['checkWord'];


即:

<?php

if(isset($_POST['submit'])){
$keywords = array('__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor');

$predefined_constants = array('__CLASS__', '__DIR__', '__FILE__', '__FUNCTION__', '__LINE__', '__METHOD__', '__NAMESPACE__', '__TRAIT__');
$checkWord=$_POST['checkWord'];

if (in_array($checkWord, $keywords)) {
    echo "FOUND!!";
}

else {
echo "Not found.";
   }

}

?>

<form method="post" action="">

Enter word to check: 
<input type="text" name="checkWord">

<br>
<input type="submit" name="submit" value="Check for reserved word">
</form>


在窗体中使用这两个数组集的不同版本。
它可以代表一些抛光,但它的伎俩

<?php

if(isset($_POST['submit'])){
$keywords = array('__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor');

$predefined_constants = array('__CLASS__', '__DIR__', '__FILE__', '__FUNCTION__', '__LINE__', '__METHOD__', '__NAMESPACE__', '__TRAIT__');

$checkWord=$_POST['checkWord'];

$checkconstant=$_POST['checkconstant'];

if (in_array($checkWord, $keywords)) {
    echo "<b>Reserved word FOUND!!</b>";
    echo "\n";
}

else {
echo "Reserved word not found or none entered.";
   }

if (in_array($checkconstant, $predefined_constants)) {
    echo "<b>Constant word FOUND!!</b>";
    echo "\n";
}

else {
echo "Constant not found or none entered.";
   }

}

?>

<form method="post" action="">

Enter reserved word to check: 
<input type="text" name="checkWord">

Enter constant word to check: 
<input type="text" name="checkconstant">

<br><br>
<input type="submit" name="submit" value="Check for reserved words">
<input type="reset" value="Reset" name="reset">
</form>

e4yzc0pl

e4yzc0pl4#

你可以的正如你在链接中提到的,我们有一个这个名字的列表,那么为什么只是以这种方式检查呢?:

$keywords = array('__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor');

 var_dump(in_array('__halt_compiler',$keywords));

字符串

r8xiu3jd

r8xiu3jd5#

我写了这个函数isRW(string $string) NULL|false|string试试。如果输入不是单词,则返回NULL;如果输入不是保留的,则返回布尔值false;如果输入是保留的,则返回string(PHP词法标记名)

function isRW($str){
    if(!preg_match("/^\w{1,20}/", $str)) return null; $rsv=false;
    $uc  = ['true','false','parent','self']; //uncheckable list
    $tk  = token_get_all('<?php '.(boolval($str)? $str:'x')); $tknm=token_name($tk[1][0]); 
    $cst = get_defined_constants(true); unset($cst['user']); global $phpcst; 
    $phpcst = !isset($phpcst)? array_merge(...array_column($cst, null)): $phpcst;

    if($tknm!='T_STRING'
    or in_array($str, $uc)  //if it's uncheckable 
    or @settype($str, $str) //if it's a type like int,NULL,object..
    or preg_match("/__\w/", $str) //PHP reserved all methods prefixed by "__" for future use
    or array_key_exists($str, $phpcst) //if it's a PHP const
    or (function_exists($str) and (new \ReflectionFunction($str))->isInternal())
    or (class_exists($str)    and (new \ReflectionClass($str))->isInternal())) $rsv=true;

    return $rsv? $tknm: $rsv;
}

字符串
一些测试输出:

isRW('}');                  //return null
isRW('foobar');             //return boolean false
isRW('void');               //return boolean false
isRW('isInternal');         //return boolean false
isRW('_call');              //return boolean false
isRW('__call');             //return string T_STRING
isRW('__halt_compiler');    //return string T_HALT_COMPILER
isRW('private');            //return string T_PRIVATE
isRW('__DIR__');            //return string T_DIR
isRW('global');             //return string T_GLOBAL
isRW('E_ERROR');            //return string T_STRING
isRW('DATE_ISO8601');       //return string T_STRING
isRW('PHP_SAPI');           //return string T_STRING
isRW('namespace');          //return string T_NAMESPACE
isRW('function');           //return string T_FUNCTION
isRW('ReflectionClass');    //return string T_STRING
isRW('abstract');           //return string T_ABSTRACT
isRW('self');               //return string T_STRING
isRW('array');              //return string T_ARRAY
isRW('is_array');           //return string T_STRING
isRW('callable');           //return string T_CALLABLE
isRW('isset');              //return string T_ISSET
isRW('and');                //return string T_LOGICAL_AND
isRW('echo');               //return string T_ECHO

abithluo

abithluo6#

根据您的用例,在php中检查保留字可能比简单地在列表中查找值要复杂一些。
有两件事需要考虑:

  • 您要使用保留字的PHP版本
  • 您要使用它的位置-函数/命名空间/常量/类/方法名

相同的保留字在代码中可能会有不同的行为,具体取决于此,让我们以array关键字为例。

  • 从4.0版到7.0版,它不能用作常量名,但从7.0版开始可以使用
  • 从4.0版到8.0版,它不能用作命名空间的一部分,但从8.0版开始可以使用
  • 从4.0版开始,不能用作类名。
  • 从4.0版开始,它不能用作函数名
  • 从4.0版到7.0版,它都不能用作方法名,但从7.0版开始可以使用

又如,namespace

  • 从5.3版到7.0版,它不能用作常量名,但从7.0版开始可以使用
  • 从5.3版开始,它不能用作命名空间的一部分,而与__halt_compiler一起使用是两个排除项之一,即使在8.0版中也不能在命名空间中使用
  • 从5.3版开始,不能将其用作类名
  • 从5.3版开始,不能将其用作函数名
  • 从5.3版到7.0版,它都不能用作方法名,但从7.0版开始可以使用

正如您所看到的,有许多细微差别,这取决于不同版本中的许多变化。
我也有同样的需求,为此创建了一个库。它可以用在复杂的用例中,检查一个保留字是否可以用在特定php版本的特定地方。请看一下,也许它能解决你的问题。
https://github.com/sspat/reserved-words

kxxlusnw

kxxlusnw7#

已经有一个公认的答案了,但我同意@HoldOffHunger的观点,即性能是一个具有如此大的值列表的问题。
但是,而不是作出大量的编辑,以解决问题的答案,这是我的版本。它将区分大小写的关键字与传递参数的小写版本进行比较。
感谢@HoldOffHunger提供初始结构。

class PHPReservedWords {
    private $word_hash = [];

    public function isWordReserved(string $word) {
        $hashes = $this->reservedWordsHash();

        return isset($hashes['cs'][$word])
               || isset($hashes['ci'][strtolower($word)]);
    }

    public function reservedWordsHash() {
        if (!$this->word_hash) {
            $hash = $this->reservedWords();
            $this->word_hash['ci'] = array_change_key_case(array_flip($hash['ci']));
            $this->word_hash['cs'] = array_flip($hash['cs']);
        }

        return $this->word_hash;
    }
    public function reservedWords() {
        // Primary Source: https://php.net/manual/en/reserved.php
        // ------------------------------------------------------
        $keywords = [
            // https://php.net/manual/en/reserved.keywords.php
            // -----------------------------------------------
            'ci' => [
                '__halt_compiler', 'abstract', 'and', 'array', 'as',
                'break', 'callable', 'case', 'catch', 'class', 'clone',
                'const', 'continue', 'declare', 'default', 'die', 'do',
                'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor',
                'endforeach', 'endif', 'endswitch', 'endwhile', 'eval',
                'exit', 'extends', 'final', 'finally', 'for', 'foreach',
                'function', 'global', 'goto', 'if', 'implements', 'include',
                'include_once', 'instanceof', 'insteadof', 'interface',
                'isset', 'list', 'namespace', 'new', 'or', 'print', 'private',
                'protected', 'public', 'require', 'require_once', 'return',
                'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use',
                'var', 'while', 'xor', 'yield', 'yield from',

                // https://php.net/manual/en/reserved.constants.php
                // ------------------------------------------------
                'true', 'false', 'null',

                // https://php.net/manual/en/reserved.other-reserved-words.php
                // -----------------------------------------------------------
                'int', 'float', 'bool', 'string', 'true', 'false',
                'null', 'resource', 'mixed', 'numeric',
            ],
            'cs' => [
                // https://php.net/manual/en/reserved.classes.php
                // ----------------------------------------------
                'Directory', 'stdClass', '__PHP_Incomplete_Class',
                'Exception', 'ErrorException', 'php_user_filter',
                'Closure', 'Generator', 'ArithmeticError',
                'AssertionError', 'DivisionByZeroError', 'Error',
                'Throwable', 'ParseError', 'TypeError',
                'self', 'static', 'parent',

                // https://php.net/manual/en/reserved.constants.php
                // ------------------------------------------------
                'PHP_VERSION', 'PHP_MAJOR_VERSION', 'PHP_MINOR_VERSION',
                'PHP_RELEASE_VERSION', 'PHP_VERSION_ID', 'PHP_EXTRA_VERSION',
                'PHP_ZTS', 'PHP_DEBUG', 'PHP_MAXPATHLEN', 'PHP_OS',
                'PHP_OS_FAMILY', 'PHP_SAPI', 'PHP_EOL', 'PHP_INT_MAX',
                'PHP_INT_MIN', 'PHP_INT_SIZE', 'PHP_FLOAT_DIG',
                'PHP_FLOAT_EPSILON', 'PHP_FLOAT_MIN', 'PHP_FLOAT_MAX',
                'DEFAULT_INCLUDE_PATH', 'PEAR_INSTALL_DIR', 'PEAR_EXTENSION_DIR',
                'PHP_EXTENSION_DIR', 'PHP_PREFIX', 'PHP_BINDIR', 'PHP_BINARY',
                'PHP_MANDIR', 'PHP_LIBDIR', 'PHP_DATADIR', 'PHP_SYSCONFDIR',
                'PHP_LOCALSTATEDIR', 'PHP_CONFIG_FILE_PATH', 'PHP_CONFIG_FILE_SCAN_DIR',
                'PHP_SHLIB_SUFFIX', 'PHP_FD_SETSIZE', 'E_ERROR', 'E_WARNING',
                'E_PARSE', 'E_NOTICE', 'E_CORE_ERROR', 'E_CORE_WARNING',
                'E_COMPILE_ERROR', 'E_COMPILE_WARNING', 'E_USER_ERROR',
                'E_USER_WARNING', 'E_USER_NOTICE', 'E_RECOVERABLE_ERROR',
                'E_DEPRECATED', 'E_USER_DEPRECATED', 'E_ALL', 'E_STRICT',
                'PHP_WINDOWS_EVENT_CTRL_C', 'PHP_WINDOWS_EVENT_CTRL_BREAK',
            ],
        ];
        $version = explode('.', PHP_VERSION);
        /*
         * Starting at the highest matching version,
         * add keywords that came into play up to that point
         */
        switch ("{$version[0]}.{$version[1]}") {
            case '8.2':
            case '8.1':
                $keywords['ci'][] = 'readonly';
            case '8.0':
                $keywords['ci'][] = 'match';
            case '7.4':
                $keywords['ci'][] = 'fn';
            case '7.3':
            case '7.2':
                $keywords['ci'][] = 'object';
            case '7.1':
                array_push(
                    $keywords['ci'],
                    'void',
                    'iterable'
                );
            case '7.0':
                break;
            default:
                throw new Exception('Your version of PHP is too old');
        }

        return $keywords;
    }
}

字符串
工作代码:https://onlinephp.io/c/51226

相关问题