unset

(PHP 4, PHP 5, PHP 7, PHP 8)

unset释放给定变量

描述

unset(混合 $var, 混合 ...$vars):

unset() 销毁指定的变量。

unset() 在函数内部的行为可能会有所不同,具体取决于您试图销毁的变量类型。

如果一个全局变量在函数内部被 unset(),那么只有局部变量会被销毁。调用环境中的变量将保留与调用 unset() 之前相同的值。

<?php
function destroy_foo()
{
global
$foo;
unset(
$foo);
}

$foo = 'bar';
destroy_foo();
echo
$foo;
?>

上面的例子将输出

bar

unset() 函数内部的全局变量,请使用 $GLOBALS 数组。

<?php
function foo()
{
unset(
$GLOBALS['bar']);
}

$bar = "something";
foo();
?>

如果一个按引用传递的变量在函数内部被 unset(),那么只有局部变量会被销毁。调用环境中的变量将保留与调用 unset() 之前相同的值。

<?php
function foo(&$bar)
{
unset(
$bar);
$bar = "blah";
}

$bar = 'something';
echo
"$bar\n";

foo($bar);
echo
"$bar\n";
?>

上面的例子将输出

something
something

如果一个静态变量在函数内部被 unset(),那么 unset() 仅在函数剩余部分的上下文中销毁该变量。后续调用将恢复该变量的先前值。

<?php
function foo()
{
static
$bar;
$bar++;
echo
"Before unset: $bar, ";
unset(
$bar);
$bar = 23;
echo
"after unset: $bar\n";
}

foo();
foo();
foo();
?>

上面的例子将输出

Before unset: 1, after unset: 23
Before unset: 2, after unset: 23
Before unset: 3, after unset: 23

参数

var

要释放的变量。

vars

更多变量。

返回值

不返回值。

示例

示例 #1 unset() 示例

<?php
// 销毁单个变量
unset($foo);

// 销毁数组的单个元素
unset($bar['quux']);

// 销毁多个变量
unset($foo1, $foo2, $foo3);
?>

示例 #2 使用 (unset) 强制转换

(unset) 强制转换经常与 unset() 函数混淆。 (unset) 强制转换仅用作 NULL 类型的强制转换,为了完整性。它不会改变它正在强制转换的变量。从 PHP 7.2.0 开始,(unset) 强制转换已弃用,从 8.0.0 开始已移除。

<?php
$name
= 'Felipe';

var_dump((unset) $name);
var_dump($name);
?>

上面的例子将输出

NULL
string(6) "Felipe"

注释

注意: 由于这是一个语言结构,而不是一个函数,因此它不能使用 可变函数命名参数 调用。

注意:

可以释放当前上下文中可见的对象属性。

如果声明,访问未设置的属性时会调用 __get(),设置未设置的属性时会调用 __set()

注意:

在对象方法内部无法释放 $this

注意:

当对不可访问的对象属性使用 unset() 时,如果声明,将调用 __unset() 重载方法。

参见

添加注释

用户贡献注释 32 个注释

Phantasma_9 at yahoo dot com
8 年前
这可能很琐碎,但释放不存在的变量不会产生错误。
Hayley Watson
11 年前
在释放变量之前,您无需检查变量是否已设置。
<?php
unset($a);
?>
是无害的。
<?php
if(isset($a)) {
unset(
$a);
}
?>
是无意义的复杂化。

这并不适用于具有 __isset() 方法(显着改变对象状态)或 __unset() 方法(未正确检查其参数或具有额外副作用)的对象属性。

后一种情况意味着 __unset 不应该比它所说的更多,并且也有责任检查(可能使用 __isset())它被要求做的事情是否有意义。

前一种情况只是纯粹的糟糕设计。
tecdoc at ukr dot net
2 年前
小心!在数组中 unset() 元素会将内部数组指针向前移动一个位置。
nox at oreigon dot de
16 年前
如果你尝试 unset 一个对象,请注意引用。

只有当 *所有* 引用都被 unset 时,对象才会释放其资源并触发其 __destruct 方法。
即使它们 *在* 对象中... 唉!

<?php

class A {
function
__destruct() {
echo
"cYa later!!\n";
}
}

$a = new A();
$a -> a = $a;
#unset($a); # 只要取消注释,你就会看到

echo "No Message ... hm, what now?\n";
unset(
$a -> a);
unset(
$a);

