第4章 变量和常量
变量和常量是计算机编程中的一个重要概念,变量或常量可以理解为,是程序给一些数据取的名字。编程时,因为一些数据随着程序的运行而改变,所以不能直接使用这些数据,需要用变量来存储,例如一个篮子里面放了5个苹果,每天吃一个,那么篮子里面的苹果每天都会减少,这就不能直接使用5,而需要给这个数据取个名字,这样数据变化时,不需要重新修改程序。常量和变量不同的地方是,常量在程序运行过程中不能改变其值,而变量可以在程序运行过程中不断改变其值。
简而言之,编程使用变量和常量来表示程序所需的任何信息。
4.1 从类型到变量
在PHP中,变量的类型是可以任意转换的,变量定义时不需要明确的类型定义。变量类型是根据使用该变量的上下文所决定的。也就是说,如果把一个字符串值赋给变量var,那么var就成了一个字符串。如果又把一个整型值赋给var,那var就成了一个整数。
当然,这也不是绝对的,PHP有两种类型转换方式可改变变量的类型,一种是自动转换,一种是强制转换。首先看一下自动类型转换,运行Zend Studio,打开项目php,新建文件“type_juggling.php”,并输入代码4-1。
代码4-1 自动类型转换例子
<?php $foo = "0"; $foo += 2; $foo = $foo + 1.3; $foo = 5 + "10 Little Piggies"; $foo = 5 + "10 Small Pigs"; ?>
保存代码,按“F5”键运行,结果如图4.1所示。
代码分析:第3行定义变量$foo,并赋值0(零),并用双引号括起来,恐怕很多人会认为输出结果中此变量应该是整型,但实际结果却是string(字符串),这是因为给一个变量赋值时,如果用引号括起来,PHP会认为这是赋的字符串值,此变量的类型也就是字符串型了。第6行变量$foo自身加2,这里的2没有引号,结果显示变量$foo的类型为int(整型),值为2,这说明当整型和字符串做相加运算后,结果为整型。第9行同理,浮点型和字符串做相加运算后,结果为浮点型。第12行比较特殊,结果为整数15,这是因为当一个字符串被当做数字来求值时,该值由字符串最前面的部分决定,如果字符串以合法的数字开始,则用该数字作为其值,否则其值为0(零),合法数字由可选的正负号开始,后面跟着一个或多个数字(包括十进制数),后面跟着可选的指数,指数是一个“e”或者“E”后面跟着一个或多个数字,本行的字符串以10开头,就将10作为其值与整数5相加,所以结果为15。另外,如果此字符串包括“.”,“e”或“E”任何一个字符,字符串被当做float来求值,反之被当做整型。
图4.1 自动类型转换
再看强制转换,新建文件“type_casting.php”,并输入代码4-2。
代码4-2 强制转换例子
<?php $foo = 10; var_dump($foo); $bar = (boolean) $foo; var_dump($bar); ?>
保存代码,按“F5”键运行,结果如图4.2所示。
图4.2 强制类型转换
代码分析:第3行定义变量$foo,并赋值,第4行打印变量$foo的类型为int(整型),值为10,第6行定义变量$bar,并将变量$foo强制转换成布尔型的值赋予$bar,打印结果为变量$bar的类型为布尔型,值为真。
PHP的强制转换类型,是在要转换的变量之前加上用括号括起来的目标类型。允许的强制转换有:
- (int),(integer):转换成整型。
- (bool),(boolean):转换成布尔型。
- (float),(double),(real);转换成浮点型。
- (string)- 转换成字符串。
- (array)- 转换成数组。
- (object)- 转换成对象。
4.2 变量的命名
PHP中的变量用一个美元符号后面跟变量名来表示,且变量名区分大小写。变量名与PHP中其他标识符遵循相同规则。一个有效的变量名由字母或者下画线开头,后面跟上任意数量的字母、数字或者下画线。下面是一个有效变量名的演示,运行Zend Studio,打开项目php,新建文件“var.php”,并输入代码4-3。
代码4-3 有效变量名例子
<?php $var = 'fool'; $var1 = 'kaka'; $_var2 = 'is'; $龙洋 = 'longyang'; var_dump($var, $var1, $_var2, $龙洋); ?>
保存代码,按“F5”键运行,结果显示如图4.3所示。
图4.3 变量命名
结果运行正常,说明变量命名正确。
4.3 可变变量
可变变量是指一个变量的变量名可以动态地设置和使用。一个可变变量获取了一个普通变量的值作为其变量名,这个变量就叫可变变量。
下面是可变变量的演示。运行Zend Studio,打开项目php,新建文件“var_var.php”,并输入代码4-4。
代码4-4 可变变量例子
<?php $a = 'hello'; $$a = 'world'; var_dump($$a); echo "$$a"; ?>
保存代码,按“F5”键运行,结果如图4.4所示。
图4.4 可变变量
代码分析:第3行定义变量$a,并赋值为“hello”,第4行定义变量$$a,并赋值为“world”,因为第3行已经给变量$a赋值为“hello”,所以可变变量$$a的值是$hello。
注意 在PHP的函数和类的方法中,超全局变量不能用做可变变量。
4.4 预定义变量
预定义变量是指PHP预先定义好的变量,不需要赋值,就可直接用。用Zend Studio做一个演示,运行Zend Studio,打开项目php,新建文件“predefined_var.php”,并输入以下代码4-5。
代码4-5 预定义变量例子
<?php var_dump($_COOKIE, $_ENV, $_FILES, $_GET, $GLOBALS, $_POST, $_REQUEST, $_SERVER, $_SESSION); ?>
保存代码,按“F5”键运行,Debug Output区域输出结果如图4.5所示。
图4.5 预定义变量
以上代码中所列的变量就是PHP的预定义变量,分别解释如下。
- $_SERVER:服务器变量,包含头信息(header)、路径(path)和脚本位置等组成的数组。
- $_ENV:环境变量,包含操作系统类型、软件版本等信息组成的数组。
- $_COOKIE:HTTP Cookies变量,通过 HTTP cookies 传递的变量组成的数组。
- $_GET:HTTP GET变量,通过 HTTP GET 方法传递的变量组成的数组。
- $_POST:HTTP POST变量,通过 HTTP POST 方法传递的已上传文件项目组成的数组。
- $_FILES:HTTP 文件上传变量,通过 HTTP POST 方法传递的已上传文件项目组成的数组。
- $_REQUEST:Request变量,此关联数组包含 $_GET、$_POST和$_COOKIE 中的全部内容。
- $_SESSION:Session变量,包含当前脚本中 session 变量的数组。
- $GLOBALS:全局变量,由所有已定义全局变量组成的数组。
注意 预定义变量的变量名就是所在数组的索引。其值会因系统环境的不同而不同,甚至可能不存在。数组将在后面的章节中学习,在这里可以把数组理解为一组数据的集合。
4.5 外部变量
在1.2.6节中学习了用HTML创建表单,当一个表单体交给 PHP 脚本时,表单中的信息会自动在PHP脚本中可用,这是PHP的外部变量之一。
以下是外部变量的演示。运行Zend Studio,打开项目php,新建文件“outside_var.php”,并输入代码4-6。
代码4-6 外部变量例子
<?php var_dump($_POST['username']); var_dump($_REQUEST['username']); var_dump($_POST['email']); var_dump($_REQUEST['email']); ?> <form action="outside_var.php" method="POST"> 你的名字: <input type="text" name="username"><br /> 你的邮件: <input type="text" name="email"><br /> <input type="submit" name="submit" value="提交" /> </form>
保存代码,然后单击Zend Studio编辑器区域的“Browser”按钮,并在地址栏输入地址“http://localhost/lesson1/outside_var.php”,按“Enter”键,结果如图4.6所示。
图4.6 表单外部变量
在“你的名字”文本框中输入自己的名字,在“你的邮件”文本框中输入自己的电子邮件,单击“提交”按钮,结果如图4.7所示。
图4.7 表单提交结果
代码分析:第3、4、5、6行代码分别打印了4个未定义的变量,PHP代码后面是HTML创建的表单,表单名分别为“name”和“email”,单击“提交”按钮,服务器接受到表单传来的值后,自动转换为PHP预定义变量$_POST的数组元素,要访问这些元素,直接把表单的字段名当成$_POST数组的索引就可以了,所以代码里面可以看到,打印的$_POST[‘name’]结果是表单字段名为“name”的文本框“你的名字”中输入的值。
除了表单提交的外部变量外,HTTP Cookies也是外部变量,Cookies 处理将在后面的章节中详细介绍,这里不做说明。
4.6 引用
对于“引用”,PHP手册比喻为UNIX系统的文件名和文件本身,即变量名是目录条目,而变量内容则是文件本身。引用可以被看做UNIX系统文件系统中的hardlink。如果这个比喻不好理解,那么可以比喻为,Windows系统的快捷方式和文件本身。
举一个例子,运行Zend Studio,打开项目php,新建文件“references.php”,并输入代码4-7。
代码4-7 引用例子
<?php $a = 'abc'; $b =& $a; $c = $a; var_dump($a, $b, $c); $a = 'def'; var_dump($a, $b, $c); ?>
保存代码,按“F5”键运行,结果如图4.8所示。
图4.8 引用
代码分析:第3行定义变量$a,并赋值abc,第4行定义变量$b,并赋值为$a,第5行定义变量$c,并引用赋值为$a。这里可以看到,变量引用就是在被引用变量前面加“&”符号。第7行打印3个变量的值,输出结果全部为“abc”,可见3个变量都是一样的。关键的第8行做了一个改动,将变量$a的值从“abc”改为了“def”,第9行再次打印3个变量的时候发生了意想不到的事情,变量$a输出“def”肯定没问题,变量$b输出“abc”也没问题,因为变量$b在第4行的时候被赋值为当时变量$a的内容,然后就一直没有改变其值,显然结果为“abc”,奇怪的是变量$c也没有改变其值,输出结果却是和重新赋值的变量$a内容一样,这就是引用的作用,好比快捷方式和快捷方式所指向的文件,变量$c就是变量$a的快捷方式,如果变量$a的值发生改变,那么变量$c也会跟着改变,而变量$b是变量$a的拷贝,也就是说$a已经复制了一份,这样即使变量$a的值发生改变,也不会影响到变量$b。
引用的好处是节约系统内存资源,这点和建立文件的快捷方式一样,比如人们使用计算机的时候,喜欢在桌面上建立快捷方式,而不需要复制文件到桌面上,快捷方式不会占用磁盘空间。
4.7 变量的销毁
在PHP中,变量通常不需要专门销毁,系统会自动释放,但对于性能要求高的系统来说,系统自动释放太慢,达不到高性能的要求,这就要求编写代码时要及时销毁一些变量,通常是销毁一些包含大量数据的变量。
通常,销毁一个变量有两种方法:一种是重新赋值,一种是使用函数unset()。下面是一个例子,运行Zend Studio,打开项目php,新建文件“unset_var.php”,并输入以下代码4-8。
代码4-8 变量的销毁例子
<?php $a = 'abc'; $a = NULL; $b = 'def'; unset($b); var_dump($a, $b); ?>
保存代码,按“F5”键运行,结果如图4.9所示。
图4.9 销毁变量
代码分析:第3行定义变量$a,并赋值“abc”,第4行重新给变量赋值为NULL(在类型中已经说到,NULL就是没有,如果忘了可以复习第3章),这样就销毁了变量$a,第5行定义变量$b,并赋值为“def”,第6行使用unset()函数销毁变量$b,第8行打印变量$a和变量$b,结果都为NULL,这说明变量已经被销毁。
4.8 常量
常量在程序运行期间不改变其值,并且常量是全局的,定义了一个常量,不用管作用域就可以在脚本的任何地方访问常量。
4.8.1 常量的定义
常量是使用define()函数来定义的,且一个常量一旦被定义,就不能再改变或者取消定义。常量名和其他任何 PHP 标签遵循同样的命名规则。合法的常量名以字母或下画线开始(常量没有美元符号),后面跟着任何字母、数字或下画线,且按惯例来说常量名全部用大写字母。常量数据包含布尔型、整型、浮点型和字符串,不能定义资源类型的常量。
常量和变量的区别有以下几点。
- 常量前面没有美元符号($)。
- 常量只能用 define()函数定义,而不能通过赋值语句。
- 常量可以不用理会变量范围的规则而在任何地方定义和访问。
- 常量一旦定义就不能被重新定义或者取消定义。
- 常量的值只能是标量。
下面是一个定义常量的例子,运行Zend Studio,打开项目php,新建文件“constant.php”,并输入以下代码4-9。
代码4-9 定义常量例子
<?php define("CONSTANT", "Hello world"); var_dump(CONSTANT, Constant); ?>
保存代码,按“F5”键运行,结果如图4.10所示。
图4.10 定义常量
代码分析:第3行定义常量CONSTANT,值为“Hello world”,第4行打印了一个CONSTANT和一个Constant来区别大小写,结果是CONSTANT打印值是正确的,而Constant的值是其本身。
4.8.2 魔术常量
在学习魔术常量前,先对PHP的预定义常量做一个说明。PHP除了有预定义变量,还有比预定义变量更多的预定义常量。这些预定义常量很多都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了。
PHP有5个魔术常量根据其使用的位置而改变。例如__LINE__的值就由其在脚本中所处的行来决定。这些特殊的常量不区分大小写,如表4.1所示。
表4.1 魔术常量
4.9 典型实例
【实例4-1】在PHP中,两个不同类型的变量参与同一个运算时,PHP会根据上下文自动处理变量的类型。但在一些需要精确运算结果的情况下,提前对变量进行类型转换,可以避免一些程序上的逻辑错误。
本实例代码主要演示了变量类型转换的相关操作、代码中使用到的函数,使用方法如下所示。
- 设置变量类型使用settype()函数,其参数有两个,第一个参数是要设置变量类型的变量名;第二个参数是要设置变量类型,其值包括boolean(或为bool)、integer(或为int)、float、string、array、object、NULL。
- 获取变量类型使用gettype()函数,其参数是变量名,函数将根据变量的类型,返回一个字符串,这个字符串的值包括boolean、integer、double(如果变量类型为float则返回double,而不是float)、string、array、object、resource、NULL、unknown type。
- 可变变量用于类型转换。
代码4-10 变量类型转换
<?php /*************************设置变量************************************/ $varint = 1; //设置一个名为$varint的整型变量 $varinteger = "4"; //设置一个名为$varinteger的字符串变量 $varstring = "小明"; //设置一个名为$varstring的字符串变量 $varbool = true; //设置一个名为$varbool的布尔型变量 $varfloat = 12.5; //设置一个名为$varfloat的浮点型变量 $varobject = "will be an object";//设置一个名为$varobject的字符串变量 $show_1 = "show_2"; $$show_1 = true; $show_3 = NULL; /** * 设置一个名为$varsarray的数组变量 * */ $varsarray = array( "1"=>"one", "2"=>"two" ); /** * 设置一个名为$vardarray的多维数组变量 * */ $vardarray = array( "cn"=>array("1"=>"一","2"=>"二"), "en"=>array("1"=>"one","2"=>"two") ); echo "使用gettype()函数,查看变量转换前的类型<br>"; echo gettype($varobject)."<br>"; echo gettype($varinteger)."<br>"; echo gettype($varsarray)."<br>"; echo gettype($varint)."<br>"; echo gettype($vardarray)."<br>"; echo gettype($show_3)."<br>"; /*************************变量类型转换************************************/ settype($varobject,"object"); //使用settype()函数,把$varobject的类型转换为对象类型 $varinteger = (int)$varinteger; //强制类型转换,把$varinteger的类型转换为整型 $varsarray = (object)$varsarray; //强制类型转换,把$varsarray转换为对象类型 $varint = "$varint"; //根据字符串定义的方法,把$varint转换为字符串型 $vardarray = (int)$vardarray; //强制类型转换,把$vardarray转换为整型 /*************************可变变量用于变量类型转换************************************/ $show_3 = $$show_1; /*************************查看变量类型************************************/ echo "<br>使用gettype()函数,查看变量转换后的类型<br>"; echo gettype($varobject)."<br>"; echo gettype($varinteger)."<br>"; echo gettype($varsarray)."<br>"; echo gettype($varint)."<br>"; echo gettype($vardarray)."<br>"; echo gettype($show_3); ?>
运行该程序后,运行结果如图4.11所示。
图4.11 程序运行结果
【实例4-2】在了解了变量的定义与使用方法后,本实例将演示变量的作用范围。了解变量的作用范围,可以帮助程序员更好地理解程序的逻辑结构。
本实例代码主要演示了变量的作用范围,在演示过程中,需要注意以下5点。
- 包含文件变量的作用范围。
- 函数中变量的作用范围。
- 关键字GLOBAL对于变量作用范围的影响。
- 预定义变量的作用范围。
- 静态变量的作用范围。
代码4-11 变量的作用范围
<?php //定义变量 $var_1 = "变量1"; $var_2 = "user"; $var_3 = "play"; //定义一个函数 function show_a(){ $var_inner = "函数定义的变量"; //显示函数访问外部变量错误的例子 echo "访问内部变量:".$var_inner."<br>"; //显示函数访问外部变量错误的例子 } //显示函数访问外部变量正确的方法 function show_b(){ global $var_2; //使用global获取访问函数外部变量 echo "访问全局变量:".$var_2.$GLOBALS["var_3"]."<br>"; } //预定义变量 function show_c(){ echo "访问全局预定义变量:".$_ENV["OS"]."<br>"; //在字符串中直接使用预定义变量 } //静态变量演示 function show_d() { static $a = 0; //定义一个静态变量 echo "静态变量演示:".$a."<br>"; //显示变量好的静态变量 $a++; //给静态变量的值加1 } //运行演示函数 show_a(); show_b(); show_c(); show_d(); //运行包含静态变量的函数,得出结果为0 show_d(); //再次运行包含静态变量的函数,得出结果为1 ?>
运行该程序后,运行结果如图4.12所示。
图4.12 程序运行结果
函数show_a()只能访问其内部定义的变量$var_inner,要想访问页面内定义的变量,可以使用“global”关键字,或使用预定义量$GLOBALS,如函数show_b()所示。
【实例4-3】在PHP中,还提供了几个内置变量,如服务器变量$_SERVER。服务器变量是由网络服务器创建的数组,其内容包括头信息、路径、脚本位置等。不同的网络服务器提供的信息有所不同,本书以Apache服务器作为标准。
在程序中可以通过“$_SERVER”,即服务器变量,来访问服务器的相关信息。在实际应用中,可以对这个数组进行遍历,也可以单独使用其中的数组单元。
代码4-12 服务器变量
<?php echo "显示脚本文件的相对路径和文件名:\"".$_SERVER["PHP_SELF"]."\"<br>"; echo "显示服务器使用的CGI脚本规范:\"".$_SERVER["GATEWAY_INTERFACE"]."\"<br>"; echo "显示当前运行脚本所在服务器的IP地址:\"".$_SERVER["SERVER_ADDR"]."\"<br>"; echo "显示当前运行脚本服务器名称:\"".$_SERVER["SERVER_NAME"]."\"<br>"; echo "显示当前运行脚本服务器标识:\"".$_SERVER["SERVER_SOFTWARE"]."\"<br>"; echo "显示请求页面的通信协议的名称和版本:\"".$_SERVER["SERVER_PROTOCOL"]."\"<br>"; echo "显示访问页面的请求方法:\"".$_SERVER["REQUEST_METHOD"]."\"<br>"; echo "显示脚本开始运行时间:\"".$_SERVER["REQUEST_TIME"]."\"<br>"; echo "显示URL问号后的字符串:\"".$_SERVER["QUERY_STRING"]."\"<br>"; echo "显示当前运行脚本的文档根目录:\"".$_SERVER["DOCUMENT_ROOT"]."\"<br>"; echo "显示当前Accept请求的头信息:\"".$_SERVER["HTTP_ACCEPT"]."\"<br>"; echo "显示当前请求的字符信息:\"".$_SERVER["HTTP_ACCEPT_CHARSET"]."\"<br>"; echo "显示当前请求的Accept-Encoding头信息:\"".$_SERVER["HTTP_ACCEPT_ENCODING"]."\"<br>"; echo "显示当前请求的Accept-Language头信息:\"".$_SERVER["HTTP_ACCEPT_LANGUAGE"]."\"<br>"; echo "显示当前请求的Connection头信息:\"".$_SERVER["HTTP_CONNECTION"]."\"<br>"; echo "显示当前请求的Host头信息:\"".$_SERVER["HTTP_HOST"]."\"<br>"; echo "显示当前页面的前一个页面的URL地址:\"".$_SERVER["HTTP_REFERER"]."\"<br>"; echo "显示当前请求的User-Agent头信息:\"".$_SERVER["HTTP_USER_AGENT"]."\"<br>"; echo "显示脚本是否可以通过HTTPS协议进行访问:\"".$_SERVER["HTTPS"]."\"<br>"; echo "显示浏览当前页面用户的IP地址:\"".$_SERVER["REMOTE_ADDR"]."\"<br>"; echo "显示浏览当前页面用户的主机名:\"".$_SERVER["REMOTE_HOST"]."\"<br>"; echo "显示用户连接到服务器时所使用的端口:\"".$_SERVER["REMOTE_PORT"]."\"<br>"; echo "显示当前执行脚本的绝对路径名:\"".$_SERVER["SCRIPT_FILENAME"]."\"<br>"; echo "显示Apache配置文件中的SERVER_ADMIN参数设置情况:\"".$_SERVER["SERVER_ADMIN"]."\"<br>"; echo "显示网络服务器使用的端口,默认为\"80\":\"".$_SERVER["SERVER_PORT"]."\"<br>"; echo "显示服务器版本和虚拟主机名的字符串:\"".$_SERVER["SERVER_SIGNATURE"]."\"<br>"; echo "显示脚本在文件系统中的基本路径:\"".$_SERVER["PATH_TRANSLATED"]."\"<br>"; echo "显示当前脚本的路径:\"".$_SERVER["SCRIPT_NAME"]."\"<br>"; echo "显示访问当前页面的URI:\"".$_SERVER["REQUEST_URI"]."\"<br>"; ?>
运行该程序后,运行结果如图4.13所示。
图4.13 程序运行结果
与服务器变量$_SERVER类似,PHP还提供了$_ENV、$_COOKIE、$_GET、$_POST、$_REQUEST、$_FILES、$_SESSION、$GLOBALS 等预定义变量,其使用方法与服务器变量$_SERVER类似。
4.10 小结
本章的内容非常简单,从概念上来说,只介绍了常量和变量,但它们确实是最基础的PHP语法,如果连什么是变量什么是常量都分不清楚,那么对于后面的大段大段的代码,读者根本就理不清思路,不知道数值到底计算结果如何。本章是PHP学习的基础,读者一定要仔细阅读并掌握。
4.11 习题
一、填空题
1. 变量必须以_____符号开头,第二个字符必须是_____或_____。
2. 销毁一个变量有两种方法:一种是_____,一种是_____。
二、选择题
1. 下面程序的运行结果是( )。
<?php $a=5; $b=3; echo $a/$b%$b."<br>"; ?>
A. 1
B. 0
C. 1.7
D. 无输出