在PHP中取消设置之前检查var是否存在?


88

启用错误报告后,或者甚至为了最佳实践,在PHP中取消设置变量时,是否应该检查它是否首先存在(在这种情况下并不总是存在)然后取消设置,或者只是取消设置?

<?PHP
if (isset($_SESSION['signup_errors'])){
    unset($_SESSION['signup_errors']);
}

// OR

unset($_SESSION['signup_errors']);
?>


1
NOT使用效率更高isset。看看我的答案。我已经做过测试以找出速度差异。
丹·布雷

Answers:


167

只是取消设置它,如果它不存在,将不会执行任何操作。


3
我不知道它是否会发出警告或通知
JasonDavis,2009年

19
@SilentGhost我同意,这似乎是一个简单的测试,但是他们正在寻求专业意见,尽管错误日志可能没有任何错误/警告/通知未设置未定义的变量,但可能还有其他未记录的问题。例如,仅调用unset意味着PHP会遍历所有var数据,因为它找不到任何东西,而使用则if set可能会有更好的索引方案。(仅举一个例子,以前的可能是补鞋匠,两种方法都使用相同的数据检查方法)。
詹姆斯

没错,而且效率更高。看一下我的答案,因为我已经测试了使用isset不使用的速度isset
丹·布雷

否决-您无法取消设置未定义的数组键。
Behnam

1
@jascha我说过,我们不能!
Behnam

48

从PHP手册

关于这些注释中前面的一些困惑,是什么导致unset()在取消设置不存在的变量时触发通知...。

取消设置不存在的变量,如

<?php
unset($undefinedVariable);
?>

不会触发“未定义的变量”通知。但

<?php
unset($undefinedArray[$undefinedKey]);
?>

触发两个通知,因为此代码用于取消设置数组的元素;$ undefinedArray和$ undefinedKey本身都没有被设置,它们只是用来定位应该被设置的对象。毕竟,如果它们确实存在,那么您仍然希望它们随后都存在。您不希望仅因为您取消set()它的元素之一就希望整个数组消失!


41
这需要更多澄清。只要数组本身存在,就可以取消设置未定义的数组键。
kingmaple 2012年

@kristovaher确实-这根本没有解决OP所描述的特定情况。
Mark Amery 2014年

21

unset在未定义的变量上使用不会导致任何错误(除非变量是不存在的数组(或对象)的索引)。

因此,您唯一需要考虑的就是最有效的方法。如我的测试所示,不使用“ isset”进行测试更加有效。

测试:

function A()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        unset($defined);
    }
}

function B()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        unset($undefined);
    }
}

function C()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        if (isset($defined))
            unset($defined);
    }
}

function D()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        if (isset($undefined))
            unset($undefined);
    }
}

$time_pre = microtime(true);
A();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function A time = $exec_time ";

$time_pre = microtime(true);
B();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function B time = $exec_time ";

$time_pre = microtime(true);
C();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function C time = $exec_time ";

$time_pre = microtime(true);
D();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function D time = $exec_time";
exit();

结果:

  1. Function A time = 1.0307259559631
    • 定义不带isset
  2. Function B time = 0.72514510154724
    • 没有isset的未定义
  3. Function C time = 1.3804969787598
    • 使用isset定义
  4. Function D time = 0.86475610733032
    • 未定义使用isset

结论:

使用它总是效率较低isset,更不用说编写它需要花费少量的额外时间。尝试unset使用未定义的变量比检查它是否可以更快unset


1
这比接受的答案更好!感谢您运行这些测试。
亚当·弗里德曼

3

如果您想取消设置变量,则可以使用 unset

unset($any_variable); // bool, object, int, string etc

尝试取消设置变量时,检查其存在没有好处。

如果变量是数组,并且希望取消设置元素,则必须确保先存在元素,这也适用于对象属性。

unset($undefined_array['undefined_element_key']); // error - Undefined variable: undefined_array

unset($undefined_object->undefined_prop_name); // error - Undefined variable: undefined_object

通过将unsetin包装在一个if(isset($var)){ ... }块中,可以轻松解决此问题。

if(isset($undefined_array)){
    unset($undefined_array['undefined_element_key']); 
}

if(isset($undefined_object)){
    unset($undefined_object->undefined_prop_name); 
}

我们仅检查变量(parent)的原因仅是因为我们不需要检查属性/元素,并且这样做会写和计算慢得多,因为它将添加额外的检查。

if(isset($array)){
...
}

if(isset($object)){
...
}

.vs

$object->prop_name = null;
$array['element_key'] = null;

// This way elements/properties with the value of `null` can still be unset.

if(isset($array) && array_key_exists('element_key', $array)){
...
}

if(isset($object) && property_exists($object, 'prop_name')){
...
}

// or 

// This way elements/properties with `null` values wont be unset.

if(isset($array) && $array['element_key'])){
...
}

if(isset($object) && $object->prop_name)){
...
}

不用说,但是type获取,设置和取消设置元素或属性时了解变量的意义也很重要。使用错误的语法将引发错误。

尝试取消设置多维数组或对象的值时,方法相同。您必须确保父键/名称存在。

if(isset($variable['undefined_key'])){
    unset($variable['undefined_key']['another_undefined_key']);
}

if(isset($variable->undefined_prop)){
    unset($variable->undefined_prop->another_undefined_prop);
}

处理对象时,还有另一件事要考虑,那就是可见性。

仅仅因为它存在并不意味着您有权对其进行修改。


最后,一个正确的答案。谢谢。
wp78de

一个小的更新:在PHP 7.4 / 8.0中,当您unset不存在父对象的属性时,不会引发任何错误。但是,在PHP8中不存在的数组中取消键的设置不仅会引起通知,还会引起警告(可能会更改)。
wp78de

1

检查此链接 https://3v4l.org/hPAto

在线工具显示了不同版本PHP的代码兼容性

根据此工具的代码

unset($_SESSION['signup_errors']);

可以在PHP> = 5.4.0上工作,而不会给您任何通知/警告/错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.