echo
"Finally that thing is gone\n";

?>

当然,对象在脚本结束时会完全消失。
Kai Kunstmann
16 年前
由于 unset() 是一个语言结构,它不能传递除变量以外的任何东西。它的唯一目的是 "unset" 这些变量,即从当前作用域中删除它们并销毁其关联数据。这对于引用变量尤其如此,其中不是实际值被销毁,而是对该值的引用。这就是为什么你不能将 'unset()' 包裹在一个用户定义函数中的原因:如果你按值传递参数,你会 unset 数据的副本;如果你按引用传递参数,你只会 unset 函数作用域内的引用变量。没有解决方法,因为你不能在 PHP 中将 '作用域' 传递给函数。这样的函数只能针对存在于公共或全局作用域中的变量(比较 'unset($_GLOBALS[variable])')。

我不知道 PHP 如何在内部处理垃圾回收,但我猜这种行为会导致巨大的内存泄漏:如果一个值变量在另一个变量仍然持有对内存中值的引用的情况下超出了作用域,那么 unset 该引用将仍然在内存中保留该值,但可能会 unset 对该内存中数据的最后一个引用,因此:占用但无法再引用的无用内存。
j dot vd dot merwe at enovision dot net
13 年前
一个关于如何从来自 mysql 请求的数组结果中 unset 数组元素的示例。在这个示例中,它检查文件是否存在,如果不存在,则从数组中删除该行。

<?php
$db
->set_query("select * from documents where document_in_user = 0"); //1
$documents = $db->result_to_array($db->get_result()); //1

foreach ($documents as $key => $row) { //2

$file = "uploads/".rawurldecode($row['document_name']);

if (
file_exists ( $file ) == FALSE ) {
unset(
$documents[$key]); //3
}
}

$documents = array_values($documents); // 重新索引数组 (4)
?>

变量
mysql 表 = documents,
数组 = $documents
数组键(索引) = $key
数组行(记录) = $row

解释

1.
它从表(mysql)中获取数组

2.
foreach 遍历数组 $documents

3.
如果记录不存在,则 unset

4.
array_values($documents) 重新索引 $documents 数组,否则当你的进程开始期望一个以键 ($key) 0(零)开头的数组时,你可能会遇到麻烦。
franckraynal at free dot fr
19 年前
这是一种让 'unset' 在函数内部对会话变量起作用的另一种方法

<?php
function unsetSessionVariable ($sessionVariableName) {
unset(
$GLOBALS[_SESSION][$sessionVariableName]);
}
?>

希望它对其他人也有用...
F.
andre at twg dot com dot au
20 年前
只有当 register_globals 为 'ON' 时,这才会起作用。

unset( $_SESSION['variable'] );

上面的代码在 register_globals 打开的情况下不起作用(只在函数外部起作用)。

$variable = $_SESSION['variable'];
unset( $_SESSION['variable'], $variable );

上面的代码在 register_globals 打开且在函数内部起作用。
hessodreamy at gmail dot com
17 年前
为了澄清 hugo dot dworak at gmail dot com 关于 unset 未设置内容的说明

在数组中 unset 一个不存在的键 *不会* 抛出错误。
<?
$array = array();

unset($array[2]);
// 这不会抛出错误

unset($array[$undefinedVar]);
// 由于未定义的变量,而不是由于不存在的键,因此会抛出错误。
?>
pfreilly at umd dot umich dot edu
12 年前
尽管搜索了很多,但我还没有找到关于如何在 PHP 中手动释放变量(不是对象)资源的解释。我也看到了很多关于 unset() 与将变量设置为 null 的优缺点的评论。因此,以下是比较 unset() 大量变量与将它们设置为 null(关于内存使用和处理时间)的一些基准测试结果。

10 个变量
Unset
内存使用量:296
经过时间:1.0013580322266E-5

Null set
内存使用量:1736
经过时间:5.9604644775391E-6

50 个变量
Unset
内存使用量:296
经过时间:3.6001205444336E-5

Null set
内存使用量:8328
经过时间:3.2901763916016E-5

100 个变量
Unset
内存使用量:296
经过时间:5.6982040405273E-5

Null set
内存使用量:15928
经过时间:5.8174133300781E-5

1000 个变量
Unset
内存使用量:296
经过时间:0.00041294097900391

Null set
内存使用量:168096
经过时间:0.00067591667175293

