【问题标题】:Should I declare and check if variables exist in PHP?我应该声明并检查 PHP 中是否存在变量吗?
【发布时间】:2012-01-14 14:32:58
【问题描述】:

我注意到在 XAMPP 上启用了严格的错误报告,现在我得到未定义的索引错误。我只有两个小问题(这里还在学习):

我知道你没有在 PHP 中声明变量,但无论如何声明它们有什么好处吗?如果没有,为什么在我没有定义严格错误报告的情况下会收到错误?

例如,当我使用 get 变量时,我会在运行类似的函数之前检查它们的值

if($_GET['todo'] == 'adduser')
    runFunctionAddUser();

这会产生错误,因为我从不首先检查 get 变量是否存在。我应该这样做吗

if(isset($_GET['todo']))
    if($_GET['todo'] == 'adduser')
        runFunctionAddUser();

相反?这样做会有优势还是不必要且缓慢?

【问题讨论】:

  • 缓冲区溢出是一个神话。 ——我个人的观点(我很孤单)是应该避免压制通知,除非它们变得太烦人和太多。特别是缺少 $_GET 变量会产生有用的调试消息来审计应用程序流。保留它们,但禁用生产服务器上的错误显示。不过,请偶尔启用它们以进行开发和调试。

标签: php structure undefined isset


【解决方案1】:

我建议if(!empty($_GET['todo']) && $_GET['todo'] == 'adduser')。这是因为 PHP 会短路逻辑表达式。

最好使用E_ALL(包括E_NOTICE)的错误报告级别进行开发,因为它可以快速帮助识别输入错误的变量/键名。

如果您要问是否测试变量是否存在速度很慢,那么您就问错了问题(答案是它的速度非常快。您在使用文件系统/数据库/等时会变慢) .

【讨论】:

  • 感谢您的回复。从现在开始我会确保做空检查,但是你知道为什么首先检查 empty() 和 isset() 比不做检查更好吗?
  • 它让语言知道您期望变量可能不存在。以$_GET['foobr'] = 'blah'; if($_GET['foobar']) ...; 为例。由于发出了通知,因此很容易识别拼写错误。
  • 把它想象成一个半自动测试套件,确保您对变量的使用(有点)理智。
  • 不要当你的意思是isset时使用!empty。假设值等于空 - 0false、一个空字符串...
【解决方案2】:

这不是您得到的缺少变量的错误,而是尝试将变量与不存在的变量进行比较的错误。

如果您尝试将 nothingness 与“adduser”进行比较,则会引发错误,因为您无法比较 nothingness

这就是#1 的答案。

对于 #2,您应该几乎总是(如果不总是)检查变量是否存在,尤其是您的 GET 变量,因为它们非常不稳定。

【讨论】:

  • 感谢您帮助澄清这一点,对于我当时使用的所有变量,我应该这样做 $variable = '';每次我在做某事后使用该变量时?
【解决方案3】:

这不是一个直接的答案,因为您已经知道了,而是如何归档它的信息:

我总是在所有程序中使用this 之类的函数来初始化传入变量(如果需要,使用默认值)。

所以你可以像这样进行初始化:

$todo = initGet('todo');

然后正常检查:

if($todo=='adduser') {

以及功能:

function initGet($var, $default=''){
    if(!isset($_GET[$var])) return $default;
    return $_GET[$var];
}

【讨论】:

    【解决方案4】:

    这个帖子有点老了,但我做了一些与这个问题相关的测试,所以我不妨发布它:

    测试代码(PHP 5.3.3 - CentOS release 6.5 (Final)):

    class NonExistant
    {
        protected $associativeArray = array(
            'one' => 'one',
            'two' => 'two',
            'three' => 'three',
            'four' => 'four',
            'five' => 'five',
            'six' => 'six',
        );
    
        protected $numIterations = 10000;
    
        public function noCheckingTest()
        {
            for ($i = 0; $i < $this->numIterations; $i++) {
                $this->associativeArray['none'];
            }
        }
    
        public function emptyTest()
        {
            for ($i = 0; $i < $this->numIterations; $i++) {
                empty($this->associativeArray['none']);
            }
        }
    
        public function isnullTest()
        {
            for ($i = 0; $i < $this->numIterations; $i++) {
                is_null($this->associativeArray['none']);
            }
        }
    
    
        public function issetTest()
        {
            for ($i = 0; $i < $this->numIterations; $i++) {
                isset($this->associativeArray['none']);
            }
        }
    
        public function arrayKeyExistsTest()
        {
            for ($i = 0; $i < $this->numIterations; $i++) {
                array_key_exists('none', $this->associativeArray);
            }
        }
    }
    

    结果是:

    | Method Name                              | Run time             | Difference
    =========================================================================================
    | NonExistant::noCheckingTest()            | 0.86004090309143     | +18491.315775911%
    | NonExistant::emptyTest()                 | 0.0046701431274414   | +0.95346080503016%
    | NonExistant::isnullTest()                | 0.88424181938171     | +19014.461681183%
    | NonExistant::issetTest()                 | 0.0046260356903076   | Fastest
    | NonExistant::arrayKeyExistsTest()        | 1.9001779556274      | +209.73055713%
    

    通过call_user_func() 以相同的方式调用所有函数,并以microtime(true) 计时

    观察

    empty()isset() 是这里其他两种方法的明显赢家,这两种方法在性能上几乎息息相关。

    is_null() 性能不佳,因为它需要先查找值,这与访问不存在的值 $this-&gt;associativeArray['none'] 几乎相同,这涉及到数组的完整查找。

    但是,我对array_key_exists() 的表现感到惊讶。它比 empty()isset() 慢 2 倍。

    注意:

    我测试过的所有函数都有不同的用途,此基准仅适用于您想要快速检查数组中的值的最通用用例。我们可以讨论 null 是否应该被视为“价值”或仅仅是不存在的指标,但这是另一个话题。 o.o

    2017-01-20 更新

    使用 PHP 7.1

    修复了@bstoney 提到的错误

    $ php -v
    PHP 7.1.0 (cli) (built: Dec  2 2016 03:30:24) ( NTS )
    Copyright (c) 1997-2016 The PHP Group
    Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies
    $ php -a
    php > $a = ['one' => 1, 'two' => 2, 'three' => 3];
    php > $numIterations = 1000000;
    php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { $a['none']; }; echo microtime(true) - $start;
    0.43768811225891
    php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { empty($a['none']); }; echo microtime(true) - $start;
    0.033049821853638
    php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { is_null($a['none']); }; echo microtime(true) - $start;
    0.43995404243469
    php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { isset($a['none']); }; echo microtime(true) - $start;
    0.027907848358154
    php > $start = microtime(true); for ($i = 0; $i < $numIterations; $i++) { array_key_exists('none', $a); }; echo microtime(true) - $start;
    0.049405097961426
    

    【讨论】:

    • 使用array_key_exists的测试代码无效,应该是array_key_exists('none', $this-&gt;associativeArray)
    • @bstoney 不错,只用了 3 年就有人注意到了 XD
    • 更新了答案以包括 PHP 7.1 测试和修复错误 :)
    • 谢谢。我也发现了另一种可能性:使用$value = &amp;$this-&gt;associativeArray['none'];,然后您可以检查$value === null。这个性能只比isset慢一点
    • 您应该使用===null 而不是is_null。它可能会更快。
    猜你喜欢
    • 2012-01-01
    • 2018-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    相关资源
    最近更新 更多