• 1. 第1章 相关知识欢迎加入PHP的学习行列,希望通过本书的学习,能使读者对PHP有大概的了解,并运行该语言进行网站和软件的开发。 PHP作为一种服务器端脚本语言,在开发动态网站,编写网络软件等方面被广泛应用。特别是近几年,PHP的版本不断升级,使PHP语言的处理能力有了很大的提升。这为将来,PHP能处理更多的系统事务奠定了基础。在学习PHP语言之前,先了解相关的术语,以便于以后的学习。
  • 2. 1.1 PHP及相关术语在阅读技术文档和相关学习资料时遇到专业术语,是学习编程语言时最困难的地方之一,在不了解相关专业术语的前提下,学习成了一件痛苦的事情。 为了能顺利的阅读PHP学习资料和技术文档,现列举常用的与PHP有关的专业术语供读者参考。
  • 3. 1.1.1 软件系统相关术语术语是了解一门语言和语言开发环境的基础,本节就介绍PHP中常碰到的环境术语。 (1)软件开发环境(SDE) (2)什么是LAMP、WAMP? (3)什么是Apache? (4)什么是MySQL? (5)Eclipse (6)什么是SSL? (7)什么是模式? (8)什么是框架? (9)什么是MVC? (10)什么是模版? (11)什么是面向过程方法? (12)什么是面向对象方法? (13)什么是Socket?
  • 4. 1.1.2 PHP语言相关术语PHP不光是一门语言,慢慢扩展成为一种行业,本节介绍这门语言涉及的一些行业用语和技术词汇。 (1)什么是PHP? PHP是Hypertext Preprocessor两个英文单词的缩写,是基于服务器端运行的脚本程序语言,其可以实现数据库和网页之间的数据交互。PHP的独特语法混合了C、Java、PERL和PHP式的新语法。 PHP语言可以单独运行,也可以镶嵌在HTML文件中,这样程序员就可以不必完全依赖HTML生成网页。因为PHP语言的执行都在服务器端,所以客户端是看不到PHP代码的。 (2)什么是PHPer? PHP programmer,指编写PHP的程序员。 (3)什么是类? 类是对某个对象的定义。它包含有关对象动作方式的信息,包括它的名称、方法、属性和事件。实际上它本身并不是对象,因为它不存在于内存中。当引用类的代码运行时,类的一个新的实例,即对象,就在内存中创建了。虽然只有一个类,但能从这个类在内存中创建多个相同类型的对象
  • 5. 1.1.2 PHP语言相关术语(4)什么是对象? 对象就是类存在于内存中的实例,通过对类进行实例化,就能得到对应的对象。 (5)什么是函数? 函数是一段相对独立的代码,不同的语言有不同的定义方式。在PHP中,函数就是有效的PHP代码的集合。在设计复杂程序时,可以把程序分为几个函数,不同的函数完成不同的功能。其优点在于各部分充分独立,不仅可以使程序易读、易维护,还可以对代码进行复用。 (6)什么是Session? Session用中文来解释就是会话期。一个会话期开始于用户输入一个站点的网址时,结束于离开这个站点时。PHP使用Session函数来创建和管理会话期内“$_SESSION”中的变量。
  • 6. 1.1.2 PHP语言相关术语(7)什么是Cookie? Cookie是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。在PHP中可以用 setcookie()函数来设置Cookie。Cookie是HTTP标头的一部分,因此setcookie()函数必须在其他信息被输出到浏览器前调用,这和对header()和SESSION函数的限制类似。可以使用输出缓冲函数来延迟脚本的输出,直到按需要设置好了所有的Cookie或者其他HTTP标头。 (8)什么是PEAR? PEAR是PHP的扩展和库代码的知识库,而这个项目最有雄心的目标则是试图定义一种标准,这种标准将帮助开发者编写可移植、可重用的代码。 (9)什么是Pecl? Pecl 是通过PEAR打包后,取得的PHP扩展库。
  • 7. 1.1.2 PHP语言相关术语(10)什么是变量? PHP 中的变量用一个美元符号后面跟变量名来表示,数据存储的内存地址。在PHP中变量名是区分大小写的。 (11)什么是常量? 常量,即不可变的数值或数据项。常量的值通常是在程序运行前定义的,在整个程序运行的过程中,其值是不会改变得。常量默认为大小写敏感。按照惯例常量标识符总是大写的。 (12)什么是引用? 在PHP中引用就是用不同的名字访问同一个变量内容。变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。 (13)什么是序列化? 序列化就是将对象的状态信息转换为可以存储、传输的数据的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。再次使用时,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。序列化只保存了对象的成员数据而不包话方法。
  • 8. 1.1.2 PHP语言相关术语(14)什么是构造函数? 构造函数是类中的一个特殊函数,当使用new操作符创建一个类的实例时,构造函数将会自动调用。在PHP5以前的版本中,当函数与类同名时,这个函数将成为构造函数。PHP5通过定义“__construct”函数来建立构造函数。如果一个类没有构造函数,则调用基类的构造函数,如果有刚调用当前类构造函数。 (15)什么是析构函数? PHP5引入了析构函数的概念,通过定义“__destruct”函数来建立析构函数。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。 专业术语的记忆有助手对新语言的学习,特别在遇到阅读技术文档时,能理解文档里大量的专业术语,不仅能加快学习的进度,也能更准确的理解原文的意思。可以少走很多弯路。 本节介绍的仅限于常用的术语,在PHP语言学习的过程中,应该多注意对PHP专业术语和其他通用专业术语的学习和集累。
  • 9. 1.2 PHP的运行及开发环境在上一节中,提到了几个术语,即:SDE、LAMP、WAMP和Eclipse。SDE,即软件开发环境,它由软件运行环境和软件开发工具两部分组成。LAMP和WAMP都是软件的运行环境;Eclipse是本书使用到的开发工具。
  • 10. 1.2.1 运行环境LAMP是指一组常用来搭建动态网站或者网络服务器的软件。这组软件中包括Linux系统、网络服务器APACHE、关系型数据库MySQL和PHP或其他语言插件。 LAMP之所以这么倍受推崇,是因为这个组合使用到的软件都是开源软件,而且它们之间的兼容性越来越高。随着开源软件的发展,LAMP已经与J2EE及.NET形成三足鼎立之势。 LAMP的自家兄弟WAMP因为微软的Windows系统被广泛使用而名声在外。在Windows系统中,常常使用的网络服务器IIS,也可以用于构建PHP的运行环境。
  • 11. 1.2.2 运行平台的选择这里指的运行平台就是LAMP/WAMP中的L或W,即:Linux和Windows操作系统。选择不同的平台会真接影响到软件开发中使用的工具,以及运行环境中其他软件的安装及配置。 在大型的网站开发过程中,往往选择LAMP的组合,其优点不仅仅在于是开源软件和兼容性,在稳定性和安全性方面也有很好的表现。但是在平台建设和维护方面的工具量相对也是很多的,这也是其缺点之一。 WAMP作为一种可选择的方案,其较短的部署时间,成为新手入门的首先。而且网络上不断推出的免配置版的WAMP更可以让程序员从复杂的环境配置中解脱出来,专心于程序的开发。本书作为PHP入门教材,将选择使用WAMP组合。 运行环境的构建将是跨入PHP世界的重要一步。值得庆幸的是走出这一步并不难。免安装、免配置版的WAMP已经发展了很多版本,读者可以很容易的从互联网上取得。下面的三个章节将重点讲解如何在已经拥有Windows系统的电脑上安装Apache、MySQL和PHP。
  • 12. 1.2.3 Apache对客户端与服务器端通信的作用本书1.1章节的中对Apache进行了名词性的解释,但读者对其在整个开发环境中,能起到的作用还不是很了解。下边列出的是一个简单的客户端与服务器通讯的步骤: (1)客户端(浏览器)和网络服务器建立TCP连接,连接建立以后,向网络服务器发出访问请求(如Get请求)。根据HTTP协议,该请求中包含了客户端的IP地址、浏览器的类型和请求的URL等一系列信息。 (2)网络服务器收到请求后,将客户端要求的页面内容返回到客户端。如果出现错误,那么返回错误代码。 (3)断开与远端Web服务器的连接。 上面的步骤中提到的网络服务器,就是一台安装有Apache的电脑主机。负责处理客户端请求的数据,并返回客户请求的内容,这就是Apache的作用。
  • 13. 1.2.4 准备工作从本节开始,学习建立一台实现上述功能的主机。 (1)一台已经安装了Windows XP/2000/2003系统的电脑。(关于Windows 的安装过程,请参照其他书籍)。本书使用是Windows XP系统。 (2)登录Apache官方网站http://www.apache.org/,下载最新版本的安装程序,本书中使用的是Apache 2.2.6 Released,详细下载地址:http://apache.mirror.phpchina.com/httpd/binaries/win32/apache_ 2.2.6-win32-x86-openssl-0.9.8e.msi。
  • 14. 1.2.5 安装Apache安装Web服务器是实现通信功能的关键,本节详细介绍如何安装Apache。
  • 15. 1.2.6 确认Apache安装成功确认Apache安装成功有很多方法,了解和掌握它们,会对网络服务器维护有很大的帮助,下边举例说明常用的两种方法。 1.使用Apache自带的管理软件 2.使用浏览器
  • 16. 1.2.7 PHP安装准备在最初的PHP安装时,都会使用手工配置,但随着PHP的发展,PHP版本也提供了安装版,而且相对于Apache和MySQL的安装来说,PHP的安装简单的多。按照下边的步骤执行,将会为Apache添加PHP的语言支持。下面是安装前的准备工作。 (1)登录PHP的官方网站http://www.php.net/,下载最新版的PHP语言安装文件,本书使用的是PHP 5.2.4,详细下载地址:http://cn2.php.net/get/php-5.2.4-win32-installer.msi/from/cn.php.net/mirror (2)PHP官方网站提供了适用于不同操作系统的文件,在下载时请注意选择正确的操作系统。 (3)PHP分为安装版与非安装版两个版本,请选择需要的包进行下载,本书选择的是安装版。
  • 17. 1.2.8 安装PHP安装PHP的详细步骤如下所示。
  • 18. 1.2.9 确认PHP安装成功右击“ApacheMonitor”图标,弹出ApacheMonitor菜单,单击“Open Apache Monitor”菜单项,进入Apache服务管理器,在对话框中单击“Stop”按钮,等待Apache服务关闭后,再单击“Start”按钮启动Apache服务,成功后Apache服务管理器的状态栏会显示:Apache/2.2.6 (Win32) PHP/5.2.4,如图所示。
  • 19. 1.2.10 Apache与PHP的相关配置为了让Apache支持PHP,PHP的安装配置更改了Apache的配置文件。Apache的主配置文件“httpd.conf”位于Apache的安装目录下的conf文件夹内,如图所示。 使用记事本程序打开“httpd.conf”,拖动滚动条至文件下方,会看到配置文件最下方有4行关于PHP的配置代码,如图所示。
  • 20. 1.2.11 开发工具开发工具是程序员使用最多的软件,它的选择与程序员的编程习惯和软件开发环境有关。最初的PHP是没有专门的开发工具的,但随着PHP的商业化运作和开源软件的发展,很多流行的IDE都添加了对PHP编码的支持,其中有Adobe公司的Dreamweaver和大名鼎鼎的Eclipse。 说到PHP的开发工具,就不能不提到Zend Studio,它是目前公认的最强大的PHP开发工具,这种集成软件包括了用于编辑,调试,配置PHP程序所需要的客户及服务器组件,具有工业标准的PHP开发环境,代码完成引擎和功能齐全的调试器。 EditPlus及其他流行的文本编辑工具都可以作为PHP的开发工具,但是在开发稍大一点的软件系统时,这些工具就会受到很多限制。但是体积小,运行快的这个特点在调试程序时,还是很实用的。如果只是想更改程序的一条代码,就要启动功能齐全的IDE,显然不合适,此时这类文本编辑软件就排上用场了。
  • 21. 1.2.12 Eclipse的下载、安装及配置在上边的章节中,讲述了PHP相关的开发工具,在综合了各种因素后,本书选择Eclipse作为主要开发工具。下边介绍Eclipse的安装与配置。 Eclipse的版本与插件版本之间的对应是有要求的,如果不兼容的版本之间对应,插件有可能不会启动。为了解决这个问题,Eclipse官方网站提供了语言开发环境的打包下载,即把Eclipse和语言开发插件打包在一起,省去复杂的配置过程。
  • 22. 1.3 第一个PHP程序在一切准备工作就绪后,就可以使用Eclipse编写PHP程序,并在Apache里发布并运行了。编写代码、发布、运行这一过程很简单,通过本节的学习,很快就会掌握。
  • 23. 1.3.1 使用Eclipse编写源程序编程语言的学习,不仅仅是对语言本身的熟悉,同时要对其周边的知识,如:开发工具、调试工具、运行环境配置等各个方面都进行了解,打下坚实的基础,才能更灵活、高效的运用这种语言工具。 通过对上面几个小节的学习,了解了PHP运行需要的环境和配置方法。在接下来的章节中,会详细介绍PHP的语法,函数,数据库等知识。在开始学习这些知识以前,先了解怎么样使用Eclipse新建PHP项目及编写PHP程序。
  • 24. 1.3.2 发布和运行PHP程序所谓的发布PHP程序,就是把已经编写完成的PHP代码文件复制到Apache指定的文档根目录下。Apache默认的文档根目录,就是其安装目录下的htdocs文件夹。为了方便读者发布程序,在运行Eclipse时,选择的工作空间就是这个文件夹。 在1.3.1章节中,Eclipse中新建的项目“learn”,等同的操作就是在htdocs文件夹下新建一个名为“learn”的文件夹。而新建文件hello.php,就是在learn文件夹下新建一个名为hello.php的PHP代码文件。这两个动作其实就是PHP程序的发布过程,动作完成后,hello.php已经发布到了Apache的文档根目录里的learn文件夹下。接下来,就是运行这个PHP文件。 运行PHP有三种方式:在命令行中运行,作为桌面程序运行,作为服务器端脚本运行。其中最经常使用的就是作为服务器端脚本运行方式。
  • 25. 1.4 常见问题第一章的内容主要是介绍了计算机与PHP语言的相关术语,PHP的运行环境的安装与配置及PHP开发工具的安装与简单使用。 在本章的几个知识点里,有几个问题应该特别说明一下。
  • 26. 1.4.1 Apache安装常见问题Apache为电脑提供网络服务,会以系统服务的形式存在,默认占用的80端口。如果在安装Apache以前,Windows安装了自带网络服务程序,即IIS或其他软件占用了80端口,Apache在安装完成后,网络服务是不会启动的。在遇到这种情况,有两种解决方法。 方法一:停止占用端口的软件 如果程序员的机器要运行ASP程序,很有可能安装了IIS,而同时又使用Apache布属PHP程序,那么后来安装的Apache是不能正常运行的。这种情况下可以通过停止IIS服务或改变IIS的服务端口来解决问题。 方法二:改变Apache的默认端口 为了不影响现有的程序运行,可能通过改变Apache的默认端口来解决问题。
  • 27. 1.4.2 MySQL安装常见问题MySQL安装时也会遇到端口冲突的问题,在默认端口3306被占用时,可以在安装里尝试使用其他端口进行安装,具体步骤参见1.2.4小节的第15步。
  • 28. 1.4.3 PHP安装常见的问题为了减少PHP安装过程中的错误,本书使用安装程序进行安装。在某些情况下,不能使用安装程序安装时,手动安装最容易出现的错误在路径问题上。由于手动安装,PHP运行需要的某些文件在PHP配置文件中找不到路径,就会引发错误。此类错误的解决方法,可以通过查找、修改PHP配置文件中关于路径的设置来解决。 在开始正式学习PHP语言之前,要对PHP配置文件中“register_globals”参数进行设置。其作用是:在设置为“on”时,程序中的变量将自动注册为全局变量,在设置为“off”是关闭这项功能。“register_globals”设置为“on”,是PHP程序中一个主要的安全隐患。要更改这项参数的设置,需要对PHP的配置文件进行编辑。
  • 29. 1.4.4 关于Eclipse的问题为了省去复杂的中文化过程,本书使用的是英文版的Eclipse,在整个使用过程中,只是涉及了几个简单而且常用的英文单词,相对于整个PHP语言的学习来说,没有什么大的障碍。如果读者希望使用中文版的Eclipse,可以下载3.2.X系列版本的Eclipse和相应版本的PDT进行配置。 Eclipse的更新很快,为了节省读者的时间,光盘中提供了Eclipse的压缩包,通过解压缩可以直接使用Eclipse程序。在实际应用中,运行环境和开发工具的使用都会产生很大小的问题,在这里就不一一列举。如果读者有什么疑问,可能通过论坛进行交流。
  • 30. 第2章 语法在第1章的学习中,介绍了PHP运行平台的选择、安装与配置。同时介绍了相关的PHP开发工具及其特点。通过学习这些知识,为PHP语言的学习打下了坚实的基础。在下面章节的学习中,统一使用第一章中构建的PHP运行环境,以及开发工具来编写PHP文件。 每一项语言学习的第一步都是语法,可见其在语言学习中地位的重要性。语法的学习过程其实就是规则的学习过程。在熟练的掌握了要学习语言的规则后,才可以灵活的使用语言。 PHP的语法相对其他编程语言来说,还是相对简单的。在通过与流行编程语言的比较后,会发现大多数编程语言的语法都大同小异。这对有语言学习基础的读者来说,可以很快进入学习,同时也要注意区别细节部分,以防止错误代码的产生。
  • 31. 2.1 语法基础每一种编程语言都有其特点,PHP对于初学者来说,入门很简单,但是同时也会为专业的程序员提供高级特性。但无论简单或高级编程,都是以语法为基础的。本章节的学习重点就是语法。
  • 32. 2.1.1 使用PHP输出HTML通过前面章节的学习,了解了怎么样编写PHP程序,并使之运行的过程。本文提到的PHP文件是以“.php”为扩展名的文件。PHP代码作为服务器脚本在后台运行,运行后得出的数据,通过PHP语言自带的显示函数,输出到浏览器内。在PHP输出HTML可以使用echo()或print()来实现,代码如下所示。
  • 33. 2.1.2 使用显示函数输出HTML使用显示函数输出带有HTML格式的内容,代码如清单所示。 清单 显示函数输出带有HTML格式的内容 输出带有HTML格式的测试字符串‘; $str3 = ‘输出带有HTML格式的测试字符串‘; echo $str1; echo ‘

    ‘; echo $str2; print ‘
    ‘; print $str3; ?>
  • 34. 2.1.3 使用开始符、结束符嵌套HTML使用开始符、结束符输出HTML,演示代码如下所示。 测试的变量值等于1。 测试的变量值不等于1。 这种方法插入HTML比较简单,不用顾虑单引号和双引号嵌套的问题。其优点在于,不容易产生错误,适用于在PHP里插入大段的HTML代码,特别适用于过程编程方法。但是后期的代码维护有一定的难度。特别是当HTML语句过长时,在编写程序的逻辑代码时容易产生错误。
  • 35. 2.1.4 使用定界符显示HTML使用定界符输出HTML,演示代码如清单所示。 清单 使用定界符输出HTML的方法 测试字符串
    测试字符串
    测试字符串 EOD; echo $str; //为定界符定义使用的变量 $name = '爱因斯坦'; $dicta = "想象力比知识更重要,因为知识是有限的,而想象力概括着世界上的一切,推动着进步,并且是知识进化的源泉。"; $size = 5; echo << {$name}说:“{$dicta}” EOT; ?>
  • 36. 2.1.5 把PHP嵌入HTML在HTML里嵌入PHP代码相对来说比较简单,代码如清单所示。 清单 把PHP嵌入HTML 用户交互页面 本页是PHP代码测试页,这一行是使用HTML代码直接输出.
  • 37. 2.1.6 PHP与JavaScript的交互JavaScript并不是新推出的脚本语言,但随着AJAX技术的兴起,这种在客户端运行,不浪费服务器端的资源,能建立良好的用户交互界面的脚本,得到了广泛的应用。与此同时网络编程语言与JavaScript变量的交换,也成了讨论的焦点。 PHP与JavaScript的交互大体可分为3种,即:使用PHP生成JavaScript,使用COOKIE进行数据交换,使用临时文件进行数据交换。 PHP生成JavaScript的方法,可以动态生成JavaScript,使得在服务器端的设置,通过客户端的JavaScript表现出来,提升用户体验。在使用时应注意,PHP生成JavaScript脚本的语法,不用与JavaScript语法混合。 使用COOKIE进行数据交换,可以在PHP与JavaScript脚本交换小数据量时使用。因为COOKIE与脚本代码无关,PHP与JavaScript都可以设置和读取COOKIE,使得两种语言在交换数据里,变得很简单。 使用临时文件进行数据交换,原理与使用COOKIE进行数据交换是一样的,只不过临时文件可以存取的数据量更大,样式更丰富。但使用临时文件往往需要更多的操作代码。
  • 38. 2.1.7 使用PHP生成JavaScript使用PHP生成JavaScript的方法很简单,与PHP输出HTML使用同样的方法,在两种语言嵌套时,应注意不要把语法混合,演示代码如清单所示。 清单 使用PHP生成JavaScript "; echo "var jsVar = '我是JavaScript变量';"; echo "var phpVar = '这是".$var2."与JavaScript组成的变量';"; echo "alert(jsVar);"; echo "alert('".$var1."');"; echo "alert(phpVar);"; echo ""; ?>
  • 39. 2.1.8 在PHP与JavaScript中使用COOKIE传递变量PHP与JavaScript都能访问浏览器里的COOKIE,通过PHP与JavaScript的COOKIE函数,可以轻松的进行交互,演示代码如清单所示。(详细内容请对照本书) 上面的代码演示了怎么样使PHP与JavaScript通过COOKIE进行数据交换。因为PHP在设置COOKIE时,会使用urlEncode对COOKIE的值进行编码,而JavaScript在解析这种编码方面还很困难,或者说是不可能。所以采用了“VBScript”脚本编写的编码解析函数来解决这个问题。使用COOKIE交互数据,在PHP与JavaScript交换少量数据时比较常用到。
  • 40. 2.1.9 使用临时文件进行数据交换这种方法和使用COOKIE进行数据交换方法的原理着不多。只不过,使用临时文件可以交换更大的数据量,可选择性比较强。 PHP的文件操作函数,在权限允许的情况下,可以在服务器端创建、存储和读取文件。用于数据交换的文件也有比较多的格式选择,例如通用的XML格式、JSON格式或使用自定义的格式。下面通过一段代码,简单演示PHP与JavaScript,使用XML文件进行数据交互的例子,演示代码如清单所示。
  • 41. 2.1.10 使用注释在本章的示例代码中,为了方便读者阅读代码,使用了大量的注释语句。大型的软件系统开发时,代码往往是成千上万行,在这么多的代码中,快速的阅读代码,并找到想要的内容,这就是注释最重要的作用。PHP注释分为单行注释和多行注释,下面的代码段,显示的是几种正确的注释方法。
  • 42. 2.2 类型本节提到的类型是指变量的类型。不同类型的变量存储的值的大小和形式都不一样。而变量的类型通常不是由程序员设定的,是由PHP根据该变量使用的上下文在运行时决定的。 PHP 支持8种原始类型。4种标量类型:boolean(布尔型)、integer(整型)、float(浮点型,也作“double”)、string(字符串);两种复合类型:array(数组)、object(对象);两种特殊类型:resource(资源)、NULL。
  • 43. 2.2.1 布尔型布尔型的英文名称为:boolean。布尔型是最简单的变量类型。其取值只有两个:真和假,使用TRUE和FALSE表示。要想为变量指定一个布尔值,只需要为其指定关键字“TRUE”或“FALSE”,并且这两个关键字不分大小写。布尔型变量多用于流程控制,示例代码如下所示。 "; } // 使用布尔值进行逻辑控制 if ($flag == TRUE) { echo "旗帜已经升起。
    "; }else{ echo “旗帜还没有升起。
    ”; } // 单独使用布尔值进行逻辑控制 if ($run) { echo "运行员已经起跑。
    "; } ?>
  • 44. 2.2.2 布尔型的类型转换在很多情况下,程序计算的结果会用来做逻辑运算,这时就需要把不是布尔值的变量转换成布尔值。强制转化布尔值,可以在变量前使用“(bool)”或“(boolean)”来实现。但是很多情况下不需要用强制转换,因为当运算符、函数或者流程控制需要一个布尔型的参数时,该值会被自动转换,这也是PHP语法的一个特色。 但如果遇到强制转换布尔值时,还是需要仔细检查,以防程序出现错误。当转换为布尔值时,以下值被认为是 FALSE: 整型值:0(零)。 浮点型值:0.0(零)。 空白字符串和字符串:“0” 。 没有成员变量的数组。 特殊类型NULL(包括尚未设定的变量)。 所有其他值都被认为是TRUE(包括任何资源)。
  • 45. 2.2.3 整型整型的英文名称为:integer。整型变量的值,使用集合表示就是Z = {..., -2, -1, 0, 1, 2, ...}。也就是正整数、0与负整数中的任意一个数。整型值可以用十进制,十六进制或八进制符号指定,前面可以加上可选的符号“-”或者“+”,如果用八进制符号,数字前必须加上0(零),用十六进制符号数字前必须加上0x。下面演示部分整数使用整型来进行文字表达的方法,代码如下所示。
  • 46. 2.2.4 整型的类型转换在有些情况下,需要对整型数值进行强制类型转换,或者根据上下文自动转换。为了保证程序的正常运行,需要对转换后的类型加以确认。下面介绍的是两种整型自动转换的例子。 (1)当整型变量溢出时,变量类型会自动转换成 float也就是浮点型。如果给定的一个数或执行运算得出的结果,超出了整型的范围,就称为溢出。在出现溢出后,PHP会自动转换类型来保证数据的正确。下面演示的是分别使用十进制、十六进制表达整型变量正常及溢出的情况,
  • 47. 2.2.5 浮点型浮点型的英文名称为:float。中文名称也可以称为浮点数、双精度数或实数,可以用以下语法定义,定义代码如下所示。 浮点数的字长和平台相关,通常最大值是1.8e308并具有14位十进制数字的精度。关于浮点数精度,要特别注意,在2.2.4小节中,将运行结果还没有确定的表达式转换为整型时,出现了精度的问题。简单的十进制分数如0.1或0.7,不可能在不丢失精度的情况下转换为内部二进制的格式,这就会造成输出结果的失真,如floor((0.1+0.7)*10)通常会返回7而不是8。 虽然浮点数能表达的值比整型多,但也有其限制,如1除3后会产生无限小数,就不可能使用浮点数表示了。所以不要相信浮点数结果精确到了最后一位,也不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者gmp函数。
  • 48. 2.2.6 浮点型的类型转换浮点型的类型转换比较简单,字符串型转换为浮点的方法,会在2.2.4小节中介绍。而其他类型的值转换为浮点型时,应先将值转换成整型,然后再转换成浮点。
  • 49. 2.2.7 字符串字符串的英文为:string。其值是一系列字符。其范围在PHP中没有强制限制,所以在操作字符串时,不用担心其长度过长的问题。在上面的章节中,已经接触过字符的定义方法,总结一下,共分为3种:单引号、双引号和定界符。 (1)单引号:定义字符串的最简单的方法是把字符用单引号(')括起来。如果在定义的字符串中出现单引号,就需要使用转义操作符(\)进行转义后,才能正常输出。使用单引号定义的字符串中出现的变量和转义序列不会被变量的值替代。 (2)双引号:使用双引号(")括起字符,同样可以定义字符串。与单引号定义字符串相同,如果在定义的字符串中出现了一个双引号,就需要使用转义操作符进行转义。而在字符串中出现其他的特殊字符,可以对照表2-1进行转义操作。 (3)定界符:使用定界符定义字符串,在前边的章节已经使用过。
  • 50. 2.2.8 字符串与双引号在使用单引号和双引号定义字符串时,在使用的时候会有不同的表现,下面演示的是单引号与双引号定义字符串的方法和转义字符串的使用,代码如清单所示。
  • 51. 2.2.9 字符串与定界符定界符由开始标识符和结束标识符组成。开始标识符由“<<<”和一个标签组成,与变量名称在同一行内。结束标识符就是开始标识符的标签,单独在一行上,而且结束标识符所在的行,除了分号之外,不能包含任何其他字符。而且在分号之前和之后,都不能有任何空格或制表符。 如果破坏了这条规则,这个结束标识符则会被视为无效的,PHP会继续寻找下去。在这种情况下找不到合适的结束标识符,将会导致脚本最后一行出现语法错误。定界符还有一件重要的规则,就是不能用定界符语法初始化类成员,只能使用上过两种介绍的方法。以下是错误的演示,代码如下所示。
  • 52. 2.2.10 简单语法与复杂语法简单语法比较通用和方便,其不仅能解析变量,还可以解析数组索引或者对象属性。对于数组索引,右方括号(])标志着索引的结束。对象属性和方法和简单变量使用方法相同。定界符中,在输入法为半角英文状态下输入的代码中插入变量,可以使用简单语法。 对于比较复杂的情况,可以使用复杂语法。复杂语法可以用花括号括起一个表达式。不是因为语法复杂而称其为复杂,而是因为用此方法可以包含复杂的表达式。 复杂语法可以在字符串中包含任何值,包括表达式。在一个字符串中出现中文,那么可以使用复杂语法在字符串中添加变量,演示代码如2.2.9小节中的清单所示。因为这种方法很少使用,,在此就不多做介绍。 注意:这两种方法只适用于双引号或者定界符指定的字符串。
  • 53. 2.2.11 字符串型的类型转换可以用(string)标记或者strval()函数将一个值转换为字符串。当使用echo()或者print()函数时,或者将一个变量值与一个字符串进行比较的时候,字符串的转换会在表达式范围内自动完成。在类型自动转换和强制转换时,一定要注意转换后变量的值。下面演示的是,在强制转换各个类型为字符串时,产生的值的情况,代码如下所示。
  • 54. 2.2.12 数组数组是一组具有相同数据类型元素组成的一个有序图。PHP中的图是一种把 values(值)映射到 keys(键名)的类型。数组通过使用array()函数定义,其值使用“key=>value”的方式设置,多个值通过逗号分割。数组的定义,如以下代码所示。 "banana", "red"=>"flower", "3"=>"三", "03"=>"叁" ); //直接为数组赋值 $two = array(1,2,3,4,5,6,7,8,9); //带有一个键名的数组 $three = array(6=>"六","七","八","九","十"); ?>
  • 55. 2.2.13 简单的数组操作数组的简单操作包括显示、添加、修改和删除,演示代码如下所示。
  • 56. 2.2.14 遍历数组遍历数组,就是把数组中的值,通过某种方法一一展现。数组的应用,大多都要求对数组进行遍历。遍历数组的方法很多,在本书的2.8节中会有其他方法的介绍,本小节只介绍使用foreach()函数遍历数组的方法,代码如清单2.12所示。 清单2.12 遍历数组 $value) { echo "值'{$value}'的键名是$key
    "; } //使用foreach遍历数组,只取值 foreach($colors as $value){ echo "没有键名,只有值:{$value}
    "; } ?>
  • 57. 2.2.15 数组的类型转换要把其他类型转换为数组,可以使用(array)标记,各个类型在转换后的数组会有所差别,代码如清单所示。
  • 58. 2.2.16 多维数组多维数组与数组的定义、操作方法都相同。通过演示代码,可以了解多维数组的定义和操作过程,代码如下所示。 array(1,2,3,4,5,6,7), "colors" => array("红","蓝","绿","黄","紫","青","橙") ); //遍历一个多维数组 foreach($more as $arrays){ foreach($arrays as $key=>$value){ echo $value; } } //显示多维数组的值 echo $more["numbers"][5]; echo $more["colors"][5]; //删除多维数组的值 unset($more["numbers"][0]); ?>
  • 59. 2.2.17 对象在PHP中,要使用“new”把对象实例化到一个变量中,代码如下所示。 height = 170; } } //初始化对象 $newHuman = new human(); //访问对象属性 echo $newHuman->height; //访问对象的方法 $newHuman->setHeight(); echo $newHuman->height; ?> 对象是通过实例化后的变量来操作的,关于对象与类的更多操作,可以参见本书的第3章。
  • 60. 2.2.18 对象的类型转换其他类型转换为对象,可以使用(object)操作符实现,代码如清单所示。 清单 其他类型转换为对象
  • 61. 2.2.19 资源资源是一种特殊变量,其值是一个到外部资源的引用。通过专门的函数,可以建立资源并对其进行访问,能建立资源的函数很多,在本书的其他章节有所介绍,本小节使用fopen()函数来建立一个资源,代码如下所示。
  • 62. 2.2.20 NULLNULL是一个特殊的值,在给变量赋与此值时,代表该变量没有值。此类型唯一的,也是仅有的值就是NULL。可以通过is_null()函数来判断当前变量,是否为NULL值,代码如下所示。
  • 63. 2.2.21 变量类型之间的转换关于类型的转换,在讲解类型的时候,已经进行了介绍。在PHP中的变量,会根据上下文的判断,自动设置变量的类型。强制转换类型也可以使用以下操作符实现。 (int)、(integer):转换成整型; (bool)、(boolean):转换成布尔型; (float)、(double)、(real):转换成浮点型; (string) :转换成字符串; (array) :转换成数组; (object) :转换成对象; 注意:强制转换操作符的括号内允许有空格和制表符的出现。
  • 64. 2.3 变量程序运行时,会在内存中存储两种形态的信息。经过定义,在程序运行中不再改变的值,称为常量;而根据各种条件,会发生变化的值称为变量。PHP中的变量由“$”符号和变量名来表示。其引用的就是存储该变量的内存地址。
  • 65. 2.3.1 命名规则变量的命名与PHP其他标签遵守相同的规则,正确的变量名由“$”符号,后面跟随以字母或下划线开头的,任意数量的字母、数字、下划线。其中字母的范围是小写字母a-z和大写字母A-Z,使用ASCII码表示就是从127-255;下划线是指“_”;数字是从0-9取值。通过下面的演示,说明一下变量的命名规则,代码如下所示。
  • 66. 2.3.2 变量类型变量的基本类型有布尔型、整型、浮点型、字符串、数组五种,加上扩展的对象、资源、NULL3种,一共有8种变量类型可供选择。 PHP的变量类型,会根据程序运行的上下文自动改变。有例外的情况,也在上一节中进行了介绍。要特别注意的是,有些类型是不能强制转换的,例如:资源。 变量在使用前一般都经过初始化,但是没有经过初始化的变量,在参与表达式的运算时,一定要注意其值的变化,下面代码演示的是,各类型变量没有初始化参与运算时的值的情况,
  • 67. 2.3.3 变量范围一个变量初始化后,其作用范围就确定下来了。下面演示的是变量定义后的有效范围,代码如清单所示。 清单 在包含文件中定义变量
  • 68. 2.3.4 全局与超全局变量要想在函数内部访问外部变量,可以使用“global”关键字或访问超全局变量来实现,代码如清单所示。
  • 69. 2.3.5 静态变量静态变量属于变量的一种。变量在程序执行时,离开其作用域,其值将会改变或消失。而静态变量恰恰相反,在程序执行时,离开其作用域时,其值不会丢失。通过以下代码,可以更清楚的了解这个过程,代码如清单所示。
  • 70. 2.3.6 可变变量在不确定一个变量的名称时,可以使用可变变量,通过演示代码,可以了解可变变量的设置和使用方法,代码如清单所示。 清单 可变变量演示
  • 71. 2.3.7 外部变量在程序中定义或自动产生的变量称为内部变量。由HTML表单、URL或外部程序产生的变量称为外部变量。可以通过预定义变量“$_REQUEST”、“$_POST”、“$_GET”获取外部变量,代码如清单所示。
  • 72. 2.4 预定义变量预定义变量是由PHP预设的一组数组,其数据包括运行环境、用户输入数据等。因其作用范围是全局生效,所以又称为超全局变量或自动全局变量。
  • 73. 2.4.1 服务器变量:$_SERVER服务器变量是由网络服务器创建的数组,其内容包括头信息、路径、脚本位置等。不同的网络服务器提供的信息有所出入,本书以Apache服务器提供的作为标准。
  • 74. 2.4.2 环境变量:$_ENV环境变量是预定义的一个数组,记录着系统路径等信息。使用print_r()函数,可以查看具体的环境变量的数组成员。其数组成员主要包括:ALLUSERSPROFILE,BID,CommonProgramFiles,COMPUTERNAME,ComSpec,FP_NO_HOST_CHECK,NUMBER_OF_PROCESSORS,OS,Path,PATHEXT,PROCESSOR_ARCHITECTURE,PROCESSOR_IDENTIFIER,PROCESSOR_LEVEL,PROCESSOR_REVISION,ProgramFiles,SystemDrive,SystemRoot,TEMP,TMP,USERPROFILE,VS80COMNTOOLS,windir,AP_PARENT_PID。 单独访问环境变量的数组成员,可以通过“$_ENV[‘成员变量名’]”的方式实现,代码如下所示。
  • 75. 2.4.3 HTTP Cookies变量:$_COOKIE使用PHP的COOKIE函数或其他程序产生的COOKIE值,都保存在“$_COOKIE”数组中,使用print_r()函数,可以查看当前设置的COOKIE值的情况。可以通过“$_COOKIE[‘变量名’]”的方式访问COOKIE值,演示代码如下所示。
  • 76. 2.4.4 HTTP GET变量:$_GET通过URL提交的变量,或表单使用“GET”方法生成的变量,都会以数组的形式保存在$_GET 变量中。使用print_r()函数,可以查看当前$_GET变量值的情况。也可以通过“$_GET[‘变量名’]”的方式访问单独访问$_GET中的变量值,演示代码如下所示。 其他语言也可以模拟GET方法,向PHP程序提交HTTP GET变量。
  • 77. 2.4.5 HTTP POST变量:$_POST单使用“POST”方法生成的变量,都会以数组的形式保存在$_POST 变量中。使用print_r()函数,可以查看当前$_POST变量值的情况。也可以通过“$_POST[‘变量名’]”的方式访问单独访问$_POST中的变量值,演示代码如下所示。 其他语言也可以模拟POST方法,向PHP程序提交HTTP POST变量。
  • 78. 2.4.6 HTTP文件上传变量:$_FILES由HTML表单生成的文件上传变量,以数组的形式记录了上传文件的详细信息,其数组成员包括上传的文件名:name;文件类型:type;临时文件名:tmp_name;错误信息代码 :error;文件大小:size。下面介绍使用HTML表单,生成文件上传变量的方法, 要使表单产生文件变量,要满足三个条件: HTML表单要使用POST方式传递数据。 表单的“enctype”参数要设置为“multipart/form-data” 。 表单中包含一个文件选择框。 通过$_FILES变量获取上传文件相关信息后,就可以配合其他文件函数实现文件的上传。
  • 79. 2.4.7 Request变量:$_REQUEST作为超全局变量,$_REQUEST存储了包括$_POST、$_GET、$_COOKIE变量在内的数据。通过访问$_REQUEST,也可以实现$_POST、$_GET、$_COOKIE变量的功能。 虽然$_REQUEST在使用时比较方便,但是其提供的数据存在一定的危险性。比如一段程序使用$_REQUEST读取$_COOKIE值时,那有心的访客可以通过提供一个$_GET变量来模拟$_COOKIE值,从而取得一定的访问权限。
  • 80. 2.4.8 Session变量:$_SESSION由PHP的SESSION函数产生的数据,都以超全局变量的方式,存放在$_SESSION变量中,使用print_r()函数,可以查看当前设置的SESSION值的情况。可以通过“$_SESSION[‘变量名’]”的方式访问SESSION值,演示代码如下所示。 关于如何在PHP中创建和使用SESSION,本书的第6章有详细介绍。
  • 81. 2.4.9 Global变量:$GLOBALS$GLOBALS变量以数组的形式,记录了所有已经定义的全局变量,而变量名就是这个数组的索引。即然$GLOBALS记录着所有的全局变量,那么理所当然的也可以访问全局变量里的信息,下面介绍使用$GLOBALS访问其他预见定义变量的方法,代码如下所示。 $GLOBALS把SESSION及其他全局变量,作为数组中的一员过行访问。可以通过print_r()函数,查看当前$GLOBALS存储值的情况。
  • 82. 2.5 常量常量的定义已经在2.3节中进行了介绍。虽然在程序中,常量不被经常使用,但程序中不变得一些参数,如数据库用户和密码等数据,也是可以使用常量来存储的。利用常量定义后不能更改的特性,还可以把其使用在程序运行安全方面。
  • 83. 2.5.1 定义和使用常量常量使用define()函数进行定义,操作格式为:“define("常量名","常量值");”。常量的命名,以字母或下划线开始,后边跟随其他任意字母、下划线和数字。常量的名称对大小写敏感,按照惯例常量标识符总是大写。下面分别演示正确的和错误的常量命名,代码如下所示。
  • 84. 2.5.2 预定义常量预定义常量也称为魔术常量。预定义常量使用的方法虽然与常量相同,但是其值会根据使用的情况而产生变量。所以从严格意义上讲,不能称其为常量。经常使用到的常量有五个,通过下面的代码,来介绍其使用方法,代码如清单所示。
  • 85. 2.6 表达式与运算符在PHP中,所有有值的都可以称为表达式。而表达式大部分都是由变量与运算符组成的。本节主要介绍表达式的组成形式和运算符的使用方法。
  • 86. 2.6.1 表达式的组成根据表达式的定义,变量赋值,就是最简的表达式,而复杂表达式的例子就是函数了。下面举例说明一下表达式的各种形式,代码如下所示。 表达式的形式有很多,产生的值也有很多可能,在使用的时候要注意表达式值的变化,才能正确的进行逻辑判断,避免程序产生错误。
  • 87. 2.6.2 运算符优先级运算符指得是能返回一个值的结构。这个结构当然也包括能返回值的函数。但类似于echo()、print()、print_r()等函数不在此列。 运行符包括一元运算符、二元运算符、三元运算符三种类型。一元运算符只能对一个数进行类似取反或加1的运算,二元运算符使用最多的。二元运算符在表达式的运算中,是根据运算符优先级来计算的。三元运算符是的形式是:“表达式1?表达式2:表达式3”,其会根据第1个表达式,来选择第2个或第3个表达式作为其本身的值,三元运算符在以后的章节中,会有详细的介绍。 运算符规则:先进行高优先级运算符的计算,再进行低优先级运算符的计算,如果运算符级别相同,按照从左到右的顺序计算。可以使用“()”符号来改变优先级。
  • 88. 2.6.3 算术运算符算术运算符包括6种最基本的运算加(+)、减(-)、乘(*)、除(/)、取模(%)、取反(-)。下面演示这6种运算符的使用方法,代码如下所示。
  • 89. 2.6.4 赋值运算符顾名思义,赋值运算符的作用就是,把右边表达式的值赋与左边的表态式。其运算符号是“=”,及其他组合的符号“+=”、“-=”、“.=”等。赋值运算符使用的比较广泛,下面演示赋值运算符的使用方法,代码如下所示。
  • 90. 2.6.5 位运算符位运算可以操作整型和字符串两种类型。其运算符包括:按位与(&)、按位或(|)、按位异或(^)、按位非(~)、左移(<<)、右移(>>),下面演示赋值运算符的使用方法,代码如下所示。
  • 91. 2.6.6 比较运算符比较运算符可以对两个值进行比较,不管两个值是否为同一类型。比较运算符包括:等于(==)、全等(===)、不等(!=)、不等(<>)、非全等(!==)、小与(<)、大于(>)、小于等于(<=)、大于等于(>=),下面演示比较运算符的使用方法,
  • 92. 2.6.7 错误控制运算符在可以产生值的表达式前使用错误控制运算符,可以忽略因表达式运算错误而产生的错误信息。错误控制运算符是“@”,下面演示错误控制运算符的使用方法,代码如下所示。
  • 93. 2.6.8 执行运算符使用执行运算符“``”,PHP将把运算符内的字符作为外壳命令来执行,其作用与shell_exec()函数相同。下面演示执行运算符的使用方法,代码如下所示。 $output"; ?> 注意:在安全模式激活或者关闭了shell_exec()的情况下,执行运算符是无效的。
  • 94. 2.6.9 递增/递减运算符递增/递减运算符主要是对整型进行操作,同时对字符也有效。其操作符包括:前加、后加、前减、后减。下面递增/递减运算符的使用方法, 递增/递减运算符对布尔值没有影响,递减NULL值时也没有效果,但是在递增NULL值是,结果为是1。
  • 95. 2.6.10 逻辑运算符逻辑运算符可以操作布尔型。其运算符包括:逻辑与(and)、逻辑与(&&)、逻辑或(||)、逻辑或(or)、逻辑异或(xor)、逻辑非(!),下面演示逻辑运算符的使用方法,代码如下所示。
  • 96. 2.6.11 字符串运算符字符串运算符主要用于连接两个字符串。其运算符包括:“.”和“.=”,下面演示字符串运算符的使用方法,代码如下所示。
  • 97. 2.6.12 数组运算符数组运算符可以对两个数组进行比较。数组运算符包括:联合(+)、相等(=)、全等(===)、不等于(!=)、不等于(<>)、不全等于(!==)。下面演示数组运算符的使用方法,代码如下所示。 $n; //比较两个数组是否不全等于 $m !== $n; ?>
  • 98. 2.6.13 类型运算符类型运算符可以针对对象进行检测,以测定其实现的接口是否来自于指定的类。下面演示类型运算符的使用方法,代码如下所示。
  • 99. 2.7 程序流程控制程序流程控制在编程语言中占有重要的地位,大部分的程序段都要依靠其来完成。PHP的程序流程主要包括判断、循环、开关控制等,而这些控制语句之间大多都可以进行嵌套使用。
  • 100. 2.7.1 if else elseif分支控制if是重要的分支控制语句,当程序运行时,为if提供一个表达式,如果表达式是TRUE值,将执行if后面的语句,如果为FALSE值,则忽略if后面的代码继续执行其他代码段。 elseif是if语句的延伸,其自身也有条件判断的功能,在if运行条件为FALSE值时,elseif会判断自身的运行条件,如果为TURE值时,执行elseif内的代码段,如果运行条件为FALSE值,刚跳过该代码段。 else也是if语句的延伸,其用在if和elseif语句后,用于这两个语句的运行条件为FALSE值时,运行其内的代码。 if、elseif、else给合使用,可以根据表达式的值来指定要运行的代码段,使得程序在运行时,流程变得更加清晰。
  • 101. 2.7.2 while do-while循环控制while语句主要负责程序里的循环控制,当需要完成大量的重复性工作时,就可以通过条件控制while来完成。while语句在运行时,如果给定的表达式是TRUE值,就运行循环体内的语句,同时改变表达式的值,再次回到while语句开始重新检查表达式的值,如果表达式是TRUE值再次循环,直到表达式值为FALSE为止。如果在循环中表达式的值为FALSE,就停止循环,继续执行其他代码。需要注意的是,如果一开始给定的表达式值为FALSE,while语句是不会运行的。
  • 102. 2.7.3 for foreach循环控制for语句也是用于循环控制,但是与while相比就比较复杂了,其语法如下所示。 for(条件1;条件2;条件3){ //要循环的语句 } for循环是比较复杂的语句,在使用时要特别注意,如果循环条件没有设置,语句是不会运行的。 语法中的条件1在循环开始前就要初始化。 语法中的条件2使用条件1的值与给出值做比较,如果为TRUE值开始循环,如果是FALSE值则结束循环。 语法中的条件3是在每次循环后运行。 如果语法中的3个条件都为空,则会形成无限循环。
  • 103. 2.7.4 switch case开关控制switch语句看似很复杂,但是其本身就是多个if语句的组合。switch语句运行时要求一个变量,在switch语句内,会对这个变量进行比较,如果满足语句内的条件就执行对应的代码,否则向下执行,直到语句结束。 使用switch相比使用if语句简单的多,也更容易理解。switch接收的变量包括整型和字符串。
  • 104. 2.7.5 break控制符在2.7.4小节中,使用break语句来结束switch语句的运行。这是典型的break语句的使用方法,同时break语句还可以作用于for、foreach、while、do-while语句,在循环语句嵌套使用时, break语句也有其针对的用法。
  • 105. 2.7.6 continue控制符在循环控制语句中使用continue语句,将跳过本次循环的剩余代码,转到循环控制的开始,如果循环语句的表达式为TRUE值,继续进行循环。continue的延伸用法和break语句一样,都是在语句后面加上数字,表示要跳出的循环数,在循环语句嵌套使用时, continue语句也有其针对的用法。
  • 106. 2.7.7 return控制符return控制符主要有两种使用方法: (1)在函数中使用return:在函数中使用return控制符,将结束函数的执行并返回指定的值, (2)在脚本中使用return:直接在脚本中,包括在循环体内使用return,将结束当前脚本的运行,
  • 107. 2.7.8 流程控制的替代语法在流程控制中,有可能遇到需要显示大段HTML代码的情况,这时可以把流程控制的语句使用替代语法表示,使程序更加易读。可以使用替代语法的流程控制语句有:if、while、for、foreach、switch。下面演示使用替代语法进行流程控制
  • 108. 2.7.9 包含运行文件操作包含文件操作包括:include()、require()、include_once()、require_once()4个语句,语句指定的文件,将被包含到当前文件并运行。下面演示这4个语句的使用方法,代码如下所示。
  • 109. 2.8 引用新建一个变量名,并指向一个已经存在的变量就称为引用。引用实际上就是为变量增加了一个别名,使用引用的变量,与使用变量本身是一样的,如果改变了引用变量的值,那么变量本身的值,也会随着产生变化。本节只是介绍了引用的基本用法,在本书的其他章节,会有其他关于引用高级应用的例子。
  • 110. 2.8.1 建立引用要完成引用操作,就要使用引用操作符“&”。下面演示引用操作符的使用方法,代码如下所示。
  • 111. 2.8.2 引用的应用引用不仅可以应用在变量上,也可以应用在数组上。下面演示引用数组使用方法,代码如下所示。
  • 112. 2.8.3 取消引用取消引用需要使用变量删除函数unset(),下面演示取消引用的方法,代码如下所示。
  • 113. 2.9 常见问题语法是学习语言的基础,只有打好扎实的基础,才能在程序编写时减少程序的语法错误,提高程序的可读性、灵活性。在本章的几个知识点里,针对容易出错的地方特别说明一下。
  • 114. 2.9.1 嵌套问题在本章中一开始接触到的HTML与PHP代码、PHP与JavaScript,到程序控制语句中的循环语句,都存在着嵌套问题。当嵌套代码在一行或几行之内,都是可控的。但是有些代码,比如要显示一个软件界面,就需要很多代码来完成,这时的代码量可能是一屏或几屏,这就需要程序员在编写程序时,在嵌套方面多加注意。有两个小的技巧,可以减少这方面的错误。 (1)完整的花括号:对于很多程序员来讲,输入花括号可能是比较费力的事,有时会因为先输入了左花括号,而在花括号内嵌入了大量代码后,没有使用右花括号关闭语句,这时候很容易产生错误。所以在输入花括号时,可以一次性输入完成,再在中间嵌入其他代码。输入完整的花括号,也孕挛偶钦叱绦蛴幸欢ǖ陌镏Eclipse在这方面提供了自动功能,会根据输入的内容自动添加另一半符号。 (2)尽量使用函数和包含文件:把大段的HTML代码做成包含文件或函数,在运行条件允许时,只要包含进文件或调用函数,就可以实现功能。使得嵌套内的代码变得简洁,易懂。
  • 115. 2.9.2 数组问题因为数组相对于变量来说,较为复杂,所以在使用时经常会遇到一些问题,主要表现在以下几个方面: (1)键名:为了简单,在编写程序时定义的数组,往往没有键名,当经过多步对数组的操作后,要使用其中一个数组成员就变得很困难。这要求在需要单读读取数组成员的时候,数组定义时,最好定义键名,以便于操作。 (2)关于显示数组成员:显示数组成员很简单,在键名是整型时,通过以下方式实现。 echo $array[键名]; 但是在输入键名时,习惯了输入整型键名不使用引号后,在输入字符串键名时,也往往容易忘记引号的存在。以下的形式就是非法的形式。 echo $array[one]; 但在使用双引号显示数组成员时,省略单引号是合法的,代码如下所示。 "数组1",1=>"数组2"); echo "$big[one]"; ?>
  • 116. 2.9.3 关于变量范围大部分的变量定义后,都是在当前脚本中使用。但是有一些变量使用量很大,在每一个脚本文件中都能用到,而且值都是一样的。显然在每个脚本文件里对其定义是不可能的。这时就可以利用变量的范围来实现变量的使用。 (1)使用包含文件:把需要使用的变量或常量定义到包含文件中,只要在脚本开始处包含这些文件,就可以使用其中定义的变量。 (2)使用全局变量:有时包含文件过于庞大,就可以考虑使用全局变量。
  • 117. 2.9.4 关于表单变量表单是用户与服务器交互的主要工具。所以在向服务器传送表单前,有两个表单参数需要注意一下。 (1)method:此项参数有两个值:GET和POST。使用GET作为参数值时,表单内的数据将以URL的形式转送到处理程序,这种方式提交的数据量有限,在使用时应该注意。使用POST作为参数值时,可以提交大量数据。在处理表单变量的程序中,应根据这项参数的值来选择使用$_GET或$_POST获取变量。 (2)enctype:在上传文件时,此项参数要求设置为“multipart/form-data”,表单内的文件上传选择框的功能才可以使用。
  • 118. 第3章 函数、类与对象函数在面向过程编程时代是一个重要的概念,通过把复杂、重复的代码转化成函数,使得面向过程编程变得简单、明了。由于面向对象编程方式的兴起,类与对象在程序代码中也占据了重要的地位。本章主要介绍函数、类及对象的创建,及使用方法。
  • 119. 3.1 函数在程序语言中,函数可以理解为一个有效的PHP代码集合。通过函数内部的代码,构建一个能表达或处理数据的语句体。而通过调用这个语句体,可以简单、快速的处理相同的事务或数据。PHP为用户提供了丰富的系统函数,使用户可以使用简单的代码,完成复杂的工作。除此之外,PHP允许用户自定义函数。本节主要针对自定义函数进行讨论。
  • 120. 3.1.1 用户自定义函数 用户要编写一个程序,只使用变量和流程控制语言来完成,可以想象是多么复杂的事。还好PHP为用户提供了自定义函数的功能,让用户可以把复杂、重复的代码定义成函数,能过简单的调用,就可以重复使用。 用户可以使用“function”关键词来定义一个函数,而函数内部的代码可以包括变量、表达式、程序流程控制语句,甚至是其他函数或类定义。用户自定义函数的代码如下所示。
  • 121. 3.1.2 函数的其他定义方式函数不仅可以在脚本中定义,也可以在流程控制语句甚至函数里定义,代码如清单所示。
  • 122. 3.1.3 递归函数函数在定义完成后,会保存在文件中等待调用。调常是在别的脚本里,才调用已经定义的函数。在有些情况下,函数会调用其本身参与运算,这类函数称为递归函数。下面演示的是,使用递归函数显示10个表格,每一个表格拥有10个单元格,代码如清单所示。
  • 123. 3.1.4 函数的参数 函数按参数区分,可以分为无参函数和有参函数。无参函数可以直接调用。在调用有参函数时,必须为其提供一个有效的参数值,如果调用有参函数时,没有提供有效的参数值,函数运行时会出错。在函数定义时,有参函数已经设置了默认值,也可以直接调用。 有参函数定义时,其参数跟在函数名后的括号内,多个参数使用逗号分割。下面演示各种函数在运行时的情况,代码如清单所示。
  • 124. 3.1.5 函数的返回值用户自定义函数使用return()函数来返回值。return()的作用在程序流程控制中已经进行了介绍。return()函数通常在用户自定义函数代码的最后一段,用于返回函数语句计算过的值,并结束函数的运行。return函数可以返回任何类型的值,包括对象。
  • 125. 3.1.6 变量函数在变量后加上括号就形式了变量函数。在PHP中,如果变量后跟随括号,在脚本运行时,PHP解析器会寻找与变量同名的函数,并尝试运行。演示变量函数使用方法的代码如下所示。
  • 126. 3.1.7 系统函数本节主要介绍了用户自定义函数的创建、使用及注意事项。用户自定义的函数主要用来进行逻辑运算,而大部分的系统低层工作,还是需要系统自带的函数来完成。PHP为用户提供了丰富的系统函数,包括文件系统函数、目录函数、数组函数、字符串函数、日期/时间函数、图像函数、MySQL数据库函数等。要想使用这些函数,直接在脚本中调用就可以。 但是所有这些系统函数不是一定可以使用的,有一些函数需要插件支持的,如:图像函数,就需要GD库的支持。要想获取当前运行环境支持的函数列表,可以编写一个小脚本来实现,代码如下所示。
  • 127. 3.2 类与对象如果说函数是有效PHP代码的集合,那么类就是变量与函数的集合,而对象就是类的实例化。在面向过程的编程方法中,函数得到了广泛的应用。而随着近年来面向对象编程方法的逐渐成熟,PHP也引进了先进的对象模式,来完善对对象的处理,提高PHP处理对象的性能,为PHP使用面向对象编程。方法打下了基础。
  • 128. 3.2.1 类的创建类是由变量和函数组成的,在类里面,变量称为属性(也可以称为成员变量),函数称为方法。演示类定义方法的代码如下所示。 wheel = 4;//在类的方法中,使用$this访问类属性 } //定义一个方法,返回类的属性 function getWheel(){ return $this->wheel; } } ?>
  • 129. 3.2.2 类的实例化与访问类定义完成后,都是存在于文件中,只有把其转化为对象后,才能在内存中存在,供程序使用。类转化为对象的过程叫做实例化。类的实例化是使用new关键字,下面演示如何实例化一个类,并访问其属性和方法,代码如清单所示。
  • 130. 3.2.3 类的继承在PHP中,可以通过继承其他类,来调用这些类里已经定义好的方法和属性,但是只允许继承1个类。被继承的类称为父类或基类,继承类称为子类。要继承其他类,可以使用extends关键字来实现,下面演示继承类的方法,代码如清单所示。
  • 131. 3.2.4 子类访问基类的方法在子类继承基类后,可以使用$this引用来访问基类的方法和属性,下面演示使用访问基类的方法,代码如清单所示。
  • 132. 3.2.5 方法的重载方法重载是指,在一个类里可以定义几个拥有相同名称的方法,通过参数来区分方法之间的不同。方法重载是很多高级编程语言的特性,而PHP语言并不提供这一特性。但是通过类的继承,子类也可以重写基类的方法,来实现类似于方法重载的特性。下面演示在子类中重写方法的例子,代码如清单所示。
  • 133. 3.2.6 静态属性、方法与范围解析符在本书的第2章语法部分,介绍了静态变量在脚本和函数里的定义及使用方法。而在类里不仅可以定义静态属性,还可以定义静态的方法。在类里定义静态属性或方法,使用static关键字,下面演示如何定义静态属性和方法的,代码如清单所示。
  • 134. 3.2.7 静态属性、方法与类继承当一个类继承其他类后,可以在类里使用$this访问基类的方法和属性。如果基类里的方法和属性是静态的,也可以能过范围解析符来访问。使用范围解析符来访问基类的格式:parent关键字,加范围解析符,加要访问的静态方法或属性,下面演示静态属性和方法在类继承里的应用,代码如清单所示。
  • 135. 3.2.8 类与常量在PHP脚本中可以定义常量,与之对应,在类中也可以定义和使用常量。在类中定义常量使用const关键字,定义和使用常量的演示代码如下所示。 getInfo(); //直接访问类中的常量 echo car::brand; ?>
  • 136. 3.3 类的其他特性类不仅仅有可以继承的特性,还有许多其他的特性,如:克隆对象、自动加载、串行化等。掌握和应用这些特性,在编写代码时,就可以更加得心应手。本节主要通过演示的方式,把类的主要特性展示出来。在实际应用中,可以根据情况,使用不同的类特性,从而提高编写代码的质量。
  • 137. 3.3.1 构造函数和析构函数所谓的构造函数,就是在类的实例化时,自动调用的方法,通常在其他使用方法前运行。析构函数与构造函数正好相反,其是在对象被显式销毁前执行。构造函数与析构函数在类里使用固定的名称表示,名为__construct的函数被解析成为构造函数,名为__destruct的函数被解析为析构函数。下面演示的是构造函数和析构函数的使用方法,代码如清单所示。
  • 138. 3.3.2 带有参数的类函数可以通过参数来获取外部数据,在类中使用构造函数,也可以实现类似的功能。下面演示怎么实现一个类在实例化时,向其添加参数,代码如清单所示。
  • 139. 3.3.3 类的访问控制考虑到安全方面的问题,编程语言都会对外部的请求数据进行控制,或者说只开放内部的几个接口供用户调用,而其他大部分属性和方法,用户都是不可见的,这种方法称为封装。在PHP中使用public、protected、private这3个关键字,来对类进行访问控制,也可以实现类似的封装功能。下面演示的是对类的访问控制,
  • 140. 3.3.4 克隆对象举一个简单的例子,来说明为什么要使用克隆对象。如果有一个对象有100个属性,而在程序运行时,需要多个一模一样的这种对象,如果每次都把类实例化,再为这些属性赋值,出错的概率是比较高的,而且工作效率方面也有问题。这个时候就需要类的克隆对象的特性。通过clone关键字,可以在类已经实例化的情况下,复制一个相同的对象,而且两个对象之间不互相影响。下面演示怎么克隆一个对象,代码如清单所示。
  • 141. 3.3.5 自动加载对象当一个软件着手开始编码时,每天都产生大量的类。要使用这些类,就需要把存储这些类的文件,都包含到当前文件中,这在初期类文件少的时候可以操作,但是当类文件达到一定数量时,这个工作就会是一种负担,而且也很容易出错。 这个问题可以通过类的自动加载对象来解决。如果在脚本中定义了__autoload()函数,当使用new关键字实例化一个类时,这个类的名称将做为参数传递给__auotload()函数,__autoload()函数根据参数自动包含含有类的文件,并加载类文件中的同名类。自动加载对象方法的演示代码如下所示。
  • 142. 3.3.6 对象序列化对象序列化就是把已经存在的对象,使用serialize()函数转换为字符串,转换后的字符串包括了这个对象的所有属性和对象名称,但是不包括对象的方法。对象序列化后,可以使用unserialize()函数进行反序列化,还原对象并重建原始的属性。下面演示如果进行对象的序列化与反序列化,代码如清单所示。
  • 143. 3.3.7 魔术方法__sleep()和__wakeup()魔术方法__sleep()在对象序列化前运行,主要用于清除类似数据提交、关闭数据库链接等工作,并返回一个数组,该数组包括了对象应该被序列化的所有变量。也可以在返回的数组中,指定要序列化的变量。魔术方法__wakeup()是在对象反序列化之前运行,主要用于重建对象序列化时丢失的资源,或其他初始化的工作。 使用魔术方法,可以使复杂的对象序列化与反序列化成为可能。下面演示使用魔术方法在对象序列化和反序列化时,改变对象属性的方法,其过程类似于克隆对象时,使用__clone()的过程,代码如清单所示。
  • 144. 3.3.8 final关键字final的意思是最终的,也可以理解为常量。如果一个类封装后,不想用户对其进行继承,或者不想用户覆盖基类的方法,就可以使用final关键字。final关键字使用方法的演示代码如下所示。
  • 145. 3.3.9 抽象方法与抽象类抽象类是由abstract关键字定义的特殊类,类中包括至少一个抽象方法。抽象方法也是使用abstract关键字定义的特殊函数,其没有函数体,直接由函数名和括号组成。抽象类不能被实例化,所以其只能通过继承来使用。继承抽象类的子类,必须重载抽象类里所有的抽象方法,才能被实例化。下面演示抽象方法和抽象类的使用方法。
  • 146. 3.3.10 接口技术PHP不同于其他编程语言,类只能进行单继承,即只能有一个基类。为了解决这个问题,PHP引入了接口的概念。对于类来说,抽象类是一个特殊的类,而对于抽象类来说,接口就是一个特殊的抽象类。在抽象类中允许存在非抽象类和属性,而接口中只允许抽象方法的存在。在接口中不能使用成员变量,但是可以使用const定义的常量。 接口使用interface关键字定义,后面跟接口名,接口名应符合PHP的标签命名规范,接口名后是花括号,花括号内包括const关键字定义的常量和所有的抽象方法。由于接口中的抽象方法都要求使用public定义,PHP默认的方法访问控制范围就是public,所以在定义接口中的抽象方法时,直接定义即可,接口定义方法的演示代码如下所示。
  • 147. 3.4 常见问题本章主要学习了函数、类与对象的知识。灵活掌握函数与类,对于合理组织代码,提高代码质量,减少代码后期维护等方面,有着重要的帮助。在本章的学习中,也有一些地方容易出现错误,本小节将做出总结。
  • 148. 3.4.1 带有默认参数函数的使用方法在本章的第1节中介绍了函数的使用方法,其中关于函数参数部分中,介绍了函数可以使用带有默认值参数。而在普通参数与带有默认值参数同时存在的情况下,定义函数经常会出现一些错误的用法,在普通参数与带有默认值参数同时使用时,定义函数的正确用法与错误的用法的演示代码如下所示。
  • 149. 3.4.2 静态方法与类的继承与重载在使用静态方法定义了基类的方法和属性后,在子类里,如果要重载这些静态方法,子类里使用的访问控制操作符应该与基类的相同。即基类使用public、protected、private定义的方法,在子类中也要使用相同的关键写与之对应。
  • 150. 3.4.3 类的封装与抽象类在抽象类定义时,使用了访问控制操作符定义的方法,在子类继承后,重载抽象类的方法时,子类里使用的访问控制操作符应该与基类的相同。即基类使用public、protected、private定义的方法,在子类中也要使用相同的关键写与之对应。
  • 151. 第4章 数组数组可以通过用户创建取得,也可以由函数返回,或由函数创建,例如:数据库查询函数。数组就是具有相同属性变量的集合,其本质就是操作和管理存储在其中的变量。在本书的第2章语法部分,介绍了创建数组及多维数组的方法。同时介绍了添加、删除、遍历数组的方法,本章主要介绍常用的数组函数。
  • 152. 4.1 创建数组的几种方法在以前介绍的创建数组的方法中,都是由用户使用array()函数来创建的,4.1小节将介绍使用数组函数创建数组的方法。这些方法不仅可以创建了数组,还可以实现更多的数组功能,以满足用户的需要。
  • 153. 4.1.1 新建一个数组 array()函数就是一个典型的数组函数,用户可以使用其创建一个新的数组,这个新数组可以是空数组,也可以包括定义时给定的数组元素。使用array()函数建立数组的演示代码如下所示。 50,2=>120,3=>260,4=>300); //创建一个二组数组 $two = array( "color" => array("red","blue","green"), "numbers" => array(1,2,3,4,5,6,7,8,9) ); //显示数组所示元素 print_r($two); //访问数组单个元素 echo $speed[2]; echo $two["color"][0]; ?>
  • 154. 4.1.2 使用变量建立数组使用compact()函数,可以把单个变量或多个变量,甚至数组,添加为数组的成员,这些数组成员的键名是变量的变量名,值是这些变量的值。compact()函数的参数是要添加入数组的变量的变量名。compact()函数使用方法的演示代码如下所示。
  • 155. 4.1.3 使用两个数组创建一个数组使用array_combine()函数,可以把两个数组合并为一个数组,但不是把两个数组的成员相加,而是使用第1个数组作为新数组的索引,另一个数组作为新数组的值。array_combine()函数使用方法演示代码如下所示。
  • 156. 4.1.4 建立指定范围单元的数组如果使用array()函数,建立一个包含100个元素的数组,每个元素的值之间都有一定的规律,在实际操作中是比较麻烦的。在这种情况下,就可以使用range()函数的自动功能来完成类似的操作。下面演示range()函数的使用方法,代码如清单所示。
  • 157. 4.2 数组中键名和值的操作数组函数中对键名和值操作的函数比较多,对键名和值的操作,不仅仅是对已经定义完成的数组进行操作,还可以使用这些函数改变数组的键名和值,以达到程序运行的要求。
  • 158. 4.2.1 检查数组中是否存在某个键名或值当一个数组有很多元素时,使用数组遍历来求证某个值或键名是否存在,在速度和效率上有一定的损失。PHP的数组函数提供了更好的解决方法,使用in_array()和array_key_exists()函数,可以快速从一个数组中取得某个值或键名是否存在的情况,下面演示in_array()和array_key_exists()函数的使用方法,
  • 159. 4.2.2 取得数组当前单元的键名很多数组在被创建时,是不知道其具体内容的,如果想知道这些未知数组当前单元的键名,可以使用key()函数来实现,结合数组遍历,可以得出数组中所有值的键名。下面演示如果使用key()函数。
  • 160. 4.2.3 把数组中的值赋与指定变量与访问变量相比,访问数组成员相对来说是比较麻烦的。而使用list()函数,可以把数组中的值,赋与指定的变量名,这时就可以在程序中使用这些直观的变量了。下面演示list()函数的使用方法,代码如清单所示。
  • 161. 4.2.4 用给定的值填充数组单元用给定的值填充数组可以分为两部分: 用给定的值填充数组的值,可以使用array_fill()函数来完成这个操作。 用给定的值填充数组的值,用给定的数组填充数组的键名,可以使用array_fill_keys()函数来完成这个操作。
  • 162. 4.2.5 交换数组中的键名和值通常在操作数组时,主要是针对数组单元的值,但是在有些情况下,需要对键名进行修改,删除等操作,这时可以使用array_flip()函数,来交换数组的键名和值,来达到修改或删除键名的操作。下面演示array_flip()函数的使用方法,代码如下所示。 清单 array_flip()函数的使用方法 50,2=>120,3=>260,4=>300); //使用array_filp()函数交换键名与值 $speed = array_flip($speed); echo "交换键名与值后的数组
    "; print_r($speed); echo "
    "; //使用range()函数建立一个数组 $array = range("a","h"); //使用array_filp()函数交换键名与值 $array = array_flip($array); echo "交换键名与值后的数组
    "; print_r($array); ?>
  • 163. 4.2.6 返回数组中所有的键名或值对数组的操作主要是针对键名或值,在不想破坏被访问数组的情况下,可以把这个数组的键名或值,单独取出来进行操作,要想返回一个数组中单元的键名,可以使用array_keys()函数,返回单元的值,可以使用array_values()函数。 使用array_keys()与array_values()这两个函数取回的键名或值,都会保存的新数组中,演示代码如清单所示。
  • 164. 4.2.7 用值将数组填补到指定长度range()、array_fill()、array_fill_keys()这3个函数都可以用来填充数组, array_pad()也可以实现数组单元值的填充,演示代码如下所示。 50,2=>120,3=>260,4=>300); //向数组右增加二个单元值,值为500 $newArray = array_pad($speed,6,500); //显示结果 Array ( [0] => 50 [1] => 120 [2] => 260 [3] => 300 [4] => 500 [5] => 500 ) //向数组左填充二个单元值,值为-500 $newArray = array_pad($speed,-6,-500); //显示结果 Array ( [0] => -500 [1] => -500 [2] => 50 [3] => 120 [4] => 260 [5] => 300 ) ?>
  • 165. 4.2.8 删除、取代数组中现有值在本节已经学习了使用range()、array_fill()、array_fill_keys()、array_pad()函数来填充数组单元的值,但是这4个函数只能为数组单元填充相同的值,而实际应用中,数组的值往往是不一样的。array_splice()不仅可以填充数组,还可以删除指定的1个或多个单元。下面演示array_splice()函数的使用方法,代码如清单所示。
  • 166. 4.2.9 移除数组中重复的值在实际应用中,数组中保存着大量的数据,很自然的会出现相同值的情况,而有些情况下,只需要重复值中的一个值进行计算,这时可以使用array_unique()函数去掉重复的值,演示代码如下所示。 a [1] => b [2] => c [3] => a [4] => d [5] => e [6] => e) print_r($result); //输出 Array ( [0] => a [1] => b [2] => c [4] => d [5] =>e ) ?> 注意:array_unique()返回的是一个新建的数组,此函数并不会破坏原来的函数。
  • 167. 4.2.10 在数组中搜索给定的值in_array()函数可以检查数组值的情况,根据值存在的情况,返回TRUE或FALSE值。而使用array_search()函数检查查值存在的情况,如果值存在时,返回这个值的键名,如果查找的值不存在,则返回NULL,array_search()函数的演示代码如下示。 数组中没有要f这个值"; }else{ echo "
    数组中有f这个值,其键名是".$key; } //输出 数组中有f这个值,其键名是5 $key = array_search("s",$array); if($key == NULL){ echo "
    数组中没有要s这个值"; }else{ echo "
    数组中有s这个值,其键名是".$key; } //输出 数组中没有要s这个值 ?>
  • 168. 4.3 遍历数组的3种方法只有在详细了解数组单元的情况下,才可以对数组做出正确的操作,虽然可以使用print_r()函数和var_dump()函数,来查看数组的成员,但是这两个函数,没有返回值可供操作。而遍历数组,才是在实际应用中,最多访问数组的方法。 在本书第2章的语法部分,介绍了循环控制语句,其中使用了foreach语句进行了遍历数组的演示。在本节学习了部分数组函数后,可以结合循环控制语句,来实现更多的数组遍历的方法。
  • 169. 4.3.1 使用while、list与each访问数组list()函数可以把当前数组单元,转换为变量使用。each()函数可以返回数组中当前单元的键名与值,并将数组指针向下移动一步。使用这两个函数,结合while循环语句,就可以实现对数组的遍历。下面演示使用while语句,进行数组遍历的方法,
  • 170. 4.3.2 使用for、foreach 访问数组最常用的遍历数组的就是foreach语句,而且foreach语句也只能用于数组遍历。在实际使用中,可能只是对数组的某一部分进行访问,就不需要对整个数组的单元都遍历一次。这时可以使用for循环语句,就可以实现类似的功能,演示代码如下所示。
  • 171. 4.4 数组的排序使用数组排序函数,可以把排序混乱的数组,进行重新整理,变得易于访问或操作。数组排序函数有很多,在实际使用时,可以根据情况来选择或组合使用。
  • 172. 4.4.1 对数组排序使用sort()函数,可以对已经定义的数组,进行重新排序,使得数组单元从低到高重新索引。sort()函数演示代码如下所示。 "b",1=>"a",3=>"c",4=>"d"); //使用sort对数组排序 if(sort($array) == TRUE){ echo "数组排序成功!"; print_r($array); }else{ echo "数组排序失败"; } //输出:数组排序成功!Array ( [0] => a [1] => b [2] => c [3] => d ) ?>
  • 173. 4.4.2 对数组逆向排序数组逆向排序应使用rsort()函数,函数运行后,使得排序数组单元从高到低重新索引。rsort()函数演示代码如下所示。 "b",1=>"a",3=>"c",4=>"d"); //使用sort对数组排序 if(rsort($array) == TRUE){ echo "数组排序成功!"; print_r($array); }else{ echo "数组排序失败"; } //输出:数组排序成功!Array ( [0] => d [1] => c [2] => b [3] => a ) ?>
  • 174. 4.4.3 对多个数组或多维数组进行排序array_multisort()函数,可以一次对多个数组进行排序,也可以根据多维数组的一维或多维进行排序。与其他数组排序函数一样,每个要排序的数组,都可以使用排序标志来影响排序结果。能影响排序结构的参数值有2类。 (1)排序顺序标志 SORT_ASC - 按照上升顺序排序。 SORT_DESC - 按照下降顺序排序。 (2)排序类型标志 SORT_REGULAR - 将项目按照通常方法比较。 SORT_NUMERIC - 将项目按照数值比较。 SORT_STRING - 将项目按照字符串比较。
  • 175. 4.4.4 将数组顺序打乱使用shuffle()函数,可以把一个数组随机排列顺序,返回一个重建索引的数组。shuffle()函数的演示代码如下所示。 $number) { echo "$key=>$number
    "; } ?> 注意:shuffle()函数返回的数组,将删除原来数组的索引,重新新的索引。
  • 176. 4.4.5 对数组排序并保持索引关系使用sort()或rsort()函数,虽然能对数组进行排序,但是实际应用中,有些重要的数组需要保持单元的索引关系。在排序的同时,保持数组的索引关系,可以使用asort()和arsort()函数。asort()函数是把数组按正向排序,arsort()函数把数组按逆向排序。下面演示这两个函数的使用方法,
  • 177. 4.4.6 对数组按照键名排序使用ksort()、krsort()函数,可以对数组的键名进行排序,并且可以保持键名与值的关联。ksort()函数用于对数组的键名进行正向排序,krsort()函数用于对数组的键名进行逆向排序。下面演示这两个函数的使用方法,代码如清单所示。 清单 ksort()、krsort()函数的使用方法 "Tom","car"=>"tubro","speed"=>"360","level"=>6); //使用ksort()对数组按键名排序 ksort($array); echo "显示排序后的数组:"; print_r($array); echo "
    "; //使用krsort()函数按键名逆向排序 krsort($array); echo "显示排序后的数组:"; print_r($array); ?>
  • 178. 4.4.7 用“自然排序”算法对数组排序所谓的自然排序,就是使用数字的正常排序方法来排序。其排序方法和sort()函数是有区别的。自然排序使用natsort()函数实现,其对单元值的大小写敏感。也可以使用natcasesort()函数对数组排序,natcasesort()函数也是使用自然排序方法,但是其会忽略单元值的大小写。下面演示sort() 、natsort()、natcasesort()函数的区别,
  • 179. 4.4.8 返回一个单元顺序相反的数组使用array_reverse()函数,可以把一个数组的单元按相反顺序排序。array_reverse()函数有2个参数,第1个是要求反的数组。第2个参数为可选,如果其值为TURE,则函数会保留原来的键名。下面演示array_reverse()函数的使用方法,代码如清单4.14所示。 清单4.14 array_reverse()函数使用方法 "; print_r($newArray); //当array_reverse()的第2个参数为TRUE值是. //定义一个用于测试的数组 $array = array("a","17",18,FALSE,array(1,2,3,4,5,6,7,8,9)); $newArray = array_reverse($array,TRUE); echo "
    array_reverse()函数第2个参数为TRUE值时排序后的数组.
    "; print_r($newArray); ?>
  • 180. 4.5 数组的栈操作栈是存储数据的一种结构,这种数据结构把数据使用线性方法保存。其主要特点是“后进先出”。在对于数组操作时,PHP也提供了相应的栈操作函数,使用户可以通过类似栈的方式访问数组。
  • 181. 4.5.1 出栈操作根据栈的“后进先出”的特性,如果操作数组出栈,实际上就是删除了数组的最后一个单元。数组出栈使用array_pop()函数实现,array_pop()函数的演示代码如下所示。
  • 182. 4.5.2 入栈操作数组的入栈操作,就是把新单元添加到数组尾部。数组的如栈操作使用array_push()函数实现,演示代码如下所示。 array_push()函数将新单元添加到数组,而不产生新数组。
  • 183. 4.5.3 将数组开头的单元移出数组虽然可以把数组看成栈来操作,但是其毕竟不是真正的栈。在操作数组中,还是可以有更灵活的方法。数组允许使用函数,将数组开头的单元移出数组,即删除单元。使用array_shift()函数可以实现这个操作,演示代码如下所示。
  • 184. 4.5.4 在数组开头插入一个或多个单元使用array_unshift()函数,可以在数组开始处添加新单元,新单元的个数,由函数的参数值决定。array_unshift()函数的演示代码如下所示。
  • 185. 4.5.5 数组的指针操作数组有两种访问方式:第一种是使用数组下标,即“数组名[键名]”的方式。第二种是使用数组内部指针的方式。 当定义一个数组时,数组的内部指针指向数组的第1个单元,这时可以使用其他数组函数,来取得当前数组单元的键名和值。 数组的指针操作函数主要包括: reset()函数,重置数组内部指针,并返回当前单元的值。如果函数操作的数组为空,函数将返回FALSE值 prev()函数,将数组内部指针向后移动一位,并返回当前单元的值。如果没有更多单元,函数将返回FALSE值。 next()函数,将数组内部指针向前移动一位,并返回当前单元的值。如果没有更多单元,函数将返回FALSE值。 end()函数,将数组内部指针移动到数组最后一个单元,并返回当前单元的值。
  • 186. 4.5.6 获取数组中的当前单元current()函数,可以获取数组内部指针指向单元的值,不移动内部指针。each()函数,可以获取数组内部指针指向单元的键名和值,并且将数组内部指针,向下移动一位。current()、each()函数与循环语句结合,都可以实现对数组的遍历。
  • 187. 4.6 数组的计算数组的计算,包括对数组本身单元的计算,值的计算和键的计算等。对数组本身的计算,可以用来比较两个数组之间的差别。而对数组值的计算,可以在不用遍历数组的情况下,得出数组值的计算结果。本章主要介绍常用的数组计算的函数。
  • 188. 4.6.1 计算数组单元数目在使用for语句实现数组遍历时,使用了计算数组单元数目的函数,即:count()。count()函数不仅可以计算数组的单元个数,也可以对象中的属性个数。 count()函数一共有2个参数,在使用时要注意参数的使用方法。 第1个参数是要计算单元数目的数组,如果这个参数的类型不是数组,那么将返回1。 第2个参数是可选,如果这个参数不为空,其值只能是COUNT_RECURSIVE或1,当此参数的值为其中之一时,count()函数可以遍历多维数组,以计算所有的单元数目。 count()函数的演示代码如下所示。
  • 189. 4.6.2 统计数组中所有的值出现的次数使用array_count_values()函数,可以计算数组中一个值出现的次数。array_count_values()函数的演示代码如下所示。
  • 190. 4.6.3 计算数组的差集计算数组差集的函数主要有3个: array_diff()函数,通过单元值比较,取得参数数组的差集。此函数可以比较两个,及两个以上的数组(即有若干个参数),数组间使用逗号分割。函数运行后,将返回一个数组,数组中记录着,第1个数组中存在,而其他数组没有的单元值。 array_diff_assoc()函数,此函数与array_diff()函数基本相同,唯一不同的是,array_diff_assoc()函数在比较数组时,对单元的健名也进行比较。 array_diff_key()函数,通过键名比较,取得参数数组的差集。此函数可以比较两个,及两个以上的数组(即有若干个参数),数组间使用逗号分割。函数运行后,将返回一个数组,数组中记录着,第1个数组中存在,而其他数组没有的键名。
  • 191. 4.6.4 计算数组的交集计算数组交集的函数主要有3个: array_intersect()函数,通过单元值比较数组,取得参数数组的交集。此函数可以比较两个,及两个以上的数组(即有若干个参数),数组间使用逗号分割。函数运行后,将返回一个数组,数组中记录着第1个数组中存在,同时也存在于其他数组中的单元值。 array_intersect_assoc()函数,此函数与array_intersect ()函数基本相同,唯一不同的是,array_ intersect _assoc()函数在比较数组时,对单元的健名也进行比较。 array_ intersect _key()函数,通过键名比较数组,取得参数数组的交集。此函数可以比较两个,及两个以上的数组(即有若干个参数),数组间使用逗号分割。函数运行后,将返回一个数组,数组中记录着第1个数组中存在,同时也存在于其他数组中的单元值。
  • 192. 4.6.5 计算数组中所有值的乘积、和使用array_product()函数,计算数组中所有值的乘积。使用array_sum()函数,计算数组中所有值的和。这两个函数的演示代码如下所示。
  • 193. 4.7 其他数组函数数组的操作函数很丰富,在介绍了关于数组的排序、栈操作及数组计算函数后,还有几个经常使用的数组函数需要进行介绍。灵活使用这些函数,可以为编写代码提供更多的途径。
  • 194. 4.7.1 数组与变量之间的转换在实际应用中,为了方便使用,通常会把变量存放在数组中。而为了方便数组单元的访问,也经常要把数组单元转换来变量。使用compact()函数,函数运行后将返回一个数组,并把其参数表内的变量转换为数组的单元。与之相对应的是extract()函数,其可以把数组中的单元,转换为变量使用。下在演示这两个函数的使用方法,
  • 195. 4.7.2 合并数组使用array_merge()函数,可以把若干个数组进行合并,转换为一个数组。array_merge()函数在转换2维或多维数组时,把1维以后的数组,都做为1个单元返回。而使用array_merge_recursive()函数,可以在保持现有数组结构的情况下,对在同一维的数组进行合并。下面演示合并数组的方法,代码如清单所示。
  • 196. 4.7.3 从数组中随机取出单元像可以产生随机数一样,也可以使用数组函数从数组中随机取出1个或几个单元。使用array_rand()函数就可以实现这个操作。 array_rand()函数有2个参数,第1个是必选参数,其值是要取出单元的数组。第2个参数是可选的,其类型为整型,如果第2个参数没有设置,函数将返回随机单元的键名,如果第2 个参数已经设置,函数将返回数组中,相应数量的单元组成的数组,函数的演示代码如下所示。
  • 197. 4.8 常见问题本章主要学习了数组的基本操作,及部分数组函数。在实际应用中,数组的使用涉及到了各个方面。灵活的使用数组和数组函数,可以有效的减少程序代码。 对于数组操作,最容易出错的地方就是键名与值的操作。
  • 198. 4.8.1 数组的键名数组的键名有两种,一种是数字键名,一种是字符串键名。在使用有些数组函数时,对这两种类型的键名的计算是不同的。比如要合并数组,比如有相同的字符串键名,函数一般都会去使用新值,覆盖旧值。而数字键名,通常是把其附加在数组后。所以在使用类似的数组函数时,一定要注意有相同键名的单元的处理。 在简单数组操作时,对于不是很关键的键名,可以不用去费心管理。但是如果键名对于程序运行来说,要求不能出错,那么在使用数组函数时,一定要注意。因为很多数组函数,特别是合并数组和栈操作时,都可以改变数组单元的键名。
  • 199. 4.8.2 数组函数的参数通常情况下,数组的值对于数组函数来说,都是有效的。但是如果数组的单元值出现了NULL、空字符串时,会对有些数组函数产生影响,典型的就是current()函数。 虽然有一些数组函数可以接收若干参数,但是在使用时,其参数的数量最好不要过多,过多的参数,还是会影响函数的执行效率。
  • 200. 第5章 目录与文件第4章讲述了数组的工作原理、访问方法和常用函数。但是数组毕竟是存在于内存中的,不能长久的保存供以后使用,这就要求程序员对数组以及内存中有用的变量进行保存。数据的保存有很多形式,通过这一章的学习,就能找到其中的一种解决方案。在本章中,为了提高读者的动手能力,有些目录或文件并没有建立,读者可以根据系统提示的错误,找到解决的方法。
  • 201. 5.1 操作目录目录在文件系统中是一个重要的概念,专业的术语把其解释成存储在磁盘上的文件及其他目录的索引,也可以将其视为一个文件夹,在文件夹中,可以放置其他的文件或文件夹,从而使得计算机的文件系统井井有条。最顶层的目录称为根目录,在PHP中用“/”或“\\”代表。“.”代表当前目录,“..”代表上级目录。
  • 202. 5.1.1 打开目录句柄目录和文件的访问,都是通过句柄实现的,下边演示的是怎么样打开一个目录句柄,以便其他目录函数使用,代码如下所示。
  • 203. 5.1.2 新建目录新建和删除目录属于文件系统函数,为了方便读者,把这两个函数放在本节中进行统一讲解。新建目录演示代码如下所示。
  • 204. 5.1.3 删除目录本函数会试图删除要求的目录,但是目录必须为空并具有相应的权限。代码如下所示。 删除目录要注意的问题: 以上代码尝试删除根目录下名为“temp”的目录。 目录删除成功将返回TRUE,如果删除失败将返回FALSE,并显示错误信息,可以使用“@”符号来抑制错误信息的输出。
  • 205. 5.1.4 取得当前工作目录此函数用于获取当前的工作目录,通过对返回值的判断,确定当前操作的目录是否正确。代码如下所示。 获取当前工作目录时要注意的问题: 此函数运行时将返回一个字符串,记录当前目录情况。 失败将返回FALSE。
  • 206. 5.1.5 改变当前目录回FALSE。通过操作此函数,可以改变当前目录,以定位到可用资源,改变当前目录的演示代码如下所示。 "; //改变当前目录 chdir('html'); // 显示当前目录 echo getcwd()."
    "; ?> 在使用chdir()函数时,要注意以下问题: 本例中的chdir()将当前目录更改为“html”。 成功返回TRUE,失败将返
  • 207. 5.1.6 从目录句柄中读取条目使用readdir()函数,会从目录句柄中读取下一个文件的文件名。配合while循环可以实现对目录的遍历,代码如下所示。 ’; /* 这是正确地遍历目录方法 */ while(false !== ($file = readdir($handle))){ echo $file.’
    ’; } closedir($handle); }else{ echo “打开目录错误!”; } ?>
  • 208. 5.1.7 列出指定路径中的文件和目录使用scandir()函数可以实现这个功能,并能按照参数对列出的目录进行排序,代码如下所示。
  • 209. 5.1.8 关闭目录句柄在使用完opendir()打开的目录句柄后,应使用closedir()进行关闭,以节省服务器资源,代码如下所示。
  • 210. 5.1.9 directory类为了方便用户对目录的操作,PHP提供了一个类似使用面向对象机制的函数,它实际上相当于使用readdir()、rewind()、closedir()三个函数实现遍历目录的功能,代码如下所示。 handle."
    "; echo "路径:".$dir->path."
    "; while(false !== ($entry = $dir->read())){ echo $entry."
    "; } $dir->close(); ?>
  • 211. 5.2 操作文件的一般方法上一节学习了使用相关目录函数对目录进行新建、打开、删除、读取及关闭等操作。在这一节中将学习操作文件的一般步骤,即:打开、读取、写入、关闭。而本节很多知识与上一节是相通的,如目录的打开与文件的打开,只不过它们使用的函数不一样而已。
  • 212. 5.2.1 打开文件在学习打开文件之前先看一段代码。代码如下所示。
  • 213. 5.2.2 读取文件文件操作中最频繁的应该是读取操作,所以在读取文件时一定要注意优化代码,这样才能从代码层面提高程序质量。下面是一则读取文件的例子,代码如下所示。 代码里的fread(),就是基本的读取文件函数,它的原型如下所示。 string fread ( int $handle, int $length )
  • 214. 5.2.3 写入文件写入文件操作具有重大的意义,软件运行时计算出来的数据,用户提交、修改的信息,通常都需要保存下来,供以后使用。而把数据写入文件,就是其中的解决方案之一。为了方便理解,先看一段简单的写入文件的程序,代码如下所示。 代码里的fwrite(),就是写入文件函数,它的原型如下所示。 int fwrite ( resource $handle, string $string [, int $length] )
  • 215. 5.2.4 关闭文件关闭文件正确的说法是关闭一个已经打开的文件句柄,在上面几个小节的学习中,都使用了这个函数,即:fclose(); fclose()只有唯一的一个参数,即文件句柄。使用fopen()或fscokopen()成功打开的句柄,都可以使用其来关闭。
  • 216. 5.3 文件的基本操作在上一节中学习了操作文件的一般步骤,以及一些基础的文件系统函数。本节是在上节内容的基础上学习更多的文件系统函数及操作文件的技巧。
  • 217. 5.3.1 在当前目录新建文件新建文件使用的函数还是fopen(),只不过是通过对fopen()的$mode值的选择来完成。在编写程序时,很多情况下要求某个文件的存在,作为程序的运行条件,这时就可以使用下面的代码: 使用fopen()函数新建文件时,要注意以下几个问题: 这段简单的代码完成了在当前目录新建一个名为“model.txt”文件,注意如果fopen()的第一个参数是“html/model.txt”时,程序会在当前目录的子目录“html”,创建“model.txt”文件。 即使再短的打开文件操作,也应该使用关闭句柄函数。 新建文件时,很容易因为文件存在或权限问题而失败,所以在新建文件前,应进行相关的检查。
  • 218. 5.3.2 新建临时文件很多情况下,变量会被保存下来,但等程序运行完成后,这些保存变量的文件就要被删除以节省服务器空间。但这个过程很麻烦的,程序员要记录过程中产生的文件的名称,还要使用函数对其进行删除操作。而PHP为了使这一工作能够快速有效的完成,为程序员提供了一个函数,即:tmpfile()函数,函数的演示代码如下所示。
  • 219. 5.3.3 新建具有唯一文件名的文件tempnam()函数与tempfile()函数的使用方法都是一样的,唯一区别的tempnam()函数将产生一个具有唯一文件名的文件。
  • 220. 5.3.4 删除文件使用unlink()函数,可以删除程序运行时产生的临时文件,删除文件的演示代码如下所示。 unlink()函数有1个参数,即要删除文件的路径与文件名。 注意:使用unlink()函数删除文件时,如果删除成功,函数将返回TRUE值,如果删除失败,函数将返回FALSE值。
  • 221. 5.3.5 复制文件复杂文件就是根据源文件的内容,建立一个拥有同样内容的新文件。在不想破坏操作文件时,可以通过复制源文件,对新产生的文件进行操作。复制文件使用copy()函数实现,演示代码如下所示。
  • 222. 5.3.6 移动、重命名文件或目录使用rename()函数,可以移动、重新命名一个已经存在的文件或目录,演示代码如下所示。
  • 223. 5.4 写入文件前面介绍过使用fwrite()函数写入文件的方法,在文件系统函数中,还可以使用fputs()、fputcsv()、file_put_contents()函数来把内容写入文件。 fputs()是fwrite()函数的别名,这两个函数的实现的功能是一样的,fputcsv()函数可以把数组按指定的规则写入文件,而file_put_contents(),可以把一个字符串直进写入文件。这3个函数各有特点,在实际应用中,就根据情况选择使用。
  • 224. 5.4.1 写入文件写入文件使用fwrite()函数,其有3个参数,第1个参数是必选参数,其值是使用fopen()函数,以及类似函数打开的文件句柄。第2个参数也是必选参数,其值是要写入文件的字符串变量。第3个参数是可选参数,如果指定了这个参数的值,fwrite()函数将在写入指定长度字符串后结束运行。下面演示fwrite()函数的使用方法,代码如清单所示。
  • 225. 5.4.2 CSV文件格式与文件存储CSV是一种比较常用的文件格式,一般以.csv作为文件的扩展名。CSV格式把文件的一行看作是一条记录,记录里的字段使用逗号分割。典型的CSV格式文件的内容如下所示。 用户名,密码,部门,职称 user1,1,秘书处,科员 user2,2,办公室,科员 user3,3,后勤部,科员 注意:在以CSV格式存储的文件里,逗号前后的空格会被忽略。第1条记录可以是字段名。如果字段中包含有逗号、换行符、空格、双引号,该字段必须用双引号括起来。
  • 226. 5.4.3 将字符串写入文件使用file_put_contents()函数,可以把一个字符串变量写入文件。file_put_contents()函数与fwrite()函数的不同之处在于,fwrite()函数需要一个fopen()或类似函数创建的句柄,file_put_contents()只需要运行函数本身。使用file_put_contents()写入文件的方法如下所示。
  • 227. 5.5 文件的读取与指针文件读取函数分为两种,一种是把文件全部读入内存的函数,如file_get_contents()函数;一种是依靠文件内部的指针,来读取文件内容的函数,如fread()函数。这两种函数都有其优缺点,在实际应用中,可以根据情况选择。
  • 228. 5.5.1 把整个文件读入到数组中file()函数读取文件后,返回1个数组,其中数组的每个单元对应着文件的1行(包括换符)。file()函数不仅可以读取本地文件,还可以从网页中读取信息。下面演示file()函数读取文件的方法,代码如清单5.4所示。 清单5.4 file()函数读取文件的方法 "; } //使用file()函数读取网页内容 $webPage = file("http://www.baidu.com/"); //遍历file()函数返回的数组 foreach($webPage as $line){ echo $line; } ?>
  • 229. 5.5.2 将文件读取到字符串使用file_get_contents()函数,可以把参数指定的文件,整个读取到1个字符串变量中。下面演示file_get_contents()函数读取文件的方法,代码如清单所示。 清单 file_get_contents()函数读取文件的方法
  • 230. 5.5.3 使用指定格式读取文件fscanf()函数,可以读取已经文件中的数据,并根据指定的格式进行格式化,从而返回一个数组。fscanf()函数有2个参数,第1个参数是需要读取的文件的句柄,第2个参数是格式化文件内容的格式。下面演示使用fscanf()函数读取文件的方法,代码如清单所示。 清单 fscanf()函数读取文件的方法 "; } //关闭文件句柄 fclose($fh); ?>
  • 231. 5.5.4 解析一个配置文件通常所说的配置文件,都是以.ini为扩展名的文本文件。配置文件中,记录着程序要运行时需要的各个参数,典型的配置文件内容如下所示。 ; 配置文件注释使用';'符号 ; 配置文件前的说明 [database] user = guest password = client db = online [site] title = "PHP入门" URL = "http://www.rzphp.com"
  • 232. 5.5.5 获取、设置文件内部指针位置文件内部指针,是文件操作系统内部的数据指针,用于标注文件当前的读写位置。使用ftell()函数可以查看当前文件内部指针的位置。使用fseek()函数,则可以快速的把文件的内部指针,指向参数指定的位置。 ftell()函数只有1个参数,其值是使用fopen()或类似函数创建的句柄。ftell()函数运行后,将返回当前文件指针的位置。fseek()函数有3个参数,第1个参数是必选参数,其值是使用fopen()函数,以及类似函数打开的文件句柄。第2个参数也是必选参数,其值是数字,代表指针移动到文件处的位置。
  • 233. 5.5.6 从文件指针处读取字符使用fgetc()函数,可以从当前文件指针处,读取一个字符并返回。下面演示fgetc()函数的使用方法,代码如清单所示
  • 234. 5.5.7 从文件指针处读取数据使用fgets()函数,可以读取文件指针指向的当前行,并返回一个记录当前行内容的字符串。fgets()函数包括2个参数,第1个参数是必选参数,其值是fopen()或类似函数创建的文件句柄,第2个参数是可选参数,其值用于指定读取文件的大小。
  • 235. 5.5.8 CSV文件格式与文件读取使用fgetcsv()函数,将读取指定文件的当前行,使用CSV格式解析出字段,并返回1个包含这些字段的数组。fgetcsv()函数有4个参数,第1个参数是必选参数,其值是使用fopen(),以及类似函数创建的文件句柄。第2个参数为可选参数,其值用于指定读取内容的长度。第3个参数是可选参数,用于指定字符分界符。第4个参数是可选参数,用于指定字符环绕符。
  • 236. 5.5.9 从文件指针处读取数据并过滤HTML使用fgetss()函数,可以从文件指针处读取一行数据,并过滤掉文件中的HTML与PHP标记。下面演示使用fgetss()函数的使用方法,代码如清单所示。 清单 fgetss()函数使用方法
  • 237. 5.5.10 重置文件指针的位置使用rewind()函数,可以重置当前文件的指针位置,使指针返回到文件头。下面演示rewind()函数的使用方法,代码如清单所示。 清单 rewind()函数使用方法 "; echo "使用fseek重定位指针到100"; fseek($fh,100); echo "显示当前指针:".ftell($fh)."
    "; echo "使用rewind()函数重置文件指针"; rewind($fh); echo "显示当前指针:".ftell($fh)."
    "; ?>
  • 238. 5.5.11 文件尾部指针测试使用feof()函数,可以检查当前文件的内部指针,是否已经处于文件尾部。feof()函数经常与while()循环语句配合,实现读取文件。feof()函数据的演示代码如下所示。
  • 239. 5.6 文件的上传与下载文件的上传与下载,都需要使用文件系统函数来完成。本节将介绍在文件上传与下载过程中,使用到的文件系统函数。处理上传文件的函数是move_uploaded_file(),实现文件下载的函数是fpassthru()。
  • 240. 5.6.1 处理上传文件在本书第2章,介绍了使用HTML产生上传文件变量的方法。产生上传文件变量的表单,只能把要上传的文件,上传到系统的临时文件夹,要想把这个临时文件保存到指定的位置,需要使用move_uploaded_file()函数。 move_uploaded_file()函数有2个参数,第1个参数是必选参数,其值是一个合法的上传文件名,第2个参数是必选参数,其值是由目录和文件名组成的字符串,代表临时文件存储的位置和文件名。
  • 241. 5.6.2 读取文件到输出缓冲区使用readfile()函数,可以读取参数指定的文件到输出缓冲区,被输入到缓冲区的内容,将在浏览器上显示。下面演示readfile()函数的使用方法,代码如清单所示。 清单 读取文件并输出到缓冲区
  • 242. 5.6.3 将文件输出到缓冲区使用fpassthru ()函数,可以把参数指向的文件,输出到缓冲区。下面演示fpassthru()函数的使用方法,代码如清单所示。 清单 将文件输出到缓冲区
  • 243. 5.6.4 实现文件下载实现文件下载,需要两个方面的条件:一是向浏览器发送正确的报头,二是把文件输出到缓冲区。本小节使用readfile()函数,来实现文件的下载功能,代码如清单所示。 清单 实现文件下载
  • 244. 5.7 文件属性的操作文件属性包括文件的大小、修改时间、所有者、权限、类型等信息。通过了解文件的属性,可以帮助程序员判断文件现在的状态,对文件实现更细致的管理。
  • 245. 5.7.1 获取文件统计信息使用stat()函数,可以获取参数指向文件的统计信息,下面演示stat()函数的使用方法,代码如清单所示。 清单 stat()函数使用方法 $value){ echo "键名:$key:单元值:$value
    "; } ?>
  • 246. 5.7.2 通过文件句柄获取文件统计信息使用fstat()函数,可以获取文件统计信息。下面演示fstat()函数的使用方法,代码如清单所示。 清单 fstat()函数使用方法 $value){ echo "键名:$key:单元值:$value
    "; } ?>
  • 247. 5.7.3 获取文件相关信息虽然可以使用stat()、fstat()函数,取得文件属性,但是每次使用文件属性时,都需要对数组进行访问。PHP提供了更加简捷的方法,来访问文件的某一个文件属性。这些函数主要包括: fileatime()函数,用于取得文件的上次访问时间。 filectime()函数,用于取得文件的inode修改时间。 filegroup()函数,用于取得文件的组。 fileinode()函数,用于取得文件的inode。 filemtime()函数,用于取得文件修改时间。 fileowner()函数,取得文件的所有者。 fileperms()函数,取得文件的权限。 filesize()函数,取得文件大小。 filetype()函数,取得文件类型。
  • 248. 5.7.4 修改文件访问和修改时间使用touch()函数,可以改变指定文件的访问和修改时间。下面演示touch()函数的使用方法,代码如清单所示。 清单 修改文件时间属性 {$filename}的修改时间是:".date("F d Y H:i:s.", filemtime($filename)); //使用指定时间,作为文件的最后访问和修改时间 touch($filename,time()-1000); clearstatcache();//清除文件属性缓冲 echo "
    {$filename}的最后访问时间是:".date("F d Y H:i:s.", fileatime($filename)); echo "
    {$filename}的修改时间是:".date("F d Y H:i:s.", filemtime($filename)); //使用指定时间,作为文件的最后访问时间 clearstatcache();//清除文件属性缓冲 touch($filename,time()-2000,time()+2000); echo "
    {$filename}的最后访问时间是:".date("F d Y H:i:s.", fileatime($filename)); echo "
    {$filename}的修改时间是:".date("F d Y H:i:s.", filemtime($filename)); ?>
  • 249. 5.7.5 改变文件所属的组使用chgrp()函数可以改变文件所属的组。chgrp()函数的演示代码如下所示。 注意:只有超级用户可以任意修改文件的组。
  • 250. 5.7.6 改变文件所有者使用chown()函数可以改变文件的所有者。chown()函数的演示代码如下所示。 注意:只有超级用户可以任意修改文件的所有者。
  • 251. 5.7.7 改变文件权限文件权限可以设定当前文件,被所有者、组用户和公共用户访问的权限。其值由4个八进制数表示,第1个八进制数是0,其后每1个八进制数由3个数字相加来表示访问权限:1表示文件可执行,2表示文件可写,4表示文件可读。 文件权限第1个数表示所有者对文件的访问权限,如果所有者对文件有全部访问权限,那么其值应该是1+2+4=7。 文件权限第2个数表示组用户对文件的访问权限,如果组用户对文件有可读、可执行的权限,那么其值应该是1+4=5。 文件权限第3个数表示公共用户对文件的访问权限,如果公共用户对文件只有可读权限,那么其值应该是1。
  • 252. 5.8 文件操作的错误处理在文件操作过程中,由于权限、路径、文件名等不确定的因素,文件系统函数在操作文件时,会产生错误,为了避免错误产生,应在操作文件之前,就对文件进检测。本节主要介绍用于文件系统错误处理的函数。
  • 253. 5.8.1 判断给定文件名是否是目录由于文件与目录的操作函数是不能通用的,所以在不确定给定的变量是文件名或目录的情况下,可以使用is_dir()函数进行检测,
  • 254. 5.8.2 判断给定文件名是否可执行使用is_executable()函数,可以检测指定文件是否为可执行文件,如果测试文件存在,并可以执行,函数将返回TRUE,否则返回FALSE,is_executable()函数演示代码如清单所示。 清单 判断文件是否可执行 "; }else{ echo "文件{$file}不可执行
    "; } } //定义存储文件名的变量 $file = "html/contents.txt"; //使用函数判断这些变量 isexec($file); ?>
  • 255. 5.8.3 判断给定文件名是否是文件使用is_file()函数,可以检测指定文件是否为文件,如果是文件函数将返回TRUE,否则返回FALSE,is_file()函数演示代码如清单所示。
  • 256. 5.8.4 判断指定文件是否可读服务器端的脚本程序,访问文件系统时,使用的一般都是公共用户。由于公共用户的权限会受到一些限制,当文件权限不确定的情况下,可以使用is_readable()函数,测试指定文件是否可读。is_readable()函数演示代码如清单所示。
  • 257. 5.8.5 判断文件是否是通过HTTP POST上传的使用HTML表单通过POST上传文件时,出于安全方面的考虑,可以使用is_uploaded_file()对上传的文件进行检测,is_uploaded_file()有1个必选参数,其值是文件上传变量的临时文件名。下面演示is_uploaded_file()函数的使用方法, is_uploaded_file()函数运行后,如果临时文件是使用权HTTP POST方式上传的,将返回TRUE值,否则返回FALSE值。
  • 258. 5.8.6 判断给定的文件名是否可写当文件权限不确定的情况下,可以使用is_writable()函数,测试指定文件是否可写。is_writable()函数演示代码如清单所示。 清单 判断文件是否可写 "; }else{ echo "{$file}不可写
    "; } } //定义存储文件名的变量 $file1 = "html/contents.txt"; $file1 = "html/arraycontents.txt"; //使用函数判断这些变量 testwrite($file1); testwrite($file1); ?>
  • 259. 5.8.7 检查文件或目录是否存在在使用文件系统函数时,除了权限问题可以引起错误外,要操作的文件或目录是否存在,也经常引发错误。在PHP中,可以使用file_exists()函数,检查指定目录或文件是否存在。下面演示file_exists()函数的使用方法,代码如清单所示。
  • 260. 5.9 路径与磁盘操作文件系统函数操作文件的同时,一定会涉及到对路径的相关操作。路径又分为相对路径和绝对路径,相对路径是以操作的文件所在目录为起点的路径;绝对路径是以当前文件所在盘符为起点的路径。本节主要介绍关于路径和磁盘方面的函数。
  • 261. 5.9.1 获取文件路径的信息使用pathinfo()函数,可以对指定的路径和文件名进行解析,并返回一个数组。下面演示pathinfo()函数的使用方式,代码如清单5.30所示。 清单5.30 获取文件路径的信息 $value){ echo "$key=>$value
    "; } ?>
  • 262. 5.9.2 获取路径中的文件名部分虽然pathinfo()函数返回的数组,已经包括了指定路径与文件名的文件名部分,但其值是保存的数组里的。PHP提供了basename()函数,可以快速的获取指定文件的文件名部分,而不用从数组中读取。下面演示basename()函数的使用方法,代码如清单所示。 清单 获取路径中的文件名部分
  • 263. 5.9.3 获取路径中的目录部分使用dirname()函数,可以快速的获取指定文件的路径部分。下面演dirname()函数的使用方法,代码如清单所示。 清单 获取路径中的路径部分 dirname()函数是根据目录分割符,来取得路径中文件名部分的。在windows系统下,“/”与“\”都可以作为目录分割符,其他系统使用“/”作为分割符。basename()函数运行后,将返回一个字符串,字符串中记录着指定路径中的文件名。
  • 264. 5.9.4 寻找与模式匹配的文件路径glob()函数可以根据指定的条件,来寻找与条件相符的文件或目录,并通过数组返回。下面演示glob()函数的使用方法,代码如清单所示。 清单 寻找与模式匹配的文件路径 "; } ?>
  • 265. 5.9.5 获取目录中的可用空间 disk_free_space()函数可以根据文件系统和磁盘分区,返回指定目录当前可以使用的字节数。下面演示disk_free_space()函数的使用方法,代码如清单所示。 清单 获取目录中的可用空间 c:可用空间为:".$m; ?>
  • 266. 5.9.6 获取一个目录的磁盘总大小disk_total_space()函数可以根据文件系统和磁盘分区,返回指定目录的空间大小。下面演示disk_total_space()函数的使用方法,代码如清单所示。 清单 获取目录的磁盘空间大小 c:盘大小为:".$m."M"; ?>
  • 267. 5.10 常见问题在PHP中使用文件系统函数,最经常出现问题的地方,就是文件的权限问题,出于安全方面的考虑,有些文件或目录是不支持的读取的,所以在操作类似文件或目录时,要注意使用相关的函数进行检查,其次在二进制文件读写时,也要注意标记的使用。
  • 268. 5.10.1 关于文件读取在文件系统函数中,关于操作文件容易出错的地方,都可以通过函数来检测并处理。但是在操作二进制文件时,一定要注意函数的选择,在本章的介绍中,读取和写入文件的函数,都标注了是否能安全的使用于二进制的操作,同时在读取和写入二进制文件时,注意使用“b”操作符。
  • 269. 5.10.2 文件系统函数的错误信息在本章中的示例代码中,制造了几个错误,这些错误都是在操作文件时,经常出现的,原因大部分是因为路径和文件不存在,读者在执行这些代码时,可以根据错误提示,来解决这些问题,当在实际应用中出现相关错误时,可以轻松解决。