10000 个变量
Unset
内存使用量:296
经过时间:0.0042569637298584

Null set
内存使用量:1650848
经过时间:0.0076930522918701

100000 个变量
Unset
内存使用量:296
经过时间:0.042603969573975

Null set
内存使用量:16249080
经过时间:0.087724924087524

300000 个变量
Unset
内存使用量:296
经过时间:0.13177299499512

Null set
内存使用量:49796320
经过时间:0.28617882728577

也许我的 null set 测试代码有缺陷,但尽管存在这种可能性,也很容易看出 unset() 对处理时间的影响很小,并且没有明显的内存使用影响(除非 memory_get_usage() 返回的值有缺陷)。如果你真的关心在 <50 个变量上节省的约 4 微秒,那么你有权利这样做。否则,使用 unset() 来最大限度地减少脚本对系统的影响。
注意:在通过 RPM 安装在 Fedora 14 上的 PHP 5.3.8 上测试
anon at no spam dot no address dot com
20 年前
补充 bond at noellebond dot com 的说法,如果你想从数组的末尾删除索引,如果你使用 unset,下一个索引值将仍然是它原本应该的值。

例如,你有
<?php
$x
= array(1, 2);

for (
$i = 0; $i < 5; $i++)
{
unset(
$x[(count($x)-1)]); // 删除数组中最后设置的键

$x[] = $i;
}
?>

你期望
Array([0] => 1, [1] => 4)
因为你想要它删除最后设置的键....

但你实际上得到
Array ( [0] => 1 [4] => 2 [5] => 3 [6] => 4 )

这是因为即使最后一个键被删除了,自动索引仍然保留了它以前的值。

只有当你从末尾删除值时,这看起来才会不对劲。我猜不同的人会想要不同的方法。

解决这个问题的方法是使用 array_pop() 而不是 unset(),因为 array_pop() 会刷新数组的自动索引。
<?php
$x
= array(1, 2);

for (
$i = 0; $i < 5; $i++)
{
array_pop($x); // 删除数组中的最后一项

$x[] = $i;
}
?>

这将返回预期的 x 值:Array([0] => 1, [1] => 4);

希望这能帮助那些出于某种奇怪原因需要它的人,我就是这样。
clark at everettsconsulting dot com
18 年前
至少在 PHP 5.0.4 中,你可以通过将数组按引用传递给函数来 unset 函数内部的数组元素。
但是,正如手册中所暗示的那样,你不能通过引用传递数组来 unset 整个数组。

<?php
function remove_variable (&$variable) // 按引用传递变量
{
unset(
$variable);
}

function
remove_element (&$array, $key) // 按引用传递数组
{
unset(
$array[$key]);
}

$scalar = 'Hello, there';
echo
'Value of $scalar is: ';
print_r ($scalar); echo '<br />';
// Value of $scalar is: Hello, there

remove_variable($scalar); // 尝试取消设置变量
echo 'Value of $scalar is: ';
print_r ($scalar); echo '<br />';
// Value of $scalar is: Hello, there

$array = array('one' => 1, 'two' => 2, 'three' => 3);
echo
'Value of $array is: ';
print_r ($array); echo '<br />';
// Value of $array is: Array ( [one] => 1 [two] => 2 [three] => 3 )

remove_variable($array); // 尝试取消设置数组
echo 'Value of $array is: ';
print_r ($array); echo '<br />';
// Value of $array is: Array ( [one] => 1 [two] => 2 [three] => 3 )

remove_element($array, 'two'); // 成功从数组中删除元素
echo 'Value of $array is: ';
print_r ($array); echo '<br />';
// Value of $array is: Array ( [one] => 1 [three] => 3 )

?>
phpmanual at kennel17 dot co dot uk
14 年前
请注意,如果您尝试取消设置不存在的数组索引且其父级也不存在,则 PHP 4 将生成警告。

示例

<?php

$foo
= array();

unset(
$foo['Bar']['Baz']);

?>

结果:“注意:未定义的索引:Bar”

在 PHP5 中,不会引发错误,这在我看来是正确的行为。

请注意,在上面的示例中,使用 unset($foo['Bar']) 不会在任何版本中生成警告。

(在 4.4.9 和 5.2.4 上测试)
匿名
17 年前
仅为确认,使用 UNSET 会破坏整个数组。我在任何地方都找不到关于此的参考,因此我决定写下它。

