PHP 变量

本文最后更新于:2024年3月18日 凌晨

PHP 变量

概述

  • PHP的变量是指用一个美元符号$作为前缀的标识符,例如:
1
2
3
4
$name
$Age
$_debugging
$MAXIMUM_IMPACT
  • 变量可以存放任意类型的值,在编译或运行时没有变量的类型检查,可以用其他不同类型的值替换一个变量的值。
1
2
3
$what = "Fred";
$what = 35;
$what = array('Fred','35','wilma');
  • 在PHP中不需要用显示的语法来声明变量,变量第一次被赋值时,变量就被创建了,换句话说,设置变量的值也有声明变量的功能,例如,下面在PHP程序中是完全合法的。
1
2
3
$day = 60*60?*24;
echo "There are $day second in a day.\n";
There are 86400 seconds in a day
  • 一个变量没有被设置值,则其值即为NULL:
1
2
3
4
if($uninitialized_varablr == NULL){
Echo "Yes!";
}
Yes!

可变变量

  • 可以引用名字存放在另外一个变量里的变量的值,例如:
1
2
$foo = 'bar';
$$foo = 'baz';
  • 在第二条语句执行后,变量$bar的值为"baz"

变量引用

  • 在PHP里,引用就是如何创建变量的别名,$black作为变量$white的别名,可以使用下面的方法:
1
$black =  & $white
  • 赋值之后,$black的旧值丢失了,取而代之的是,​$black此时成为存放在$white中的值的另一个名字:
1
2
3
4
5
6
7
8
$big_long_variable_name = "PHP";
$short = & $big_long_variable_name;
$big_long_variable_name = " rocks!";

print "$short is $short\n";
print "Long is $big_long_variable_name\n";
$short is PHP rocks!
Long is PHP rocks!
  • 在赋值之后,两个变量是同一个值的不同名字,销毁其中一个变量,不会影响到另一个变量的值,如:
1
2
3
4
5
$white = "snow";
$black = & $white;
unset($white);
Print $black;
snow
  • 函数可以通过引用返回值。
1
2
3
4
5
function &ret_ref() {// 注意&
$var = "PHP";
return $var;
}
$v = &ret_ref();// 注意&

变量作用域

  • 由变量声明的位置控制的变量作用域(scope),决定程序的哪些部分可以访问变量,在PHP中由4种类型的变量作用域:局部作用域,全局作用域,静态变量和函数参数。

局部作用域

  • 在一个函数中声明的变量就是那个函数的局部变量,也就是说,它只在该函数的代码中可见(包括嵌套函数定义);在函数外面是不可访问的,另外,定义在函数外的变量(称为全局变量)在函数中默认不可访问,例如,下面的函数更新了一个局部变量而不是全局变量:
1
2
3
4
5
6
7
function update_counter() {
$counter++;
}
$counter = 10;
update_counter();
echo $counter;
10
  • 因为没有其他的声明,在函数里的$counter是那个函数的局部变量,函数增加局部变量​$counter的值,在子程序结束时$counter的值被丢弃,全局变量$counter的值依然为10
  • 只有函数能提供局部作用域,和其他语言不一样的是,在PHP里不可以创建一个作用域是循环,条件分支或其他块类型的变量。

全局作用域

  • 在函数外声明的变量就是全局的变量,它们可以在程序的任何部分被访问,然而,默认不能再函数中访问全局变量,要让一个函数可以访问全局变量,可以再函数中使用关键字global来声明在函数中,这里将重写update_counter()函数来使它可以访问全局变量$counter
1
2
3
4
5
6
7
function update_counter() {
Global $counter++;
}
$counter = 10;
update_counter();
echo $counter;
11
  • 另一个略显笨拙的办法是使用PHP的$GLOBALS数组来更新全局变量,而不是直接访问变量:
1
2
3
4
5
6
7
function update_counter() {
$GLOBALS["counter"]++;
}
$counter = 10;
update_counter();
echo $counter;
11

静态变量

  • 静态变量仅在局部函数中存在,但当程序执行离开此作用域时,其值并不丢失,下一次调用函数时,上次执行得到的结果仍然得以保留,可以使用关键字static来声明一个静态变量,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
function update_counter() {
static $counter = 0;
$counter++;
Echo "Static counter is now $counter\n";
}
$counter = 10;
update_counter();
updata_counter();
echo "Global counter is $counter\n;

Static counter is now 1
Static counter is now 2
Global counter is 10

函数参数

  • 函数定义可以有已命名的参数:
1
2
3
4
5
function greet ($name) {
echo "Hello,$name\n";
}
greet("Janet");
Hello,Janet
  • 函数参数是局部的,意味着它们只能在它们的函数内有效,$name不能在greet()函数外被访问。

垃圾收集

  • PHP使用引用计数(reference counting)和写时复制(copy-on-write)来管理内存,写时复制保证了在变量间复制值时不浪费内存,引用计数保证了不在需要时将内存交还给操作系统。
  • 要理解PHP里的内存管理,首先要知道符号表(symbol table)的思想,一个变量有两部分–变量名(如$name)和变量值(如"Fred")符号表是一个将变量名映射到内存中变量值所在地址的数组。
  • 当从一个变量复制值到另一个变量时,PHP没有为复制值使用更多的内存,相反,它更新了符号表来说明"这两个变量都是同一内存块的名字",所以下面的代码实际上并没有创建一个新数组:
1
2
$worker = array("Fred",35,"Wilma");
$other = $worker;// 数组没有被复制。
  • 如果后来修改了任意一个人拷贝,PHP将分配所需的内存来产生复制:\
1
%worker[1] = 36;// 值改变时,数组被复制。
  • 通过延迟分配和复制,PHP在很多情形下节省了时间和内存,这就是写时复制。
  • 符号表指向的每一个值都有引用计数(reference counting),它的数值表示取得那块内存的途径数目,在将数组初值赋给$worker和将$worker赋给$other之后,符号表中指向数组条目($worker$other)的引用计数为2,换言之,那片内存有两种取得方式:
    • 通过$worker或​$other,但是在$worker[1]改变后,PHP为$worker创建了一个新的数组,并且每个数组的引用计数都只有1
    • 当一个变量离开作用域时(就像一个函数参数或局部变量到达函数结尾时),它的值的引用计数减去,当一个变量在其他内存空间被赋值时,旧值的引用计数加1每对一个值的引用计数到达0时,它的内存就会被释放,这就是引用计数。
  • 引用计数是管理内存的较好方式,保持变量作用域限制于函数中,通过值来传递,并让引用计数来管理内存,如果你想要主要获得更多的信息和控制权来释放变量的值,可以使用isset()unset()函数。
  • 查看一个变量是否被设置甚至是空字符串,使用isset():
1
2
3
$s1 = isset($name);//$s1是false
$name = "Fred";
$s2 = isset($name);// 是true
  • 使用unset()来移除一个变量的值:
1
2
$name = "Fred";// 值为NULL
unset($name);

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!