使用 unset 和使用 $myarray=array(); 来取消设置之间的区别在于,显然数组只会覆盖,并且仍然存在。

<?php

$myarray
=array("Hello","World");

echo
$myarray[0].$myarray[1];

unset(
$myarray);
//$myarray=array();

echo $myarray[0].$myarray[1];

echo
$myarray;
?>

使用 unset 的输出是
<?
HelloWorld

注意:C:\webpages\dainsider\myarray.php 第 10 行的未定义偏移量:0

注意:C:\webpages\dainsider\myarray.php 第 10 行的未定义偏移量:1

使用 $myarray=array(); 的输出是
?>

<?
HelloWorld

注意:C:\webpages\dainsider\myarray.php 第 10 行的未定义偏移量:0

注意:C:\webpages\dainsider\myarray.php 第 10 行的未定义偏移量:1

数组
?>
pauljamescampbell at gmail dot com
16 年前
这是我对略微乏味的 unset 方法的变体。它在混合中加入了一些 80 年代的史泰龙动作香料。享受!

<?php
/**
* 函数 rambo(第一滴血)
*
* 完全彻底地摧毁一切,返回受害者的击杀数
*
* @param 无所谓,是兰博宝贝
* @return 整数 尸体数量(但如果低于 500,就不值得一提)
*/
function rambo() {

// 获取受害者并启动尸体计数状态
$victims = func_get_args();
$body_count = 0;

// 干掉那些该死的混蛋
foreach($victims as $victim) {
if(
$death_and_suffering = @unset($victim)) {
$body_count++;
}
}

// 兰博在这项任务中累计了多少次击杀?
return($body_count);
}
?>
lion_cat at mail ru
15 年前
关于数组的 unset

如果您取消设置最后一个数组成员
$ar[0]==2
$ar[1]==7
$ar[2]==9

unset ($ar[2])

在通过 $ar[]=7 添加新成员后,

您将获得
$ar[0]==2
$ar[1]==7
$ar[3]==7,

因此,unset 对内部数组计数器没有影响!!!
dan AT --nospam-- cubeland DOT co DOT uk
19 年前
dh at argosign dot de -
可以使用 $GLOBALS 数组在函数内部取消设置全局变量。

<?php
$x
= 10;

function
test() {
// 不需要执行 ' global $x; '
unset ($GLOBALS['x']);
echo
'x: ' . $GLOBALS['x'] . '<br />';
}

test();
echo
"x: $x<br />";

// 将导致
/*
x:
x:
*/
?>
匿名
14 年前
此外,我意识到,当一个对象被销毁时,它会关心销毁对象空间可见性中的变量,但不会关心局部可见性中的变量,请注意发现的模式。

<?php
class release_test{
private
$buffer;
private
$other_object;
public function
__construct(){
$this->other_object=new other_object_class();
}
public function
__destruct(){
// 注意,您始终必须取消设置类对象,以便释放资源
unset($this->other_object);
}
public
allocate_mem_A(){
$this->buffer=file("/tmp/bigfile");
}
public
allocate_mem_B(){
$buffer=file("/tmp/bigfile");
}
public
allocate_mem_C(){
$buffer=file("/tmp/bigfile");
unset(
$buffer);
}
public
allocate_mem_D(){
$this->other_buffer=file("/tmp/bigfile");
}
}

// 这不会导致资源问题
$A=new release_test();
$A->allocate_mem_A();
$A->__destruct();
unset(
$A);

// 这会导致资源问题
$B=new release_test();
$B->allocate_mem_B();
$B->__destruct();
unset(
$B);

// 这不会导致资源问题
$C=new release_test();
$C->allocate_mem_C();
$C->__destruct();
unset(
$C);

// 这不会导致资源问题
$D=new release_test();
$D->allocate_mem_D();
$D->__destruct();
unset(
$D);
?>
thorry at thorry dot net
20 年前
文档在谈到静态变量时并不完全清楚。它说

如果在函数内部取消设置静态变量,则 unset() 会销毁该变量及其所有引用。

<?php
function foo()
{
static
$a;
$a++;
echo
"$a\n";
unset(
$a);
}

foo();
foo();
foo();
?>

上面的示例将输出

1
2
3

它确实如此!但变量并未删除,这就是值不断增加的原因,否则输出将为

1
1
1

引用在函数内部被销毁,这种处理方式与全局变量相同,区别在于静态变量是局部变量。

使用 unset 和静态值时要小心,因为输出结果可能与预期不符。似乎无法销毁静态变量。您只能销毁当前执行函数中的引用,后续的静态语句将恢复引用。

文档如果能写成这样会更好
"如果在一个函数内部 unset() 一个静态变量,unset() 将销毁对该变量的所有引用。"

示例: (已在 PHP 4.3.7 上测试)
<?php
function foo()
{
static
$a;
$a++;
echo
"$a\n";
unset(
$a);
echo
"$a\n";
static
$a;
echo
"$a\n";
}

foo();
foo();
foo();
?>

输出结果为

1

1
2

2
3

3
warhog at warhog dot net
20 年前
您可能希望 unset 所有已定义的变量,以下是一种方法

<?php

function unset_all_vars($a)
{ foreach(
$a as $key => $val)
{ unset(
$GLOBALS[$key]); }
return
serialize($a); }

unset_all_vars(get_defined_vars());

?>

您也可以保存一个 "内存" 的序列化变量,并将它存储在一个临时文件中。如果您处理文本文件和/或文件上传,并且有非常大的变量,这将非常有用。

致敬
edouard dot berge at gmail dot com
13 年前
警告!

从数组中 unset 时,如果 unset 所有元素,数组始终会被设置

$tab=array('A'=>1,'B'=>2);
unset($tab['A']);
unset($tab['B']);
echo isset($tab)." ".count($tab);

输出结果: 1 0
stacionari at gmail dot com
16 年前
有时您需要在某个循环(if、while、foreach 等)中将值分配给数组索引,但您希望将起始索引键设置为大于零的某个数字(例如 5)。以下是一种方法

<?php
$values
= array(5, 10, 15, 100); // 我们希望添加到新数组中的值数组

$myArray = array(4=>0); // 将起始键设置为 4 并分配某个值(例如 0)
unset($myArray[4]); // 删除此索引键,但保留后续枚举

foreach($values as $value){
$myArray[] = $value; // 将值分配到我们的数组中
}

print_r($myArray);

/* 输出结果:

Array ( [5] => 5 [6] => 10 [7] => 15 [8] => 100 )

*/

?>
macnimble at gmail dot com
15 年前
两种在数组中 unset 值的方法

<?php
# 按键移除:
function array_remove_key ()
{
$args = func_get_args();
return
array_diff_key($args[0],array_flip(array_slice($args,1)));
}
# 按值移除:
function array_remove_value ()
{
$args = func_get_args();
return
array_diff($args[0],array_slice($args,1));
}

$fruit_inventory = array(
'apples' => 52,
'bananas' => 78,
'peaches' => 'out of season',
'pears' => 'out of season',
'oranges' => 'no longer sold',
'carrots' => 15,
'beets' => 15,
);

echo
"<pre>Original Array:\n",
print_r($fruit_inventory,TRUE),
'</pre>';

# 例如,胡萝卜和甜菜不是水果...
$fruit_inventory = array_remove_key($fruit_inventory,
"beets",
"carrots");
echo
"<pre>Array after key removal:\n",
print_r($fruit_inventory,TRUE),
'</pre>';

# 我们也删除 'out of season' 和 'no longer sold' 的水果...
$fruit_inventory = array_remove_value($fruit_inventory,
"out of season",
"no longer sold");
echo
"<pre>Array after value removal:\n",
print_r($fruit_inventory,TRUE),
'</pre>';
?>
Hayley Watson
16 年前
关于这些笔记中前面关于导致 unset() 触发通知的原因的一些困惑,以及 unset() 不存在变量时会触发通知的原因...

unset() 不存在变量,例如
<?php
unset($undefinedVariable);
?>
不会触发 "Undefined variable" 通知。但是
<?php
unset($undefinedArray[$undefinedKey]);
?>
会触发两个通知,因为这段代码用于 unset 数组中的一个元素;$undefinedArray 和 $undefinedKey 本身并没有被 unset(),它们只是用于定位应该被 unset 的内容。毕竟,如果它们确实存在,您仍然希望它们在之后都存在。您不希望整个数组因为 unset() 了其中的一个元素而消失!
dibakar dot datta at gmail dot com
18 年前
除了使用 unset 函数注销会话或其他数组值之外,您也可以使用这种小功能,只需一行代码即可完成此任务。

假设您想要注销会话存储的值。
您可以使用

$_SESSION = array();

这种语法可以节省大量时间,而不是 unset 每个值。
Andreas
13 年前
您无法 unset 数组的数字键,如果键是字符串。请看以下示例

// 创建一个包含 3 种不同键类型的简单数组
$test[1] = array(
10 => array('apples'),
"20" => array('bananas'),
'30' => array('peaches')
);
$test[2] = (array) json_decode(json_encode($test[1]));
$test[3] = (array) (object) $test[1];
// 从 stdClass 对象中获取数组形式
$testClass = new stdClass();
$testClass->{10} = array('apples');
$testClass->{"20"} = array('bananas');
$test[4] = (array) $testClass[6];

echo "<pre>";
foreach($test as $testNum => $arr) {

echo "\nTest: " . $testNum . " \n";
var_dump($arr);

foreach($arr as $key => $fruit) {
echo "key: " . $key . "\n";
echo "key exists: ";
var_dump(array_key_exists(strval($key), $arr));
echo "typeof key is: " . gettype($key) . "\n";

unset($arr[$key]);
}
var_dump($arr);
echo "\n" . str_repeat("-", 80);
}
echo "</pre>";

输出结果如下

Test: 1
array(3) {
[10]=>
array(1) {
[0]=>
string(6) "apples"
}
[20]=>
array(1) {
[0]=>
string(7) "bananas"
}
[30]=>
array(1) {
[0]=>
string(7) "peaches"
}
}
key: 10
key exists: bool(true)
typeof key is: integer
key: 20
key exists: bool(true)
typeof key is: integer
key: 30
key exists: bool(true)
typeof key is: integer
array(0) {
}

--------------------------------------------------------------
Test: 2
array(3) {
["10"]=>
array(1) {
[0]=>
string(6) "apples"
}
["20"]=>
array(1) {
[0]=>
string(7) "bananas"
}
["30"]=>
array(1) {
[0]=>
string(7) "peaches"
}
}
key: 10
key exists: bool(false)
typeof key is: string
key: 20
key exists: bool(false)
typeof key is: string
key: 30
key exists: bool(false)
typeof key is: string
array(3) {
["10"]=>
array(1) {
[0]=>
string(6) "apples"
}
["20"]=>
array(1) {
[0]=>
string(7) "bananas"
}
["30"]=>
array(1) {
[0]=>
string(7) "peaches"
}
}

--------------------------------------------------------------
Test: 3
array(3) {
[10]=>
array(1) {
[0]=>
string(6) "apples"
}
[20]=>
array(1) {
[0]=>
string(7) "bananas"
}
[30]=>
array(1) {
[0]=>
string(7) "peaches"
}
}
key: 10
key exists: bool(true)
typeof key is: integer
key: 20
key exists: bool(true)
typeof key is: integer
key: 30
key exists: bool(true)
typeof key is: integer
array(0) {
}

--------------------------------------------------------------
Test: 4
array(2) {
["10"]=>
array(1) {
[0]=>
string(6) "apples"
}
["20"]=>
array(1) {
[0]=>
string(7) "bananas"
}
}
key: 10
key exists: bool(false)
typeof key is: string
key: 20
key exists: bool(false)
typeof key is: string
array(2) {
["10"]=>
array(1) {
[0]=>
string(6) "apples"
}
["20"]=>
array(1) {
[0]=>
string(7) "bananas"
}
}

--------------------------------------------------------------

解决问题的办法是重建数组
$oldArray = $array();
$array = array();
foreach($oldArray as $key => $item) {
$array[intval($key)] = $item;
}
chad 0x40 herballure 0x2e com
17 年前
在 PHP 5.1.6 上观察到,在方法内部 <?php unset($this); ?> 将删除该方法中对 $this 的引用。就 unset() 而言,$this 不被认为是 "特殊的"。
tigercat at aol dot com
11 年前
在函数中组合使用 "global" 和 "unset" 会导致一些意想不到的结果。这是因为 "global" 函数在执行时创建对变量的引用,因此可以在函数中 "global $my_variable" 声明中删除变量。使用过时的引用访问已删除的数据通常是一件坏事;在某些语言中,它会导致机器地址错误。

<?php
$my_global_var
= "旧数据";
f1();

function
f1() // 无效变量引用的示例
{
global
$my_global_var; // 创建对全局变量的引用
f2(); // 重新创建全局变量,因此引用现在无效

// 错误的...
echo $my_global_var; // 输出 "旧数据" (来自无效内存?)

// 正确的...
global $my_global_var; // 重新建立对新全局变量的引用
echo $my_global_var; // 如预期输出 "新数据"
}

function
f2() // 重新创建全局变量
{
unset(
$GLOBALS['my_global_var']); // 此语法适用于所有变量类型,包括数组
global $my_global_var; // 必须在 unset 后执行此操作才能访问新全局变量
$my_global_var = "新数据";
}
?>
muhamad_zakaria at yahoo dot com
19 年前
我们在将 'unset' 应用于重载属性(PHP5)时遇到了问题,请考虑以下代码。
<?php
class TheObj {
public
$RealVar1, $RealVar2, $RealVar3, $RealVar4;
public
$Var = array();

function
__set($var, $val) {
$this->Var[$var] = $val;
}
function
__get($var) {
if(isset(
$this->Var[$var])) return $this->Var[$var];
else return -
1;
}
}

$SomeObj = new TheObj;

// 这里我们为真实变量设置值
$SomeObj->RealVar1 = 'somevalue';
$SomeObj->{'RealVar2'} = 'othervalue';
$SomeObj->{'RealVar'.(3)} = 'othervaluetoo';
$SomeObj->{'RealVar'.'4'} = 'anothervalue';

// 这里我们为虚拟变量设置值
$SomeObj->Virtual1 = 'somevalue';
$SomeObj->{'Virtual2'} = 'othervalue';
$SomeObj->{'Virtual'.(3)} = 'othervaluetoo';
$SomeObj->{'Virtual'.'4'} = 'anothervalue';

// 现在我们将尝试取消设置这些变量
unset($SomeObj->RealVar1);
unset(
$SomeObj->{'RealVar'.(3)});

// 由于这些变量不再可用,以下行将由 '__get' 魔术方法捕获
print $SomeObj->RealVar1."\n";
print
$SomeObj->{'RealVar'.(3)}."\n";

// 现在我们将尝试取消设置这些变量
unset($SomeObj->Virtual1);
unset(
$SomeObj->{'Virtual'.(3)});

// 但是,这些变量仍然可用???即使它们被 "unset" 了
print $SomeObj->Virtual1."\n";
print
$SomeObj->{'Virtual'.(3)}."\n";
?>

请注意,PHP 没有用于取消设置重载属性的魔术回调。这就是为什么 unset($SomeObj->Virtual1) 不起作用的原因。

但当我们设置 'null' 值时它确实起作用,例如以下代码。
<?php
// 现在我们将设置 'null' 值而不是使用 unset 语句
$SomeObj->Virtual1 = null;
$SomeObj->{'Virtual'.(3)} = null;

// 现在这些变量不再可用
print $SomeObj->Virtual1."\n";
print
$SomeObj->{'Virtual'.(3)}."\n";
?>
听起来很丑陋,是吗?

这同样适用于 "虚拟" 数组变量,请在 http://bugs.php.net/bug.php?id=33513 (在反馈中)查看更多相关信息。
PS:我们在编写上述代码时使用的是来自 CVS 快照的 PHP 版本 5.1.0-dev。
magnesium dot oxide dot play+php at gmail dot com
10 年前
您可以取消设置超全局变量,如 $GLOBALS、$_GET 等,但会导致异常行为(从 PHP 5.3.3 开始)。

1) 超全局变量的取消设置是在全局范围内进行的,即在函数内部进行取消设置会影响全局。

2) 可以重新创建取消设置的超全局变量(重新创建的变量是超全局变量),但原始功能(在 $GLOBALS、$_SESSION 中...)已丢失。

<?php

function foo(){
unset(
$GLOBALS);
}

function
bar(){
var_dump($GLOBALS);
}

foo();
bar(); // 产生 E_NOTICE ($GLOBALS 未定义)
$GLOBALS=3;
bar(); // 显示 int(3)

?>
ronan at shopping-feed dot com
4 年前
<?php

$list
= ['a', 'b', 'c'];
next($list);
unset(
$list[1]);

echo
current($list); // 结果: "c"
ray.paseur sometimes uses gmail
2 年前
可能是因为它是一个语言结构,而不是一个函数,如果你尝试使用错误抑制运算符...

@unset($var);

... 你会得到这个:解析错误:语法错误,意外的 'unset' (T_UNSET) ...
To Top