PHP MySQL 入门教程(一)

原文:Beginning PHP and MySQL

协议:CC BY-NC-SA 4.0

一、PHP 简介

技术民主化指的是越来越多的人可以使用技术的过程。也许没有比互联网更强大的民主化仲裁者了,互联网已经成为全球开发者构建和共享开源软件的平台。 1 这个软件反过来又被用来驱动财富 50 强企业、主权国家、教育机构、创业公司、各种组织和个人拥有的数百万个网站。

虽然有很多协作开发技术的优秀例子,它们似乎是凭空出现,成为互联网技术领域的主导者(Apache web server,以及 Perl、Python 和 Ruby 语言都出现在脑海中),但可能没有一种语言像 PHP 语言那样获得如此广泛的关注。20 世纪 90 年代中期,加拿大/丹麦软件开发人员拉斯马斯·勒德尔夫创建了这个项目,以增强他个人网站的功能,他很快就开始将这些增强功能背后的代码提供给其他人,并将这个项目命名为个人主页,或 PHP。其余的,正如他们所说,都是历史了。

根据 2013 年 1 月 Netcraft 的一项调查,每一个后续版本提交增强功能和漏洞修复的贡献者数量都有所增加,此外用户数量也呈双曲线增长,从 20 世纪 90 年代中期的几十个增加到惊人的 2.44 亿个网站(包括脸书、维基百科、思科 WebEx 和 IBM 等)。在 web 开发人员有如此多的高质量选项可供选择的环境中,PHP 似乎无处不在,这确实是一个惊人的成就。在 2016 年和 2017 年,据报道3PHP 在 82%的已知编程语言的 Web 服务器上使用。

那么,究竟是什么让 PHP 成为如此吸引人的语言呢?在这一章中,我希望提出这样的论点,向您介绍这种语言的主要特性,重点是当前版本,并调查在许多方面增强这种语言的巨大 PHP 生态系统。本章结束时,你将学会以下内容:

  • PHP 语言的哪些关键特性对初学者和专家程序员都有如此大的吸引力?

  • PHP 7 的当前主要版本(推荐使用的版本)提供了什么,以及在即将到来的版本中会有什么。

  • PHP 生态系统如何以无数种方式扩展 PHP 的功能。

这本书的内容集中在 PHP 作为构建 web 应用的脚本语言,但是这种语言还可以有更多的用途。它可以在各种平台上使用,从小型单板计算机(如 Raspberry Pi)到大型大型机系统(如 IBM System 390),以及介于两者之间的任何系统。PHP 通常用作管理任务的命令行工具,它可以用于运行 CRON 作业,与 web 应用共享一个大型代码库。

PHP 的主要特性

每个用户都有使用 PHP 构建他们梦想中的 web 应用的特定原因,尽管人们可能会认为这些动机可以分为四类:实用性、功能、可能性和价格。

实际

PHP 的存在有一个简单的原因:将动态内容引入静态的 web 环境。如今,整个网站都是动态组装的;但是,仍然有很多机会向页面添加非常简单的动态内容,比如搜索输入框的自动完成。PHP 很容易适应这个范围的两端,由于入门门槛低,它很适合新程序员。例如,一个有用的 PHP 脚本可以只包含一行代码;与许多其他语言不同,没有必要强制包含库。例如,下面的启用 PHP 的网页代表一个有效的 PHP 脚本,其中从<?php?>之间的所有内容都将被视为代码部分。其他所有内容都是静态 HTML,不加处理地传递给客户端:

<html>
<head>
<title>My First PHP Script</title>
</head>
<body>
<?php echo "Hello, world!"; ?>
</body>
</html>

当客户机请求包含这一行代码的网页时,服务器将执行脚本中 PHP 代码的部分(下一章将详细介绍),字符串Hello, world!将嵌入到页面中原始代码所在的位置。当然,如果有人对输出静态文本感兴趣,那么首先也可以使用普通的 HTML,所以让我们考虑第二个例子,它包含更有趣的内容,即今天的日期(为了可读性,我先不把这些例子封装在<?php?> PHP 分隔符中,它们让服务器的 PHP 解释器知道应该执行脚本的哪些部分):

echo date("F j, Y");

如果今天是 2017 年 11 月 2 日,那么您会看到网页中的日期输出如下

November 2, 2017

如果这种特殊的日期格式不符合您的需要,您可以使用一组不同的格式说明符,例如

echo date("m/d/y");

一旦执行,您将看到相同的日期呈现为

11/08/17

如果这段代码看起来晦涩难懂,请不要担心。在后面的章节中,PHP 语法将被详细解释。目前,试着了解事情的要点。

当然,输出动态文本实际上并没有触及 PHP 功能的表面。因为 PHP 首先是一种 web 开发语言,所以从逻辑上讲,它包含了各种有趣的特性,能够执行诸如文本处理、与操作系统对话以及处理 HTML 表单等任务。考虑到文本处理,PHP 实际上提供了超过 100 个函数(执行特定任务的代码块),这些函数似乎可以用任何可以想到的方式操作文本。例如,您可以使用ucfirst()函数将字符串的第一个字符转换成大写:

echo ucfirst("new york city");

执行这一行会产生

New york city

虽然比原文有所改进,但结果仍然不正确,因为三个单词都应该大写。使用ucwords()函数修改您的示例,如下所示:

echo ucwords("new york city");

运行修改后的代码会产生

New York City

正是我们要找的!事实上,PHP 提供了以无数种方式操纵文本的函数,包括计算单词和字符,删除空白和其他不需要的字符,替换和比较文本,等等。

无论是日期格式化、字符串操作、表单处理,还是许多其他任务,PHP 语言通常都提供了非常实用的解决方案,希望这几个例子能够说明这一点。在接下来的章节中,我将返回数百个这样的例子!

力量

PHP 语言可以用称为扩展的库(实现某些行为的代码集合,比如连接到电子邮件服务器)来扩展。其中许多是与语言捆绑在一起的,或者可以通过 PECL 这样的网站下载。总的来说,这些库包含超过 1,000 个函数(同样,函数是执行特定任务的代码块),此外还有数千个第三方扩展。虽然您可能已经知道 PHP 与数据库交互、操纵表单信息和动态创建页面的能力,但是当您得知 PHP 还可以做以下事情时,可能会感到惊讶:

  • 与多种文件格式互操作,包括 Tar、Zip、CSV、Excel、Flash 和 PDF。

  • 通过将密码与语言词典和容易破解的模式进行比较,评估密码的可猜测性。

  • 解析和创建常见的数据交换格式,如 JSON 和 XML,这两种格式在构建与 Twitter 和脸书等第三方服务交互的 web 应用时已经成为事实上的标准。

  • 管理文本文件、数据库、微软活动目录中的用户帐户信息,并与脸书、GitHub、谷歌和 Twitter 等第三方服务接口。

  • 创建文本和 HTML 格式的电子邮件,并与邮件服务器协同工作,将这些电子邮件发送给一个或多个收件人。

其中一些特性可以在本地语言中获得,而其他特性可以通过在线资源(如 Composer、PHP 扩展和应用库(PEAR)和 GitHub)等第三方库获得,这些库作为数百个易于安装的开源包的库,以无数种方式进一步扩展 PHP。

PHP 还提供了一个可扩展的基础设施,使得集成用 c 编写的功能成为可能。其中许多功能都可以在 PECL 资源库( https://pecl.php.net )中找到。PECL 是 PEAR 扩展代码库的首字母缩写。

可能性

PHP 开发人员很少受限于任何单一的实现解决方案。相反,用户通常充满了语言提供的选择。例如,考虑 PHP 的一系列数据库支持选项。为超过 25 种数据库产品提供了本机支持,包括 IBM DB2、Microsoft SQL Server、MySQL、SQLite、Oracle、PostgreSQL 等。也有几种通用的数据库抽象解决方案,其中最流行的是 PDO ( https://www.php.net/pdo )。PDO 是 PHP 的一个核心特性,它与大多数 PHP 发行版捆绑在一起,默认情况下是启用的。

最后,如果你正在寻找一个对象关系映射(ORM)解决方案,像 Doctrine ( https://www.doctrine-project.com )这样的项目应该非常适合。

PHP 前面提到的灵活的字符串解析能力为不同技能的用户提供了机会,不仅可以立即开始执行复杂的字符串操作,还可以快速地将类似功能的程序(如 Perl 和 Python)移植到 PHP 上。除了近 100 个字符串操作函数之外,还支持基于 Perl 的正则表达式格式(在 5.3 版之前还支持基于 POSIX 的正则表达式,但在 PHP 7 中已被弃用和删除)。

你更喜欢包含过程编程的语言吗?拥抱面向对象的范例怎么样?PHP 对两者都提供了全面的支持。尽管 PHP 最初只是一种过程语言,但开发人员后来意识到提供流行的 OOP 范例的重要性,并采取措施实现了一个广泛的解决方案。这并没有取代这种语言的过程性质,而是增加了一种新的使用方式。

这里反复出现的主题是 PHP 允许您以很少的时间投入快速利用您当前的技能。这里给出的例子只是这种策略的一小部分,这种策略在语言中反复出现。

价格

PHP 是开源软件,可以免费下载并用于个人和商业用途! 4 开源软件和互联网形影不离。Sendmail、Bind、Linux 和 Apache 等开源项目在整个互联网的持续运行中扮演着重要的角色。虽然不必支付辛苦赚来的钱肯定是开源软件最吸引人的方面之一,但其他几个特征也同样重要:

  • 摆脱大多数商业产品强加的许多许可限制:开源软件用户摆脱了商业对手的绝大多数许可限制。尽管许可证变体之间确实存在一些差异,但是用户可以自由地修改、重新发布和集成软件到其他产品中。

  • 开放开发和审计过程:尽管并非没有事故,开源软件长期以来享有一流的安全记录。如此高质量的标准是开放开发和审计过程的结果。因为任何人都可以免费查看源代码,所以安全漏洞和潜在问题通常可以很快被发现和修复。开源倡导者 Eric S. Raymond 对这一优势做了最好的总结,他写道:“如果有足够多的眼球,所有的错误都是肤浅的。”

  • 鼓励参与:开发团队不限于某个特定的组织。任何有兴趣和能力的人都可以自由加入这个项目。成员限制的消除极大地增强了给定项目的人才库,最终有助于更高质量的产品。

  • 低运营成本 : PHP 在低端硬件上高效运行,需要时很容易扩展,很多机构以较低的每小时成本提供初级/入门级资源。

PHP 的现状

在撰写本文时,PHP 当前的稳定版本是 7.1,尽管在您阅读本书时,版本号无疑已经向前发展了。不用担心;尽管我使用的是 7.1 的测试版来构建和测试这些例子,但你在本书中尝试的任何例子无疑都可以很好地与你安装的 PHP 版本兼容(下一章将详细介绍)。PHP 5.x 和 PHP 7.x 就是这种情况。我建议您至少使用 7.x 版本,以便利用这个版本提供的很酷的新功能、巨大的性能改进和正在进行的安全/错误修复,尽管我一定会清楚地指出任何 7.x 特定的功能,以免您或您的主机提供商碰巧还没有升级时产生任何混淆。

虽然看起来我在版本号上小题大做,但事实是你可以用任何 5.4 或更新版本的 PHP 正确执行本书中 99%的例子。这是因为版本 5.0(发布于十多年前,2004 年 7 月)代表了 PHP 发展的一个重要分水岭。版本 7 于 2015 年秋季发布,尽管有一些新功能,但此次发布的重点是性能和内存使用。事实上,与在 PHP 5 下运行的相同脚本相比,许多 PHP 脚本运行速度提高了一倍,而使用的内存只有一半。尽管以前的主要版本增加了大量新的库,但第 5 版包含了对现有功能的改进,并增加了一些通常与成熟编程语言架构相关的特性。几个最显著的增加包括大幅改进的面向对象能力(在第 6 和 7 章中讨论)、异常处理(在第八章中讨论),以及改进的对 XML 和 web 服务互操作的支持(在第二十章中讨论)。当然,这并不是说 PHP 开发人员从此就不忙了!我将重点介绍几个近年来新增的优秀特性。如果您不理解其中的一些内容,请不要担心,我们将在本书的其余部分涵盖您需要了解的所有内容。这个列表只是为了证明 PHP 是一种不断发展、维护和支持的语言:

  • 名称空间:在 5.3 版本中引入,名称空间是管理和共享代码的一个非常有用的特性。我将在第七章中介绍 PHP 的名称空间支持。

  • 原生 JSON 解析和生成:PHP 的原生 JavaScript 对象符号(JSON)特性从 5.2 版本开始提供,包括解析和生成 JSON 的能力,这是与当今许多现代 web 服务通信和构建尖端 web 应用的基本任务。

  • 极大改进的 Windows 支持:尽管 PHP 在所有主流操作系统上都得到支持,包括 Linux、OS X 和 Windows,但它以前在前两个平台上运行最为有效,绝大多数 Windows 用户在本地开发自己的应用,并部署到基于 Linux/Unix 的托管提供商。然而,近年来,大量的工作已经投入到提高 PHP 在 Windows 上的稳定性和性能上(这在很大程度上要归功于微软自己),使得 Windows Server 成为托管 PHP 驱动的 web 应用的一个完全可以接受的解决方案。

  • 交互式外壳(interactive shell):如果你有使用其他编程语言(如 Ruby 或 Python)的经验,你肯定会喜欢它们的交互式外壳,这使得测试和试验代码变得容易和方便。PHP 5.1 版本也增加了类似的便利,我将在第二章中讨论。我相信 PHP 的交互式 shell 是学习这门语言的一个非常重要的工具,所以我会鼓励你使用它来完成后面章节中的许多例子。

  • 本地 web 服务器:同样,如果你有在 Ruby on Rails 等其他编程环境中工作的经验,你可能会发现内置的 web 服务器非常方便,因为它允许你在本地运行你的 web 应用,只需要最少的配置麻烦。PHP 5.4 版本增加了类似的便利,我将在第二章中向您介绍本地 web 服务器。

  • Traits : Traits 是 Scala、Self、Perl 等语言支持的高级面向对象特性。这个特性在 5.4 版本中被添加到 PHP 中,我将在第七章中向你介绍它。

  • 丰富的增强功能:在每一个 PHP 版本中,除了语法上的变化,比如库函数的添加和修改,您还会发现无数的错误和安全修复以及性能改进。在很大程度上,这些新特性的引入保持了向后兼容性。旧的方式通常至少会维持到下一个主要版本发布。

  • 性能:随着 PHP 7 的发布,对于许多常见用途,原生 PHP 代码的执行时间和内存使用量大约减少了一半,性能改进在 7.1 版本和即将发布的 7.2 版本中继续。任何使用外部服务(如数据库)的代码可能不会看到如此显著的改进,因为查询仍然会花费相同的时间。

  • 标量类型声明 : PHP 是一种松散类型的语言,允许向函数传递任何类型的变量。在某些情况下,开发人员希望强制执行传递的参数类型,如果传递了错误的类型,就会生成警告或错误。在各种 PHP 5.x 版本中引入了一些类型声明,PHP 7 引入了标量类型(string、int、float 和 bool)的声明。

  • 返回类型声明:就像函数参数可以接受不同类型的变量一样,函数的返回值可以是任何允许的类型。为了强制执行返回值的预定义类型,PHP 引入了一种声明返回类型的方法。如果函数返回的类型不同于声明的类型,将会产生错误。

  • 新运算符 : PHP 7 增加了两个新运算符;??也被称为零聚结算子和< = >宇宙飞船算子。两者都旨在减少执行常见操作所需的代码量。

  • 常量数组:在 PHP 7 中,不可能使用 define()函数将数组定义为常量。

  • 匿名类:就像 PHP 5.3 中引入了闭包(匿名函数)一样,PHP 7 也允许使用匿名类。在任何需要将类作为函数参数的地方,都可以动态定义类。

  • 会话选项:现在可以通过解析 session_start()函数的选项数组来定义会话选项。这将覆盖 php.ini 中定义的任何默认值。

那么如何才能跟上语言变化的潮流呢?对于初学者,我建议偶尔在 https://www.php.net 查看一下 PHP 官方主页,尤其是关于 PHP 7 https://php.net/manual/en/migration70.new-features.php 中新功能的页面,这里列出了即将到来的 7.2 版本中的特性 https://php.net/manual/en/migration71.new-features.php 。此外,PHP 文档附录( https://www.php.net/manual/en/appendices.php )提供了关于每个要点和主要版本的详细说明,包括偶尔的向后不兼容更改、新特性和功能、升级提示和配置更改。也可以考虑订阅低容量公告邮件列表,你可以从 https://www.php.net/mailing-lists.php 开始订阅。不定期的电子邮件将与最新的版本保持一致,强调新版本的最新变化。

PHP 生态系统

本书讨论的大部分内容都是为了给你提供阅读和编写 PHP 代码的必要信息。但是,仅仅因为你很快就会成为一名更熟练的 PHP 程序员,并不意味着你应该从头开始构建所有即将出现的 web 应用。事实上,真正精通的程序员知道,快速高效地完成事情往往意味着站在那些已经煞费苦心地构建强大软件(如内容管理系统、电子商务平台和开发框架)的巨人的肩膀上。对于 PHP 开发者来说,幸运的是不缺巨头!在许多情况下,通过修改和扩展现有软件,您将能够大大减少构建功能强大的 web 应用所需的时间和精力,这些软件通常是在类似于 PHP 语言所使用的开源许可下提供的。在这一节中,我想借此机会强调几个值得您在下一个 web 项目中考虑的流行的基于 PHP 的软件实例。

获得

特纳广播公司、福克斯新闻频道、*《华盛顿邮报》《大众科学》*杂志都拥有庞大的网站,上面有无数的图片、文章、照片库、用户账户和视频。所有这些媒体都有一个共同点,那就是它们都依赖于开源和 PHP 驱动的 Drupal 内容管理框架( https://www.drupal.org )来管理它们令人难以置信的多样化内容。

经过十多年的积极开发,Drupal 拥有大量的特性。有些可以作为 Drupal“核心”的一部分获得(例如,搜索、用户管理和访问控制,以及内容创建),其他的可以通过第三方模块获得(在撰写本文时,有近 32,000 个可以通过 https://drupal.org/project/Modules 获得)。看起来具有无限的可扩展性和主题性,很有可能你每天都会访问不止一个 Drupal 支持的网站,而你自己却不知道!

博客

像 Drupal 一样,WordPress 是一个开源的、PHP 驱动的内容管理系统,已经积累了如此庞大的用户群,你完全有可能每天都访问一个 WordPress 驱动的网站。WordPress 支持的网站包括 TechCrunch、BBC America、官方的星球大战博客,以及更多这里列出的 https://www.wpbeginner.com/showcase/40-most-notable-big-name-brands-that-are-using-wordpress/ 。事实上,WordPress 的用户基数如此之大,以至于据报道它为互联网上 28.7%的网站提供了动力。 5

WordPress 拥有庞大的用户群体,他们在开发插件和主题方面异常活跃。事实上,在撰写本文时,通过 https://wordpress.org/plugins/ and https://wordpress.org/extend/themes/ 分别有近 52,000 个插件和 2,600 个主题可用,并且通过第三方供应商如 https://themeforest.net/category/wordpress 还有更多的插件和主题可用。

胃里

通过网络向全球受众销售产品和服务的诱惑力是不可否认的,但创建和管理网上商店也面临着诸多挑战。目录和产品管理、信用卡处理、移动购物、有针对性的促销整合以及搜索引擎优化只是任何寻求实现一个适度的电子商务解决方案的开发人员所面临的几个障碍。基于 PHP 的 Magento 项目( https://magento.com/ )背后的团队试图通过提供一个令人难以置信的全功能电子商务解决方案来消除这些障碍。

算上用户中的零售巨头耐克、Warby Parker、Office Max、奥奈达、优派和 The North Face,Magento 甚至能够满足最雄心勃勃的期望,而且非常适合小型企业使用。事实上,在撰写本文时,Magento 网站显示全球有超过 150,000 家在线商店由 Magento 提供支持。Magento 有多个版本,包括一个免费的企业版,并享有一个名为 Magento market place(marketplace.``magento.com)home 的庞大社区的支持,可以说它是任何地方任何编程语言中最高质量的电子商务解决方案。

MediaWiki

我怀疑这个星球上没有一个普通的互联网用户没有利用过协作编辑的在线百科全书维基百科( https://www.wikipedia.org )上的巨大知识字体。这些用户中的绝大多数可能没有意识到的是,维基百科完全是建立在自由软件之上的,包括 PHP 和 MySQL!也许更令人惊讶的是,你可以下载用于驱动维基百科的相同软件。名为 MediaWiki ( https://www.wikimedia.org ),需要基于 Wiki 的内容管理解决方案的开发人员可以轻松下载并安装该软件,并开始利用全球数百万 Wikipedia 用户享有的相同功能。

SugarCRM

成长中的公司很快发现有必要采用客户关系管理(CRM)解决方案,以便更有效地管理客户支持、销售团队协作和营销活动。这些解决方案在历史上非常昂贵,经常需要大量的管理资源,并且很少满足用户的特定需求。他们的同名产品 SugarCRM ( https://sugarcrm.com )背后的公司通过提供一个基于 PHP 的 CRM 解决方案,在解决所有这三个问题方面取得了长足的进步,该解决方案足够简单,可以在夫妻店内有效管理,但足够强大和可扩展,可以被诸如 Men’s Wearhouse,Coca-Cola Enterprises,甚至技术巨头 IBM 等公司巨头所接受。

SugarCRM 有多个版本,包括免费社区版,可从 https://www.sugarcrm.com/download 下载。需要官方支持、托管或社区版中没有的功能的 CRM 用户可以从各种商业版本中选择,所有这些都在 https://www.sugarcrm.com/products 中有详细描述。

Zend 框架

web 框架不是现成的软件产品,而是通过提供一个基础来解决所有应用(无论用途如何)面临的许多常见挑战,从而帮助开发人员更快、更有效地构建自己的软件解决方案。例如,典型的 web 框架包括在数据库集成、应用视图和逻辑的分离、用户友好 URL 的创建、单元测试和配置管理方面帮助开发人员的特性。

一个流行的 PHP 框架是 Zend Framework ( https://framework.zend.com/ ),这是一个由 PHP 产品和服务提供商 Zend Technologies ( https://www.zend.com )开发的开源项目。最近发布的版本 3 经过了重新编写,非常小心地采用了行业最佳实践,并为当今 web 应用开发人员面临的挑战提供了解决方案,其中包括云和 web 服务集成。

平心而论,Zend Framework 只是几个强大的 PHP 框架之一;其他的还包括 CakePHP、Laravel、Symfony,以及一大堆所谓的“微”框架,比如 Fat-Free 和 Slim。事实上,在第二十一章中,我将向您介绍 Laravel,这是一个相对较新的框架,在我看来,它是寻求用框架提高生产力的 PHP 新程序员的完美切入点。

摘要

这一章是对 PHP 语言的概述,强调了它的起源、当前状态,以及令人难以置信的软件生态系统,它的出现使这种语言变得更加强大和有吸引力。希望这篇概述达到了我的目标,让你对未来的机会感到兴奋!

在第二章中,您将深入研究 PHP 安装和配置过程;您还将了解到更多关于搜索虚拟主机提供商时需要寻找的内容。尽管读者经常把这种类型的章节比作在黑板上抓钉子,但是你可以从对这个过程的更多了解中获得很多。所以,拿起零食,舒适地坐在你的键盘前——是时候把手弄脏了!

简而言之,开源软件是源代码免费提供的软件。

2

http://news.netcraft.com/archives/2013/01/31/php-just-grows-grows.html

3

https://w3techs.com/technologies/details/pl-php/all/all

4

只要遵循一些完全合理的条款。参见 https://php.net/license/index.php 获取许可信息。

5

http://wpengine.com/2012/08/the-state-of-the-word-and-wordpress/

二、配置您的环境

PHP 的设计和创建是为了生成注入 HTML 文档的动态内容,或者生成由 web 服务器提供服务的完整 HTML 文档。web 服务器通常是连接到互联网的物理服务器,或者是数据中心中的虚拟或共享服务器。作为开发人员,您还需要一个本地环境,用于开发和测试您正在开发的 web 页面,然后再将它们部署到服务器上。因为 PHP 可以在许多系统上使用,并且支持大量的 web 服务器,所以不可能在一章中涵盖所有可能的组合,但是我们可以涵盖一些最常见的配置。

Apache ( https://httpd.apache.org ) web 服务器已经统治 PHP 环境很长时间了,但是由于速度和内存使用的提高,新的服务器正在获得牵引力。增长最快的服务器之一是 Nginx ( https://www.nginx.org/ ) web 服务器。在基于 Windows 的系统上,也可以使用微软的互联网信息服务器(IIS) ( https://www.iis.net/ )。这三款服务器的市场份额对比可以在这里找到: https://w3techs.com/technologies/comparison/ws-apache,ws-microsoftiis,ws-nginx

某种形式的 Linux 似乎是托管网站最喜欢的操作系统。但开发人员仍然主要使用 Windows 或 macOS 笔记本电脑/台式机进行开发;使用 Linux 作为开发平台的开发人员数量不多,但在不断增加。2017 年的堆栈溢出调查提供了支持这一说法的数字( https://insights.stackoverflow.com/survey/2017 ),尽管这涵盖了 PHP 开发以外的内容。

如果你是一个项目的唯一开发者;您很可能可以在您的本地环境中做任何事情;但是如果您是团队的一员,您可能希望考虑一个共享的 web 服务器,您可以在那里开发/部署和测试您的代码,然后再将代码提交到生产服务器。让开发/测试服务器的配置与生产环境接近一致是一种很好的做法。这将有助于在新页面上线之前发现与系统配置相关的错误。

在设置 web 服务器时,至少有四种基本类型需要考虑:

  • 拥有自己的硬件。您可以完全控制硬件的类型、CPU 的数量和类型、硬盘大小和内存等。您甚至可以联系 IT 部门来为您配置和管理服务器。这种类型的 pf 环境让您可以完全控制,但很可能会有很高的硬件购买初始成本和很高的互联网连接订阅成本。服务器可以托管在您自己的设施中,或者您可以在数据中心租用空间,也称为共置。

  • 一种共享的主机环境,其中主机提供商配置硬件和软件,并为您提供一个用户帐户,该帐户可以访问共享主机上的单个虚拟 web 服务器。在大多数情况下,您将可以访问服务器上的单个目录,并且您对 PHP 的配置或您可以访问的特性没有任何影响。每台服务器将托管多个网站,资源共享可能会有问题,但这通常是最便宜的虚拟主机形式。

  • 租赁但专用的硬件。数据中心将安装和配置硬件,并将其出租,允许用户完全访问硬件。

  • 作为一个中间地带,你可以选择虚拟专用服务器(VPS ),托管公司利用一个强大的服务器群,可以同时托管多个操作系统。你将负责选择和配置操作系统,并安装所有的软件,你需要主持你的网站。你每月只需 10 美元就可以开始;参见( https://www.digitalocean.comhttps://www.linode.com/ 仅举几个例子),有许多主机服务提供商在许多大洲都有数据中心,使得在接近预期用户的地方托管您的新网站成为可能。有了虚拟主机,随着网站流量的增长,升级到更多的 CPU、内存或硬盘空间也变得非常容易。无需购买新硬件,只需选择新计划并迁移服务器。这些主机提供商大多支持迁移,所有的配置都被复制,这样网站在短暂的停机后还能继续工作。

其他云公司也提供对托管环境和许多其他服务的访问。 https://aws.amazon.com/ec2/https://azure.microsoft.com 就是其中的两个例子。

选择托管环境

发布网站从未如此简单。有无数基于云的托管选项,您可以按需付费,并且可以轻松升级到更强大的配置,而无需订购硬件、安装操作系统,然后安装所需的所有软件。

虚拟服务器

如今,最常见的基础架构是虚拟服务器。它就像一个普通的服务器一样工作。你首先去你喜欢的主机提供商(亚马逊 AWS,微软 Azure,谷歌云,数字海洋,Linode,和许多其他的)。第一步是创建一个账户,并提供一张信用卡进行支付。接下来选择服务器的大小(CPU、内存、磁盘空间和网络带宽),然后选择数据中心,最后选择操作系统。几分钟后,您将能够使用 ssh 连接到主机。

平台即服务(PaaS)

如果您想跳过操作系统和 web 服务器软件堆栈的安装、配置和维护,您可以选择 PaaS 解决方案。这也是基于云的,但它更像传统的共享主机。服务提供商将安装和配置运行应用所需的一切,在本例中是 PHP。你所要做的就是把你的 PHP 代码上传到服务器上。这些服务由 Cloudways、Fortrabbit、Appfog、Engine Yard 等公司提供。

安装先决条件

配置环境的第一步通常从下载和安装 web 服务器开始。只要配置为在不同的 TCP 端口上运行,就可以在同一系统上安装多个 web 服务器。对于 http 和 https 协议,web 服务器的默认端口号是 80 和 443,但是您可以选择任何尚未使用的端口。在生产环境中,网站会与一个主机名( www.example.com )相关联。主机名与一个 IP 地址相关联(在本例中为 93.184.216.34)。多个主机名可以链接到同一个 IP 地址。这意味着网站托管在同一台服务器上。在开发环境中,您可能不需要完成主机名的配置。在这种情况下,您可以使用您的环境的 IP 地址和每个网站的新端口号。

Windows 操作系统

在 Windows (10 和 8)上,我们从下载 PHP 的二进制包开始。这个步骤对于任何 web 服务器都是一样的。PHP 的当前版本可以在 https://windows.php.net/download/ 找到,在那里你还可以找到其他有用的信息和链接。它有 x86 (32 位)和 x64 (64 位)两种版本。您应该选择与您的操作系统相匹配的版本。在 Windows 上,还有线程安全(TS)和非线程安全(NTS)版本可供选择。在本章中,我们将使用 NTS 版本,并使用 FastCGI 来集成 web 服务器。下载并解压 zip 存档文件。在本例中,我选择 c:\php7 作为将文件解压到的文件夹。

您可以通过打开一个终端窗口(CMD 或 PowerShel)并执行以下步骤来轻松测试 PHP:

cd \php7
.\php -v

输出将如下所示:

PHP 7.1.11 (cli) (built: Oct 25 2017 20:54:15) ( NTS MSVC14 (Visual C++ 2015) x64 )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

这是一个使用 PHP 命令行(cli)版本的例子。稍后会详细介绍。

建议您在开发中使用与生产中相同的服务器。在下面几节中,我们将介绍如何安装和配置 IIS、Apache 和 Nginx web 服务器,以使用我们刚刚下载和安装的 PHP 二进制文件。

(同 ImmigrationInspectors 移民检查)

在 Windows 10(和 8)上安装 IIS 从控制面板开始。打开程序和功能部分,并单击左侧的打开或关闭 Windows 功能。这将打开一个弹出窗口,显示一长串可用功能,如图 2-1 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-1

视窗 功能

如果未安装任何内容,Internet 信息服务旁边将不会有复选标记。单击复选框将选择安装选项。黑色方块表示没有安装 IIS 下的所有选项。如果扩展服务,您可以从许多选项中进行选择。为了使用 PHP,你必须选择如图 2-2 所示的 CGI 选项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-2

IIS 选项

选择选项并按“确定”后,Windows 将安装所有选定的功能,您将可以配置第一个网站。我已经创建了一个名为 c:\Web 的目录,我将在那里保存我的网站。在那个文件夹中,我创建了一个名为 site 的文件夹,并放了一个名为 phpinfo.php 的文件。这是一个非常基本的文件,如下所示:

<?php
phpinfo();

phpinfo()函数是一个内置函数,可以用来显示配置细节、安装的模块和其他参数。像这样的文件不应该存在于生产系统中,因为它可能会给黑客提供攻击服务器所需的信息。

现在让我们继续配置 IIS 下的第一个网站。这从启动 IIS 管理器开始。只需在 Windows 搜索栏中键入 IIS,然后选择应用 Internet Information Server (IIS)管理器。

展开左侧的树以查看名为 Sites 的文件夹,并右键单击该文件夹以获得上下文菜单。这个菜单应该包括顶部的选项添加网站。选择此选项将打开一个弹出窗口,如图 2-3 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-3

添加网站

重要的字段是名称(测试)、物理路径(c:\Web\site)和端口号(8081)。当您添加这些值并单击“确定”时,网站将被创建。此时,网站只支持 HTML 和可能的 ASP 脚本,这取决于您安装的功能。为了启用 PHP 脚本,您必须添加一个处理器。单击左侧面板中的测试网站,然后双击处理器映射图标。这将显示现有处理器的列表。现在右键单击 mappings 列表中的任意位置,并选择 Add Module Mapping 选项。这将弹出一个窗口,您可以在其中输入必要的参数,如图 2-4 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-4

配置 PHP 处理器

现在,您可以通过单击左侧面板中的 Test(我们给服务器起的名字),然后单击右侧面板中的 restart 链接来重启 web 服务器。要测试服务器,请打开您最喜欢的浏览器并键入http://localhost:8081/phpinfo.php。这将产生如图 2-5 所示的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-5

PHP 信息

输出很长,包含每个已安装扩展的部分。图 2-5 仅显示输出的第一页。

街头流氓

转移到阿帕奇。有两种不同的方法来集成 PHP 和 Apache。如果你正在使用 PHP 的非线程安全版本,你将不得不像我们使用 IIS 一样使用 FastCGI。这是最容易操作的版本,推荐给初学者。如果您使用的是线程安全版本,那么您可以使用 Apache 模块,该模块将在 Apache 启动时加载 PHP 模块。长期以来,这一直是 PHP 首选的 web 服务器,Windows 二进制文件由 Apache Lounge 提供,而不是由 Apache Foundation 维护的网站( https://www.apachelounge.com/download/ )。建议使用与您的操作系统(x86 或 x64)匹配的最新副本和版本。下载文件是一个 zip 存档文件,其中包含一个名为 Apache24 的文件夹。只需将这个文件夹解压到 c:\Apache24。要使用 FastCGI 版本,您还必须从同一站点下载 mod_fcgid 归档文件,并将 mod_fcgid.so 复制到 c:\Apache24\modules。

导航到 c:\Apache24\conf 文件夹,在那里您将找到 httpd.conf,这是 Apache 的主要配置文件。在您最喜欢的编辑器中打开该文件,并将包含Listen 80的行更改为Listen 8082。您可以使用系统中尚未使用的任何端口号。我们对 IIS 使用 8081,为了让两台服务器安装在同一系统上,我们对 Apache 使用 8082 端口。

您还需要取消靠近虚拟主机文件底部的那一行的注释,并添加一行来包含 PHP 特定的配置。这可能看起来像Include conf/extra/httpd-php.conf.你将不得不创建文件c:\Apache24\conf\extra\httpd-php.conf与以下内容:

#
LoadModule fcgid_module modules/mod_fcgid.so
FcgidInitialEnv PHPRC "c:/php7"
AddHandler fcgid-script .php
FcgidWrapper "c:/php7/php-cgi.exe" .php

如果您使用线程安全版本和 Apache PHP 模块,该文件应该如下所示:

#
AddHandler application/x-httpd-php .php
AddType application/x-httpd-php .php .html
LoadModule php7_module "c:/php7ts/php7apache2_4.dll"
PHPIniDir "c:/php7ts"

注意,PHP 文件夹名为 php7ts。这是因为我的系统上安装了两个版本。您必须调整文件夹名称以匹配您系统上的安装。

无论哪种情况,您都需要为您的站点配置一个虚拟主机。在这种情况下,我们使用 c:\Web\site 中与 IIS 服务器相同的站点。https-vhosts.conf 文件应该如下所示:

<VirtualHost *:8082>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "c:/Web/site"
    ServerName dummy-host.example.com
    ServerAlias www.dummy-host.example.com
    ErrorLog "logs/dummy-host.example.com-error.log"
    CustomLog "logs/dummy-host.example.com-access.log" common
</VirtualHost>
<Directory "c:/Web/site" >
    Options FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
</Directory>

<Directory>部分用于提供 Apache 访问来读取系统上的文件。

现在您已经完成了 web 服务器的配置,是时候启动它了。简单的方法是运行命令 c:\Apache24\bin\httpd。如果配置没有错误,服务器将启动,您可以打开浏览器并键入地址http://localhost:8082/phpinfo.php,它将显示类似于图 2-5 所示的信息页面。

如果你想让 Apache 作为一个 Windows 服务安装,你可以运行命令c:\Apache24\bin\httpd -k install,然后你可以使用c:\Apache24\bin\httpd -k startc:\Apache24\bin\httpd -k stop与服务交互。

Nginx

web 服务器领域的新成员是 Nginx。这是一个轻量级的服务,可以与 Windows 上的 FastCGI 版本的 PHP 进行交互。正如我们稍后将展示的,它使用 Linux 上的 PHP-FPM 接口。前往 http://nginx.org/en/download.html 下载最新稳定版本。它是一个 zip 文件,可以解压到 c:\nginx-1.12.2(取决于当前的版本号)。在 Windows 上,为了使用 Nginx,应该已经运行了 php-cgi.exe 二进制文件。这可以通过从命令行运行命令c:\php7\php-cgi.exe -b 127.0.0.1:9123来完成。这将使命令行窗口保持打开。如果您想避免这种情况,可以下载一个实用程序,在隐藏窗口中运行该命令。该实用程序可以从 http://redmine.lighttpd.net/attachments/660/RunHiddenConsole.zip 下载。如果您将可执行文件放在 nginx 文件夹中,启动命令将如下所示:

c:\nginx-1.12.2\RunHiddenConsole.exe c:\php7\php-cgi.exe -b 127.0.0.1:9123

端口号 9123 是任意选择的。您可以使用与您的系统匹配的任何未使用的号码。您只需要确保在 nginx 配置文件中使用相同的编号。在您最喜欢的编辑器中打开 c:\ nginx-1 . 12 . 2 \ conf \ nginx . conf,将 server 部分中的 listen 行更新为 8083 而不是 80,并在 server 块中添加一个如下所示的部分:

root c:/Web/site;

location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9123;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

现在,您可以从命令行使用命令c:\nginx-1.12.2\nginx启动 nginx 服务器。确保您位于 nginx-1.12.2 文件夹中。要测试服务器,请打开浏览器并转到http://localhost:8083/phpinfo.php。您将再次看到如图 2-5 所示的信息页面。

苹果

macOS 预装了 PHP。不幸的是,它通常是一个旧版本的 PHP,目前在 OS X 的最新版本 High Sierra 上是 5.6.30 和 7.1。最佳做法是使用 Mac OSX 可用的软件包管理器(MacPorts 或 Homebrew)之一来获得最新版本的 PHP。这些包管理器以一种易于在 OSX 上安装和使用的方式提供了一大套在 Linux 平台上可用的软件包。

在安装 Homebrew 之前,您需要下载并安装 Xcode。Xcode 是 app store 的免费应用。下载后,您必须从终端窗口运行该命令。

xcode-select – install

为了使用自制软件( https://brew.sh/ ),你必须先安装一些基本的组件。这可以通过在终端中运行以下命令来实现:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

这将安装和配置 brew 系统。建议定期运行以下命令,以确保您拥有最新版本的安装包和 Homebrew 本身。

$ brew update
$ brew upgrade

要开始安装 PHP,你必须运行几个命令,允许自制软件进入公式库。

brew tap homebrew/dupes
brew tap homebrew/versions
brew tap homebrew/homebrew-php

现在您可以运行命令来安装 php 7.1

brew install php71

要安装 nginx,运行以下命令

brew install nginx

这将安装和配置 Nginx 在端口 8080 上运行,这允许它在没有超级用户访问(sudo)的情况下启动。

默认配置使用/usr/local/var/www 作为文档根目录。将包含以下内容的文件放在那里可以用来测试配置。

<?php
phpinfo();

Nginx 的默认配置将 PHP 部分注释掉了。在您喜欢的编辑器中打开/usr/local/etc/nginx . nginx . conf,取消对以下部分的注释:

location ~ \.php$ {
    root                 html;
    fastcgi_pass  127.0.0.1:9000
    fastcgi_index index.php;
    fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name
    include              fastcgi_params;
}

现在我们需要做的就是启动服务器。首先,我们启动 php-cgi 监听端口 9000,然后启动 nginx 服务器。

# php-cgi -b 127.0.0.1:9000 &
# nginx

打开浏览器,在地址栏中键入 localhost:8080/phpinfo.php。这将显示类似于上面窗口部分中显示的图 2-5 的输出。

Linux 操作系统

在基于 Linux 的操作系统上安装 PHP 通常从该系统上的包管理器开始。基于 Red Hat 的系统(CentOS、RHEL 或 Fedora)称为 yum。在其他系统上,它可能是 apt-get。Linux 发行版的维护者将构建包含 web 服务器、PHP、PHP 扩展和您可能需要的其他软件组件的包。它们中的许多甚至会提供依赖管理,所以当你试图安装一个软件包,而系统缺少一个或多个其他软件包时,它会根据系统的建议来安装这些软件包。

如果您刚刚安装了 CentOS 系统,可以使用下面的命令来安装 nginx 和 php:

%> yum install nginx php71u-cli php71u-fpm

或者,如果您的首选发行版是基于 Debian/Ubunto 的,您将运行 apt-get 命令来安装类似的库。

%> apt-get install nginx
%>apt-get install php-fpm

这将安装 Nginx web 服务器,PHP 的 web 服务器和命令行(CLI),它将安装一个特殊的组件称为 FastCGI 进程管理器(FPM)。这是一个 the FastCGI 版本的包装器,允许对负载较重的站点进行更多的调优。

根据 Linux 发行版的不同,PHP 文件最终会出现在发行版维护者定义的目录结构中。配置文件最有可能以/etc 结尾。

来源

PHP 也有源代码发行版(或者你可以直接去 GitHub https://github.com/php/php-src )。如果你想改进 PHP 或者添加你自己的扩展,这是一条可行之路。它需要关于你正在工作的平台上的配置工具和编译器的知识,但是它也允许你在最新版本的 PHP 上运行,甚至是尚未发布的版本。

配置 PHP

当您的系统上安装了 web 服务器和 PHP 二进制文件后,您就可以开始配置 PHP 了。这是通过一个名为 php.ini 的文件来完成的。这个文件的位置取决于操作系统和您使用的 php 发行版。在 Windows 上,它将位于 c:\php7 中(或者您选择将 zip 文件解压缩到的文件夹的名称);在 Mac 和 Linux 上,它可能在/etc(或/usr/local/etc)中。您可以在命令行上使用 phpinfo()函数或 php -I 来获取 php.ini 文件的位置。

php.ini 文件用于控制 php 的运行时配置。如果您自己编译 PHP,您也可以控制编译时配置。编译时配置用于定义要包含在二进制文件中的模块,选择线程安全或非线程安全选项等。运行时配置用于定义 PHP 运行的环境,有许多选项。完整的列表可以在 PHP 文档 https://php.net/manual/en/ini.list.php 中找到。

PHP 的基本包包含两个版本,分别叫做 php.ini-development 和 php.ini-production。这些文件针对开发和生产环境进行了优化。您必须将其中一个文件重命名为 php.ini,并可能重启 web 服务器来加载该文件。如果您使用软件包管理器安装,这通常会自动处理。您也可以从一个空文件启动自己的 php.ini 版本。这将使您完全控制内容,但要小心,因为这可能会遗漏重要的配置选项。如果您使用包管理器来获得 PHP 二进制文件,这些文件可能会有不同的名称,您可能会获得 Linux 发行版提供的 php.ini 版本。

根据 php 的调用方式(使用的 SAPI),可以创建 php.ini 文件的特殊版本。如果您将 PHP 同时用作 web 服务器的一部分和命令行(cli)工具,这将非常有用。您可以创建一个名为 php-cli.ini 的文件。如果在使用命令行版本时该文件存在(在 php.ini 所在的同一目录中),将使用它来代替常规的 php.ini。只有在 php-cli.ini 不存在时才使用 php.ini 文件。可以为任何受支持的 SAPIs 创建 php.ini 版本。

php.ini 文件可以用来配置 php 行为的几乎任何方面。有关完整和最新的选项列表,请参见 https://php.net/manual/en/configuration.file.phphttps://php.net/manual/en/ini.php

某些配置选项可以在中被覆盖。或者通过使用 PHP 脚本中的ini_set()函数。如果您托管在一个共享环境中,并且没有权限编辑 php.ini 文件,那么您可以使用。您的 PHP 脚本所在的目录中的 htaccess。这将允许您覆盖 php.ini 中定义的一些值,但它会带来性能开销,因为每个请求都会对文件进行评估,尽管这只是中等流量到大流量级别的站点的问题。

每个配置选项都有四个不同的范围类别。每个类都定义了如何改变它们。

  • PHP_INI_PERDIR:可以在php.inihttpd.conf.htaccess文件中修改指令

  • PHP_INI_SYSTEM:指令可以在php.inihttpd.conf文件中修改

  • PHP_INI_USER:可以在用户脚本中修改指令

  • PHP_INI_ALL:指令可以在任何地方修改

配置选项的文档包括类。

php.ini 文件是一个纯文本文件,包含节、注释以及成对的键和值。节是方括号中的名称,就像[PHP]。部分名称用于将配置选项分组到逻辑存储桶中。注释由一行第一个位置的分号(;)标识。每个配置选项都被写成 key = value,例如engine = On

默认的 ini 文件包含一个 PHP 常规设置部分,然后是每个已安装模块的一个部分。常规 PHP 部分包含以下逻辑子部分:

  • 关于 PHP . ini——文件和特性的描述

  • 快速参考–生产和开发版本之间的差异

  • php.ini 选项–用户定义的 ini 文件

  • 语言选项

  • 多方面的

  • 资源限制

  • 错误处理和记录

  • 数据处理

  • 路径和目录

  • 文件上传(在第十五章中介绍)

  • Fopen 包装纸

  • 动态扩展

Apache httpd.conf 和。htaccess 文件

当 PHP 作为 Apache 模块运行时,您可以通过httpd.conf文件或.htaccess文件修改许多 PHP 指令。这是通过在指令/值赋值前添加以下关键字之一来实现的:

  • php_value:设置指定指令的值。

  • php_flag:设置指定布尔指令的值。

  • php_admin_value:设置指定指令的值。这与php_value不同,它不能在.htaccess文件中使用,也不能在虚拟主机或.htaccess中被覆盖。

  • php_admin_flag:设置指定指令的值。这与php_value不同,它不能在.htaccess文件中使用,也不能在虚拟主机或.htaccess中被覆盖。

例如,要禁用短标记指令并防止其他人覆盖它,请将下面一行添加到您的httpd.conf文件中:

php_admin_flag short_open_tag Off

在执行脚本中

第三种,也是最本地化的,操作 PHP 配置变量的方法是通过 PHP 脚本本身的ini_set()函数。例如,假设您想修改 PHP 给定脚本的最大执行时间。只需将以下命令嵌入 PHP 脚本的顶部:

<?php
ini_set('max_execution_time', '60');

PHP 的配置指令

以下部分介绍了 PHP 的许多核心配置指令。除了一般定义之外,每个部分还包括配置指令的范围和默认值。因为您可能会花大部分时间在php.ini文件中处理这些变量,所以当这些指令出现在这个文件中时,它们就会被引入。

请注意,本节介绍的指令在很大程度上只与 PHP 的一般行为相关;本节不介绍与扩展相关的指令,也不介绍与本书后面重点关注的主题相关的指令,而是在相应的章节中介绍。

语言选项

本节中的指令决定了该语言的一些最基本的行为。您肯定想花一些时间来熟悉这些配置的可能性。请注意,我只强调了一些最常用的指令。请花些时间仔细阅读您的php.ini文件,了解您还可以使用哪些指令。

引擎= 开|关

范围:PHP_INI_ALL;默认值:On

这是语言选项部分中的第一个选项,但是只有在将 PHP 作为 Apache 模块运行时才有用。在这种情况下,可以使用每个目录的设置来启用/禁用 PHP 解析器。一般来说,您希望保留这个选项以使 PHP 有用。

short_open_tag = On | Off

范围:PHP_INI_PERDIR;默认值:On

尽管这在默认情况下是打开的,但在 php.ini 的分布式版本中是关闭的(-生产和开发)。PHP 脚本组件包含在转义语法中。有四种不同的转义格式,其中最短的称为短开始标记,如下所示:

<?
    echo "Some PHP statement";
?>

您可能认识到这种语法与 XML 是共享的,这在某些环境中可能会导致问题。因此,提供了一种禁用这种特定格式的方法。当short_open_tag使能(On)时,允许短标签;当残疾人(Off)时,他们不是。

精度 =整数

范围:PHP_INI_ALL;默认值:14

PHP 支持多种数据类型,包括浮点数。precision参数指定浮点数表示中显示的有效位数。请注意,该值在 Win32 系统上设置为 12 位,在 Linux 上设置为 14 位。

output_buffering = On | Off |整数

范围:PHP_INI_PERDIR;默认值:4096

任何人,哪怕只有很少的 PHP 经验,都可能非常熟悉下面两条消息:

"Cannot add header information – headers already sent"
"Oops, php_set_cookie called after header has been sent"

当脚本试图修改已经发送回请求用户的标题时,会出现这些消息。最常见的情况是,在一些输出已经被发送回浏览器之后,程序员试图向用户发送 cookie,这是不可能完成的,因为标题(用户看不到,但浏览器会使用)总是在该输出之前。PHP 4.0 版通过引入输出缓冲的概念为这个恼人的问题提供了一个解决方案。启用时,输出缓冲告诉 PHP 在脚本完成后立即发送所有输出。这样,对头部的任何后续更改都可以在整个脚本中进行,因为它还没有被发送。启用output_buffering指令打开输出缓冲。或者,您可以通过将输出缓冲区设置为您希望该缓冲区包含的最大字节数来限制输出缓冲区的大小(从而隐式启用输出缓冲)。

如果不打算使用输出缓冲,应该禁用该指令,因为它会稍微降低性能。当然,解决标题问题的最简单的方法就是尽可能在任何其他内容之前传递信息。

output_handler = 字符串

范围:PHP_INI_PERDIR;默认值:NULL

这个有趣的指令告诉 PHP 在将所有输出返回给请求用户之前,通过一个内置的输出函数传递它。例如,假设您希望在将所有输出返回到浏览器之前对其进行压缩,这是所有主流 HTTP/1.1 兼容浏览器都支持的一个特性。你可以这样分配output_handler:

output_handler = "ob_gzhandler"

ob_gzhandler()是 PHP 的压缩处理函数,位于 PHP 的输出控制库中。请记住,您不能同时将output_handler设置为ob_gzhandler()并启用zlib.output_compression(接下来讨论)。输出压缩通常由 web 服务器处理。在 PHP 中使用这个特性会导致一些 web 服务器出现问题。

zlib . output _ compression =On | Off | integer

范围:PHP_INI_ALL;默认值:Off

在输出返回到浏览器之前对其进行压缩可以节省带宽和时间。大多数现代浏览器都支持这一 HTTP/1.1 特性,并且可以安全地在大多数应用中使用。您可以通过将zlib.output_compression设置为On来启用自动输出压缩。此外,通过给zlib.output_compression分配一个整数值,您可以同时启用输出压缩和设置压缩缓冲区大小(以字节为单位)。

zlib . output _ handler =string

范围:PHP_INI_ALL;默认值:NULL

如果zlib库不可用,zlib.output_handler指定一个特定的压缩库。

implicit_flush = On | Off

范围:PHP_INI_ALL;默认值:Off

启用implicit_flush会导致在每次调用print()echo()并完成每个嵌入的 HTML 块后,自动清除或刷新其内容的输出缓冲区。在服务器需要很长时间来编译结果或执行某些计算的情况下,这可能很有用。在这种情况下,您可以使用此功能向用户输出状态更新,而不是等待服务器完成该过程。使用此功能会对性能产生影响。我们总是建议在尽可能短的时间内生成所有输出并返回给用户。对于高流量的网站,你应该考虑毫秒。

serialize_precision = 整数

范围:PHP_INI_ALL;默认值:-1

当 doubles 和 floats 被序列化时,serialize_precision指令决定了存储在浮点之后的位数。将此值设置为适当的值,可以确保在以后对数字进行非序列化时不会损失精度。

open _ base dir =字符串

范围:PHP_INI_ALL;默认值:NULL

很像 Apache 的DocumentRoot指令,PHP 的open_basedir指令可以建立一个基本目录,所有的文件操作都被限制在这个目录中。这可以防止用户进入服务器的其他受限区域。例如,假设所有 web 资料都位于目录/home/www 中。为了防止用户通过几个简单的 PHP 命令查看和潜在操纵像/etc/passwd这样的文件,可以考虑这样设置open_basedir:

open_basedir = "/home/www/"

disable_functions = 字符串

范围:php.ini only;默认值:NULL

在某些环境中,您可能希望完全禁止使用某些默认函数,例如exec()system() .这些函数可以通过将它们分配给 disable_function s参数来禁用,如下所示:

disable_functions = "exec, system";

disable_classes = 字符串

范围:php.ini only;默认值:NULL

考虑到 PHP 对面向对象范式的接受所提供的能力,用不了多久你就可以使用大型类库了。但是,在这些库中可能有某些您不希望提供的类。您可以通过disable_classes指令来阻止这些类的使用。例如,如果您想禁用两个名为vectorgraph的特定类,您可以使用以下命令:

disable_classes = "vector, graph"

请注意,该指令的影响并不依赖于 safe_mode 指令。

ignore _ user _ abort =Off | On

范围:PHP_INI_ALL;默认值:Off

有多少次你浏览到一个特定的页面,只是为了在页面完全加载之前退出或关闭浏览器?通常这种行为是无害的。但是,如果服务器正在更新重要的用户配置文件信息,或者正在完成一项商业交易,该怎么办呢?启用ignore_user_abort会导致服务器忽略由用户或浏览器发起的中断导致的会话终止。

多方面的

杂项类别由一个指令expose_php组成。

expose_php = On | Off

范围:php.ini only;默认值:On

潜在攻击者能够收集到的关于 web 服务器的每一点信息都会增加他成功破坏 web 服务器的机会。获取有关服务器特征的关键信息的一种简单方法是通过服务器签名。例如,默认情况下,Apache 将在每个响应头中广播以下信息:

Apache/2.7.0 (Unix) PHP/7.2.0 PHP/7.2.0-dev Server at www.example.com Port 80

禁用expose_php会阻止 web 服务器签名(如果启用的话)广播 PHP 已安装的事实。尽管您需要采取其他步骤来确保足够的服务器保护,但还是强烈建议您隐藏服务器属性,尤其是如果您想获得服务器的 PCI 认证。

注意

您可以通过在httpd.conf文件中将ServerSignature设置为Off来禁用 Apache 对其服务器签名的广播。

资源限制

尽管 PHP 的资源管理功能在版本 5 中得到了改进,在版本 7 中减少了资源的使用,但是您仍然必须小心确保脚本不会因为程序员或用户发起的操作而独占服务器资源。这种过度消耗普遍存在的三个特定领域是脚本执行时间、脚本输入处理时间和内存。每个都可以通过以下三个指令来控制。

max_execution_time = 整数

范围:PHP_INI_ALL;默认值:30

max_execution_time参数设置了 PHP 脚本可以执行的时间上限,以秒为单位。将该参数设置为0会禁用任何最大限值。注意,由 PHP 命令执行的外部程序所消耗的任何时间,比如exec()system(),都不计入这个限制。PHP 的许多内置流函数和数据库函数也是如此。

max_input_time = 整数

范围:PHP_INI_ALL;默认值:60

max_input_time参数限制了 PHP 脚本解析请求数据的时间,以秒为单位。当你使用 PHP 的文件上传功能上传大文件时,这个参数尤其重要,这将在第十五章中讨论。

内存限制= 内存

范围:PHP_INI_ALL;默认值:12 8M

memory_limit参数决定了可以分配给 PHP 脚本的最大内存量,以兆字节为单位。

数据处理

本节介绍的参数影响 PHP 处理外部变量的方式,这些变量通过一些外部来源传递到脚本中。GET、POST、cookies、操作系统和服务器都可能提供外部数据。本节中的其他参数决定了 PHP 的默认字符集、PHP 的默认 MIME 类型,以及外部文件是否会自动添加到 PHP 的返回输出中。

arg _ separator . output =string

范围:PHP_INI_ALL;默认值:&

PHP 能够自动生成 URL,并使用标准的&符号来分隔输入变量。但是,如果您需要覆盖这个约定,您可以通过使用arg_separator.output指令来实现。

arg _ separator . input =string

范围:PHP_INI_PERDIR;默认值:&

&符号(&)是用于分隔通过 POST 或 GET 方法传入的输入变量的标准字符。虽然不太可能,但是如果您需要在您的 PHP 应用中覆盖这个约定,您可以通过使用arg_separator.input指令来实现。

变量 _ 顺序= 字符串

范围:PHP_INI_PERDIR;默认值:EGPCS

variables_order指令决定了ENVIRONMENTGETPOSTCOOKIESERVER变量的解析顺序。这些值的排序可能会导致意外的结果,因为后面的变量会覆盖过程中前面解析的变量。

register_argc_argv = 开|关

范围:PHP_INI_PERDIR;默认值:1

通过 GET 方法传递变量信息类似于向可执行文件传递参数。许多语言根据argcargv来处理这样的参数。argc是参数计数,argv是包含参数的索引数组。如果你想声明变量$argc$argv并模仿这个功能,启用register_argc_argv。这个特性主要用于 PHP 的 CLI 版本。

post_max_size = integerM

范围:PHP_INI_PERDIR;默认值:8M

在请求之间传递数据的两种方法中,POST 更适合传输大量数据,比如通过 web 表单发送的数据。然而,出于安全和性能的原因,您可能希望对通过这种方法发送给 PHP 脚本的数据量设置一个上限;这可以通过使用post_max_size来完成。

auto _ prepend _ file =string

范围:PHP_INI_PERDIR;默认值:NULL

在执行 PHP 脚本之前创建页眉模板或包含代码库通常是使用include()require()函数来完成的。通过给auto_prepend_file指令指定文件名和相应的路径,您可以自动化这个过程,并且放弃在脚本中包含这些函数。

auto_append_file = 字符串

范围:PHP_INI_PERDIR;默认值:NULL

在 PHP 脚本执行后自动插入页脚模板通常是使用include()require()函数完成的。通过将模板文件名和相应的路径分配给auto_append_file指令,您可以自动化这个过程,并放弃在脚本中包含这些函数。

default _ mime type =字符串

范围:PHP_INI_ALL;默认值:text/html

MIME 类型提供了一种对互联网上的文件类型进行分类的标准方法。您可以通过 PHP 应用提供这些文件类型中的任何一种,最常见的是 text/html。但是,如果您以其他方式使用 PHP,比如为移动应用生成 JSON 格式的 API 响应,那么您需要相应地调整 MIME 类型。您可以通过修改 default_mimetype 指令来实现这一点。

default_charset = string

范围:PHP_INI_ALL;默认值:UTF-8

PHP 在 Content-Type 头中输出一个字符编码。默认情况下,这被设置为 UTF-8。

路径和目录

本节介绍决定 PHP 默认路径设置的指令。这些路径用于包含库和扩展,以及用于确定用户 web 目录和 web 文档根目录。

include_path = string

范围:PHP_INI_ALL;默认值:.;/path/to/php/pear

如果第三个参数设置为 true,则该参数设置的路径将作为函数使用的基本路径,如include() , require()fopen()。您可以指定多个目录,用分号分隔每个目录,如下例所示:

include_path=".:/usr/local/include/php;/home/php"

请注意,在 Windows 上,使用反斜线代替正斜线,并且驱动器号位于路径的前面:

include_path=".;C:\php\includes"

doc_root = 字符串

范围:PHP_INI_SYSTEM;默认值:NULL

这个参数决定了所有 PHP 脚本的默认服务。只有当它不为空时,才使用此参数。

user_dir = 字符串

范围:PHP_INI_SYSTEM;默认值:NULL

user_dir指令指定了 PHP 使用/~username约定打开文件时使用的绝对目录。例如,当user_dir被设置为/home/users并且用户试图打开文件~/gilmore/collections/books.txt时,PHP 知道绝对路径是/home/users/gilmore/collections/books.txt

扩展目录= 字符串

范围:PHP_INI_SYSTEM;默认值:/path/to/php(在 Windows 上,默认值是ext)

指令告诉 PHP 它的可加载扩展(模块)在哪里。默认情况下,这设置为。/,这意味着可加载的扩展与正在执行的脚本位于同一目录中。在 Windows 环境下,如果没有设置 extension_dir,则默认为C:\PHP-INSTALLATION-DIRECTORY\ext\

Fopen 包装纸

本节包含五个与远程文件的访问和操作相关的指令。

allow_url_fopen = On | Off

范围:PHP_INI_SYSTEM;默认值:On

启用allow_url_fopen允许 PHP 将远程文件视为本地文件。启用后,如果文件具有正确的权限,PHP 脚本可以访问和修改驻留在远程服务器上的文件。

from = 字符串

范围:PHP_INI_ALL;默认值:""

指令的标题可能会引起误解,因为它实际上决定了用于执行 FTP 连接的匿名用户的密码,而不是身份。因此,如果from这样设定:

from = "jason@example.com"

当请求认证时,用户名anonymous和密码jason@example.com将被传递给服务器。

user_agent = string

范围:PHP_INI_ALL;默认值:NULL

PHP 总是发送一个内容头及其处理后的输出,包括一个用户代理属性。该指令确定该属性的值。

default_socket_timeout = 整数

范围:PHP_INI_ALL;默认值:60

此指令确定基于套接字的流的超时值,以秒为单位。

auto _ detect _ line _ endings =On | Off

范围:PHP_INI_ALL;默认值:0

开发人员感到沮丧的一个永无止境的原因是行尾(EOL)字符,因为不同的操作系统使用不同的语法。启用auto_detect_line_endings决定了fgets()file()读取的数据是使用 Macintosh、MS-DOS 还是 Linux 文件约定(\r、\r\n 还是\n)。当读取文件的第一行时,启用此选项会导致较小的性能损失。

动态扩展

本节包含一个指令extension

扩展名= 字符串

范围:php.ini only;默认值:NULL

扩展指令用于动态加载特定的模块。在 Win32 操作系统上,模块可能是这样加载的:

extension = php_bz2.dll

在 Unix 上,它将这样加载:

extension = php_bz2.so

请记住,在任一操作系统上,简单地取消注释或添加这一行并不一定会启用相关的扩展。您还需要确保扩展已经编译或安装,并且操作系统上安装了任何必要的软件或库。

选择编辑

PHP 脚本是文本文件,可以用任何文本编辑器创建,但是现代编辑器或集成开发环境(IDE)提供了许多对开发人员有益的特性。选择一个支持所有你喜欢的语言或者至少 PHP 和 JavaScript 的 IDE 应该是必须的。语法突出显示、代码完成、文档集成和版本控制系统等都是现代 ide 中可用的特性。有一些开源或免费的编辑器(Atom、Komodo Edit、Visual Studio Code)和大量的商业产品(PHPStorm、Sublime Text 等)。有些编辑器可以在多个平台上使用,但是在选择 IDE 的时候,很大程度上取决于开发人员的偏好,也许在某种程度上还取决于您所工作的组织的文化。

PHPStorm

PHP Storm 是一个强大的编辑器,也许是目前最受欢迎的编辑器。由 JetBrains ( https://www.jetbrains.com/phpstorm/ )提供。它支持 PHP、SQL、CSS、HTML、JavaScript 的代码补全;集成到版本控制和数据库,以及 xdebug 等。它被认为是一个完整的、同类最佳的 IDE。

原子

Atom ( https://atom.io )是一个高度可配置的开源编辑器,对黑客攻击/改进编辑器本身是开放的。默认下载包括对 PHP 的支持,但是您必须下载一个自动完成包。

崇高的文本

Sublime Text ( https://www.sublimetext.com/ )适用于 Windows、Mac OSX 和许多 Linux 发行版(CentOS、Ubuntu、Debian 和其他一些发行版)。它是按用户许可的,允许您在多个系统上安装它,只要在任何给定时间只有一个系统在使用。

Visual Studio 代码

微软已经创建了 Visual Studio 的免费版本(code . Visual Studio . com/)。它可以在 Windows、Mac OSX 和 Linux 系统上运行。它没有本地 PHP 支持,但是有一个商业插件。

PHP 开发工具

PDT 项目( https://www.eclipse.org/pdt )目前看起来势头不小。在 Zend Technologies ltd .(https://www.zend.com)的支持下,并构建在开源 Eclipse 平台( https://www.eclipse.org )(一个用于构建开发工具的广受欢迎的可扩展框架)之上,PDT 很可能成为业余爱好者和专业人士事实上的开源 PHP IDE 的领跑者。

注意

Eclipse 框架已经成为许多项目的基础,这些项目促进了关键的开发任务,例如数据建模、商业智能和报告、测试和性能监控,以及最显著的编写代码。虽然 Eclipse 最出名的是它的 Java IDE,但它也有用于 C、C++、Cobol 以及最近的 PHP 等语言的 IDE。

Zend 工作室

ZendStudio 是当今所有商业和开源产品中最强大的 PHP IDE 之一。作为 Zend Technologies Ltd .的旗舰产品,Zend Studio 提供了企业 IDE 的所有功能,包括全面的代码完成、CVS、Subversion 和 git 集成、对 Docker 的支持、内部和远程调试、代码分析以及方便的代码部署过程。

除了能够执行 SQL 查询以及查看和管理数据库模式和数据之外,还提供了将代码与 MySQL、Oracle、PostgreSQL 和 SQLite 等流行数据库集成的工具。

Zend Studio ( https://www.zend.com/products/studio )可用于 Windows、Linux 和 Mac OS X 平台。

摘要

在这一章中,你学习了如何配置你的环境来支持 PHP 驱动的 web 应用的开发。特别关注 PHP 的许多运行时配置选项。最后,向您简要介绍了最常用的 PHP 编辑器和 ide,以及在搜索 web 托管提供商时需要注意的一些问题。

在下一章中,你将通过创建你的第一个 PHP 驱动的网页和学习该语言的基本特性来开始你对 PHP 语言的探索。根据其结论,您将能够创建简单但非常有用的脚本。这些材料为后续章节奠定了基础,在这些章节中,您将获得开始构建一些真正酷的应用所需的知识。

三、PHP 基础

这本书你只看了两章,已经涉及了相当多的内容。到目前为止,您已经熟悉了 PHP 的背景和历史,并且已经回顾了该语言的关键安装和配置概念和过程。到目前为止,您所学到的知识为本书的剩余内容奠定了基础:创建强大的 PHP 驱动的网站!本章开始了这一讨论,介绍了这种语言的大量基本特性。具体来说,您将学习如何执行以下操作:

  • 在你的网页中嵌入 PHP 代码。

  • 使用从 Unix shell 脚本、C 和 C++语言借用的各种方法对代码进行注释。

  • 使用echo(),print(), printf(),sprintf()语句将数据输出到浏览器。

  • 使用 PHP 的数据类型、变量、操作符和语句来创建复杂的脚本。

  • 利用关键控制结构和语句,包括if-else-elseifwhileforeach, include, require, break, continuedeclare.

学完这一章,你不仅会掌握创建基本但有用的 PHP 应用所必需的知识,还会理解如何充分利用后面章节中的内容。

注意

本章既是新手程序员的教程,也是新手程序员的参考。如果你属于前一类,考虑完整地阅读这一章,并跟随例子。

在你的网页中嵌入 PHP 代码

PHP 的一个优势是你可以直接将 PHP 代码嵌入到 HTML 中。为了让代码做任何事情,必须将页面传递给 PHP 引擎进行解释。但是 web 服务器不只是传递每一页;相反,它只传递那些按照第二章中的指令定义的由特定文件扩展名(通常是.php)标识的页面。但是,即使有选择地只将某些页面传递给引擎,对于引擎来说,将每一行都视为潜在的 PHP 命令也是非常低效的。因此,引擎需要一些方法来立即确定页面的哪些区域启用了 PHP。这在逻辑上是通过将代码包含在 PHP 标签中来实现的。PHP 标签通常被定义为开头的<?php和结尾的?>

每个文件可以包含一个 PHP 代码块,也可以包含嵌入整个文件的多个代码块。当文件包含单个 PHP 代码块时,通常会排除终止标签?>。这将消除任何内容,特别是作为输出的一部分发送给客户机的文件末尾的空白。

默认语法

默认分隔符语法以<?php开头,以?>结尾,如下所示:

<h3>Welcome!</h3>
<?php
    echo "<p>Some dynamic output here</p>";
?>
<p>Some static output here</p>

如果您将这段代码保存为first.php并从支持 PHP 的 web 服务器上执行它,您将看到如图 3-1 所示的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-1

PHP 输出示例

短标签

对于积极性不高的打字员,可以使用更短的分隔符语法。这种语法被称为短标签,它放弃了默认语法中所需的php引用。然而,要使用这个特性,您需要确保 PHP 的short_open_tag指令是启用的(这是默认的)。下面是一个例子:

<?
    print "This is another PHP example.";
?>

如果您想快速地进出 PHP 以输出一些动态文本,您可以使用一种称为 shortcircuit 语法的输出变体来省略这些语句,如下例所示。

<?="This is another PHP example.";?>

这在功能上等同于以下两种变体:

<? echo "This is another PHP example."; ?>
<?php echo "This is another PHP example.";?>

嵌入多个代码块

在一个给定的页面中,您可以根据需要多次进出 PHP。例如,下面的例子是完全可以接受的:

<html>
<head>
<title><?php echo "Welcome to my web site!";?></title>
</head>
<body>
<?php
         $date = "November 2, 2017";
      ?>
<p>Today's date is <?=$date;?></p>
</body>
</html>

如您所见,前面代码块中声明的任何变量都会被后面的代码块记住,本例中的$date变量就是这种情况。变量将在本章后面讨论。基本定义是所有变量都以一个$字符开头。这使得有一个名为$data的变量和一个名为date()的内部函数成为可能,并允许解释器知道其中的区别。

注释您的代码

无论是为了你自己的利益还是为了负责维护你的代码的人的利益,彻底注释你的代码的重要性不能被夸大。PHP 提供了几种语法变体,尽管和定界变体一样,只有两种用于 any regularly,这两种我都将在本节中介绍。

单行 C++语法

注释通常只需要一行,这意味着您需要做的就是在该行前面加上一个特殊的字符序列,告诉 PHP 引擎该行是一个注释,应该被忽略。这个字符序列就是双斜线,//

<?php
    // Title: My first PHP script
    // Author: Jason Gilmore
    echo "This is a PHP program.";
?>

作为双斜杠的替代,PHP 还支持 Perl 风格的注释,其中#被用作字符,表示该行的其余部分将被视为注释。

<?php
# Title: My first PHP script
# Author: Jason Gilmore
    echo "This is a PHP program."; # Some comment here
?>

//#都可以在一行代码的任何地方使用。PHP 解释器将忽略注释字符右边的所有内容。

phpDocumentor 的高级文档

因为文档是有效的代码创建和管理的如此重要的一部分,所以已经投入了相当大的努力来设计帮助开发人员自动化该过程的解决方案。事实上,现在所有主流编程语言都有先进的文档解决方案,包括 PHP。phpDocumentor ( https://www.phpdoc.org )是一个开源项目,它通过将源代码中嵌入的注释转换成各种易读的格式(包括 HTML 和 PDF)来简化文档处理过程。

phpDocumentor 的工作原理是解析应用的源代码,搜索被称为文档块 *的特殊注释。*文档块用于记录应用中的所有代码,包括脚本、类、函数、变量等等,它包含人类可读的解释以及形式化的描述符,如作者姓名、代码版本、版权声明、函数返回值等等。

即使你是一个编程新手,也要花些时间尝试一些高级的文档解决方案,比如 phpDox ( http://phpdox.de/ )。

多行注释

在代码中包含更详细的功能描述或其他解释性注释通常很方便,这在逻辑上保证了许多行。虽然您可以在每一行前面加一个双斜杠,但是 PHP 还提供了多行变体,可以在不同的行上打开和关闭注释。这里有一个例子:

<?php
    /*
      Processes PayPal payments
      This script is responsible for processing the customer's payment via PayPal.
accepting the customer'scredit card information and billing address.
      Copyright 2014W.J. Gilmore, LLC.
     */
?>

为了更加清晰,您经常会遇到每行都带有星号前缀的多行注释,如下所示:

<?php
    /*
* Processes PayPal payments
* This script is responsible for processing the customer's payment via PayPal.
     * accepting the customer'scredit card information and billing address.
* Copyright 2014 W.J. Gilmore, LLC.
     */
?> 

向客户端输出数据

当然,即使是最简单的动态网站也会向客户机(浏览器)输出数据,PHP 为此提供了几种方法。最常见的是print()函数和echo()语句。这两者有许多相似之处,也有一些不同之处。Echo 接受参数列表,不需要括号,也不返回值。要使用echo(),只需将你想要输出的参数传递给它,就像这样:

echo "I love the summertime.";

您还可以将多个变量传递给echo()语句,如下所示:

<?php
    $title = "<h1>Outputting content</h1>";
    $body = "<p>The content of the paragraph...</p>";
echo $ title , $ body ;
?>

该代码产生以下内容:

Outputting Content

The content of the paragraph...

当处理双引号字符串时,可以不使用连接操作符直接将变量嵌入到字符串中。只需将变量作为字符串"$title $body"的一部分。

PHP 用户更喜欢使用视觉提示来区分静态字符串和任何变量。您可以用花括号将变量括起来,如下所示:

echo "{$title} {$body}<p>Additional content</p>";

如果变量后面的字符串内容会被解释为变量的一部分,则需要括号。

<php
  $a = 5;
  echo "$a_abc<br/>";  //there is no variable $a_abc this will not show the value of $a
  echo "{$a}_abc<br/>";  //Now $a is isolated as a variable and the output will be as expected.

?>

第一个 echo 语句将产生一个空行,第二个语句将显示附加了 _abc 的值$a

5_abc

虽然 echo()看起来像一个函数,但它实际上是一个语言构造。这就是为什么它可以不带括号使用,并且允许传递逗号分隔的参数列表,如下例所示:

<php
  $a = "The value is: ";
  $b = 5;
  echo $a, $b;
?>

使用 printf()语句的复杂输出

当您想要输出存储在一个或几个变量中的静态文本和动态信息的混合时,printf()语句是理想的。它非常理想,原因有二。首先,它巧妙地将静态和动态数据分成两个不同的部分,从而提高了可读性并易于维护。第二,printf()允许您根据动态信息的类型、精度、对齐和位置,对动态信息在屏幕上的呈现方式进行相当大的控制。例如,假设您想将一个动态整数值插入到一个静态字符串中,如下所示:

printf("Bar inventory: %d bottles of tonic water.", 100);

执行此命令会产生以下结果:

Bar inventory: 100 bottles of tonic water.

在这个例子中, %d 是一个占位符,称为类型说明符,而 d 表示一个整数值将被放置在那个位置。当printf()语句执行时,唯一的参数100将被插入到占位符中。请记住,整数是预期的,因此如果您传递一个包含十进制值的数字(称为 float ),它将被向下舍入到最接近的整数。如果你传递100.2100.6,那么100将被输出。传递一个字符串值,比如“一百”,将会输出 0,尽管如果传递123food,那么123将会输出。类似的逻辑适用于其他类型说明符(常用说明符列表见表 3-1 )。

表 3-1

常用的类型说明符

|

类型

|

描述

|
| — | — |
| %b | 参数被视为整数;以二进制数表示 |
| %c | 参数被视为整数;表示为对应于该 ASCII 值的字符 |
| %d | 参数被视为整数;表示为带符号的十进制数 |
| %f | 被视为浮点数的参数;表示为浮点数 |
| %o | 参数被视为整数;表示为八进制数 |
| %s | 被视为字符串的参数;以字符串形式呈现 |
| %u | 参数被视为整数;表示为无符号十进制数 |

那么如果你想传递两个值呢?只需在字符串中插入两个说明符,并确保将两个值作为参数传递。例如,下面的printf()语句传入一个整数和浮点值:

printf("%d bottles of tonic water cost $%f.", 100, 43.20);

执行此命令会产生以下结果:

100 bottles of tonic water cost $43.200000.

因为$43.200000不是理想的货币表示,当处理小数值时,可以使用精度说明符将精度调整到两位小数。下面是一个例子:

printf("$%.2f", 43.2); // outputs $43.20

还有其他说明符用于调整参数的对齐、填充、符号和宽度。更多信息请参考 PHP 手册。

sprintf()语句

sprintf()语句在功能上与printf()相同,只是输出被分配给一个字符串,而不是作为输出呈现给客户端。原型如下:

string sprintf(string format [, mixed arguments])

下面是一个例子:

$cost = sprintf("$%.2f", 43.2); // $cost = $43.20

PHP 的数据类型

数据类型是分配给共享一组公共特征的任何数据的通用名称。常见的数据类型包括布尔、整数、浮点、字符串和数组。PHP 早就提供了一组丰富的数据类型,这将在下面讨论。

标量数据类型

标量数据类型用于表示单个值。有几种数据类型属于这一类别,包括布尔型、整型、浮点型和字符串型。

布尔代数学体系的

布尔数据类型以乔治·布尔(1815-1864)的名字命名,他是一位数学家,被认为是信息论的创始人之一。布尔数据类型代表真实,只支持两个值:true 和 false。或者,可以用零来表示FALSE,用任何非零值来表示TRUE。下面是几个例子:

$alive = false;       // $alive is false.
$alive = true;        // $alive is true.
$alive = 1;           // $alive is true.
$alive = -1;          // $alive is true, because -1 is nonzero.
$alive = 5;           // $alive is true.
$alive = 0;           // $alive is false.
$alive = 'a';         // $alive is true.
$alive = '1';         // $alive is true.
$alive = '0';         // $alive is false.

在上面的例子中,只有前两个赋值将导致一个布尔值被赋给变量$alive。其他赋值将产生一个字符串或整数值,见下文。当下面列出的任何值在if语句中使用时,如下所示,它们都将被视为布尔值。这是因为 PHP 在执行if语句之前做了必要的变量转换。

if ($alive) { ... }

如果值为 0、’ 0 '、false 或 null(未定义),则此语句为 false,在所有其他情况下为 true。字符串“0”的计算结果为 false,因为它首先被转换为整数,然后被转换为布尔值。

整数

一个整数代表任何整数,或者换句话说,一个不包含小数部分的数。PHP 支持几种基本格式的整数值,其中包括以 10 为基数(十进制)和以 16 为基数(十六进制)的计数系统,尽管您可能只关心第一种系统。整数表示的几个例子如下:

42           // decimal
-678900      // decimal
0755         // octal
0xC4E        // hexadecimal
0b1010       // binary

浮动

浮点数,也称为浮点数双精度数实数,允许您指定包含小数部分的数字。当一个简单的整数值不够用时,浮点数被用来表示货币值、重量、距离和一大堆其他的表示形式。PHP 的浮点可以用多种方式指定,这里演示了其中几种:

4.5678
4.0
8.7e4
1.23E+11

线

简单地说,字符串是被视为连续组的字符序列。字符串由单引号或双引号分隔,尽管 PHP 还支持另一种定界方法,这将在后面的“字符串插值”一节中介绍。

以下是有效字符串的所有示例:

"PHP is a great language"
"whoop-de-do"
'*9subway\n'
"123$%⁷⁸⁹"
"123"
"12.543"

最后两个值是数字字符串。PHP 允许在数学运算中使用它们,如下例所示:

<?php
$a = "123";
$b = "456";

echo $a + $b . "\n";
echo $a . $b . "\n";

不是 a 和 a 和 ab 如何被定义为字符串,而是当这些值相加时,它们将被转换为数字。在第二个示例中,我们使用串联运算符将两个字符串相加。

5791
23456

复合数据类型

复合数据类型允许相同类型或不同类型的多个项目聚集在单个代表性实体下。数组物体就属于这一类。

排列

将一系列相似的项目聚集在一起,以某种特定的方式排列和引用它们通常是有用的。这个数据结构被称为数组,正式定义为数据值的索引集合。数组索引的每个成员(也称为)引用一个对应的值,并且可以是对该值在序列中的位置的简单数字引用,也可以与该值有一些直接的关联。例如,如果您对创建美国各州的列表感兴趣,可以使用数字索引数组,如下所示:

$state[0] = "Alabama";
$state[1] = "Alaska";
$state[2] = "Arizona";
...
$state[49] = "Wyoming";

但是,如果这个项目需要将美国各州和它们的首都联系起来呢?您可以使用关联索引代替基于数字索引的键,如下所示:

$state["Alabama"] = "Montgomery";
$state["Alaska"] = "Juneau";
$state["Arizona"] = "Phoenix";
...
$state["Wyoming"] = "Cheyenne";

数组是在第五章正式介绍的,所以如果你现在还没有完全理解这些概念,不要太在意。

注意

PHP 还支持由几个维度组成的数组,更好的说法是多维数组。第五章也介绍了这个概念。

目标

PHP 支持的另一种复合数据类型是对象。对象是面向对象编程范例的核心概念。如果你是面向对象编程的新手,第六章和第七章会专门讨论这个话题。

与 PHP 语言中包含的其他数据类型不同,对象必须显式声明。对象特征和行为的声明发生在一个叫做的东西中。下面是一个类定义和后续调用的一般示例:

class Appliance {
   private $_power;
   function setPower($status) {
      $this->_power = $status;
   }
}
...
$blender = new Appliance;

一个类定义创建了几个与数据结构相关的属性和函数,在这个例子中,数据结构名为Appliance。只有一个属性power,可以使用setPower()方法进行修改。

但是,请记住,类定义是一个模板,它本身不能被操作。相反,基于该模板创建对象。这是通过关键字new完成的。因此,在前面清单的最后一行,创建了一个名为blender的类Appliance的对象。

然后可以利用setPower():方法设置blender对象的power属性

$blender->setPower("on");

第六章和第七章致力于 PHP 面向对象开发模型的全面覆盖。

使用类型转换在数据类型之间转换

将值从一种数据类型转换为另一种数据类型被称为类型转换。通过将变量转换为另一种类型,可以将变量作为不同的类型计算一次。这是通过将预期类型放在要转换的变量前面来实现的。可以通过在变量前插入表 3-2 中所示的操作符之一来转换类型。

表 3-2

铅字铸造操作员

|

强制转换运算符

|

转换

|
| — | — |
| (array) | 排列 |
| (bool)(boolean) | 布尔代数学体系的 |
| (int)(integer) | 整数 |
| (object) | 目标 |
| (real)(double)(float) | 浮动 |
| (string) | 线 |

让我们考虑几个例子。假设您想将一个整数转换为双精度型,如下所示:

$score = (double) 13; // $score = 13.0

将 double 类型转换为 integer 类型将导致整数值向下舍入,而不考虑小数值。这里有一个例子:

$score = (int) 14.8; // $score = 14

如果将字符串数据类型转换为整数数据类型,会发生什么情况?让我们来看看:

$sentence = "This is a sentence";
echo (int) $sentence; // returns 0

虽然这可能不是预期的结果,但很难说您是否愿意像这样转换字符串。当用于数学运算或使用 cast 运算时,PHP 会将字符串转换为有代表性的数值。另一个例子是字符串“123 house ”,它将被转换为数值 123。

您也可以将数据类型转换为数组的成员。被转换的值只是成为数组的第一个元素,就像这样:

$score = 1114;
$scoreboard = (array) $score;
echo $scoreboard[0]; // Outputs 1114

请注意,这不应该被认为是向数组中添加项目的标准做法,因为这似乎只适用于新创建的数组的第一个成员。如果对现有数组进行强制转换,该数组将被清除,仅在第一个位置留下新转换的值。有关创建数组的更多信息,请参见第五章。

最后一个例子:任何数据类型都可以被转换为对象。结果是变量变成了对象的属性,该属性的名称为scalar:

$model = "Toyota";
$obj = (object) $model;

然后,可以按如下方式引用该值:

print $obj->scalar; // returns "Toyota"

通过类型转换调整数据类型

由于 PHP 对类型定义的宽松态度,变量有时会被自动转换为最适合它们被引用的环境。考虑下面的片段:


<?php
    $total = 5;       // an integer
    $count = "15";    // a string
    $total = $total + $count; // $total = 20 (an integer)
?>

使用+=运算符可以将语句$total = $total + $count;写得更短:

$total += $count;

结果是预期的;$total被赋值为 20,在这个过程中把$count变量从字符串转换成整数。下面是另一个展示 PHP 类型转换能力的例子:

<?php
    $total = "45 fire engines";
    $incoming = 10;
echo $incoming + $total; // 55
?>

原始$total字符串开头的整数值用于计算。但是,如果它不是以数字表示开始,那么它的值就是0

让我们考虑最后一个特别有趣的例子。如果数学计算中使用的字符串包含代表科学记数法的eE (,它将被计算为浮点数,如下所示:

<?php
    $val1 = "1.2e3"; // "1200"
    $val2 = 2;
    echo $val1 * $val2; // outputs 2400 as 1.2e3 as a float is1200
?>

类型标识符函数

许多函数可用于确定变量的类型,包括is_array(), is_bool(), is_float(), is_integer(), is_null(), is_numeric(), is_object(), is_resource(), is_scalar(),is_string()。因为所有这些函数都遵循相同的命名约定、参数和返回值,所以它们的介绍被合并到一个示例中。通用原型如下:

boolean is_name(mixed var)

所有这些功能都集中在这一部分,因为每个功能最终都完成相同的任务。每个函数确定由var指定的变量是否满足由函数名指定的特定条件。如果var确实是函数名测试的类型,则返回TRUE;否则,返回FALSE。下面是一个例子:

<?php
    $item = 43;
    printf("The variable \$item is of type array: %d <br />", is_array($item));
    printf("The variable \$item is of type integer: %d <br />", is_integer($item));
    printf("The variable \$item is numeric: %d <br />", is_numeric($item));
?>

该代码返回以下内容:

The variable $item is of type array: 0
The variable $item is of type integer: 1
The variable $item is numeric: 1

虽然is_array()is_integer()is_numeric()函数返回一个布尔值,但代码显示输出为 0 和 1。这是因为在printf()语句中使用的%d 占位符会将布尔值转换成整数。

您可能对$item前面的反斜杠感到疑惑。考虑到美元符号标识变量的特殊目的,如果您想将它输出到屏幕上,必须有一种方法来告诉解释器将它作为普通字符处理。用反斜杠分隔美元符号将实现这一点。

使用变量操作动态数据

虽然变量在本章的许多例子中被使用,但是这个概念还没有被正式引入。本节从定义开始。变量是可以在不同时间存储不同值的符号。例如,假设您创建了一个能够执行数学任务的基于 web 的计算器。当然,用户会想要输入他选择的值;因此,程序必须能够动态存储这些值并相应地执行计算。同时,程序员需要一种用户友好的方式来引用应用中的这些值持有者。变量完成这两项任务。

鉴于这一编程概念的重要性,明确地为变量的声明和操作打下基础将是明智的。在本节中,将详细研究这些规则。

变量声明

一个变量总是以一个美元符号$开始,然后是变量名。变量名可以以字母或下划线开头,可以由字母、下划线、数字或 127 到 255 之间的其他 ASCII 字符组成。以下是所有有效的变量:

  • $color

  • $operating_system

  • $_some_variable

  • $model

以及一些无效变量名的例子:

  • $ color

  • $'test'

  • $-some-variable

请注意,变量区分大小写。例如,以下变量相互之间没有关系:

  • $color

  • $Color

  • $COLOR

在 PHP 中,变量不必像在 c 语言中那样显式声明,相反,变量可以同时声明和赋值。尽管如此,仅仅因为你做某事并不意味着你应该。良好的编程实践表明,所有变量都应该在使用前初始化,最好附带注释。如果变量在使用时没有定义,PHP 将赋予一个默认值。

一旦你初始化了你的变量,你可以在计算和输出中使用它们。变量赋值有两种方法:按值赋值和按引用赋值。

给变量赋值

按值赋值只是将被赋值表达式的值复制到变量 assignee。这是最常见的作业类型。下面是几个例子:

$color = "red";
$number = 12;
$age = 12;
$sum = $age + "15"; // $sum = 27

请记住,这些变量中的每一个都拥有分配给它的表达式的副本。例如,$number$age各自拥有值 12 的唯一副本。如果给其中一个赋值,另一个不受影响。如果你希望两个变量指向一个值的同一个副本,你需要通过引用来赋值。

通过引用分配变量

PHP 允许您通过引用来分配变量,这实质上意味着您可以创建一个变量来引用与另一个变量相同的内容。因此,对引用可变内容的特定项目的任何变量的改变将反映在引用相同内容的所有其他变量中。您可以通过在等号后面添加一个&符号&来引用变量。让我们考虑一个例子:

<?php
    $value1 = "Hello";
    $value2 =& $value1;    // $value1 and $value2 both equal "Hello"
    $value2 = "Goodbye";   // $value1 and $value2 both equal "Goodbye"
?>

还支持另一种引用赋值语法,即在被引用的变量前面附加&符号。以下示例遵循这一新语法:

<?php
    $value1 = "Hello";
    $value2 = &$value1;    // $value1 and $value2 both equal "Hello"
    $value2 = "Goodbye";   // $value1 and $value2 both equal "Goodbye"
?>

PHP 的超全局变量

PHP 提供了许多有用的预定义变量,可以从执行脚本中的任何地方访问这些变量,并为您提供大量特定于环境的信息。您可以筛选这些变量来检索关于当前用户会话、用户操作环境、本地操作环境等等的细节。在这一节中,我将介绍几个最常用的超全局变量,其他超全局变量的介绍留到后面的章节。让我们从一个输出通过$_SERVER超全局可用的所有数据的例子开始:

foreach ($_SERVER as $var => $value) {
   echo "$var => $value <br />";
}'

如您所见,相当多的信息是可用的——有些有用,有些不太有用。您可以只显示这些变量中的一个,只需将其视为常规变量。例如,使用它来显示用户的 IP 地址:

HTTP_HOST => localhost
HTTP_USER_AGENT => Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Firefox/24.0
HTTP_ACCEPT => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_LANGUAGE => en-US,en;q=0.5
HTTP_ACCEPT_ENCODING => gzip, deflate
HTTP_DNT => 1
HTTP_CONNECTION => keep-alive
PATH => /usr/bin:/bin:/usr/sbin:/sbin
SERVER_SIGNATURE =>
SERVER_SOFTWARE => Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8y DAV/2 PHP/5.3.6
SERVER_NAME => localhost
SERVER_ADDR => ::1
SERVER_PORT => 80
REMOTE_ADDR => ::1
DOCUMENT_ROOT => /Applications/MAMP/htdocs
SERVER_ADMIN => webmaster@dummy-host.example.com
SCRIPT_FILENAME => /Applications/MAMP/htdocs/5thedition/03/superglobal.php
REMOTE_PORT => 50070
GATEWAY_INTERFACE => CGI/1.1
SERVER_PROTOCOL => HTTP/1.1
REQUEST_METHOD => GET
QUERY_STRING =>
REQUEST_URI => /5thedition/03/superglobal.php
SCRIPT_NAME => /5thedition/03/superglobal.php
PHP_SELF => /5thedition/03/superglobal.php
REQUEST_TIME => 1383943162
argv => Array
argc => 0

如您所见,相当多的信息是可用的——有些有用,有些不太有用。您可以只显示这些变量中的一个,只需将其视为常规变量。例如,使用它来显示用户的 IP 地址:

printf("Your IP address is: %s", $_SERVER['REMOTE_ADDR']);

这将返回一个数字 IP 地址,如 192.0.34.166。

您还可以获得有关用户浏览器和操作系统的信息。考虑以下一行程序:

printf("Your browser is: %s", $_SERVER['HTTP_USER_AGENT']);

这将返回类似于以下内容的信息:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Firefox/24.0

这个例子只展示了 PHP 九个预定义变量数组中的一个。本节的其余部分将专门介绍每种方法的目的和内容。

了解有关服务器和客户端的更多信息

$_SERVER超全局包含由 web 服务器创建的信息,比如关于服务器和客户机配置以及当前请求环境的细节。虽然在$_SERVER中找到的变量的值和数量因服务器而异,但是您通常可以找到在 CGI 1.1 规范中定义的变量( https://www.w3.org/CGI )。您可能会发现所有这些变量在您的应用中都非常有用,其中一些变量包括:

  • 将用户指引到当前位置的页面的 URL。

  • $_SERVER['REMOTE_ADDR']:客户端的 IP 地址。

  • $_SERVER['REQUEST_URI']:URL 的路径部分。例如,如果网址是http://www.example.com/blog/apache/index.html,URI 就是/blog/apache/index.html

  • 客户端的用户代理,通常提供关于操作系统和浏览器的信息。

检索使用 GET 传递的变量

$_GET超全局包含与使用GET方法传递的任何参数相关的信息。如果请求 URL http://www.example.com/index.html?cat=apache&id=157 ,您可以通过使用$_GET超级全局变量来访问以下变量:

$_GET['cat'] = "apache"
$_GET['id'] = "157"

默认情况下,$_GET超全局是访问通过GET方法传递的变量的唯一方式。你不能像这样引用GET变量:$cat, $id.关于用 PHP 处理表单和安全访问外部数据的更多信息,请参见第十三章。

检索使用 POST 传递的变量

$_POST超全局包含与使用POST方法传递的任何参数相关的信息。考虑下面的 HTML 表单,用于请求订阅者信息:

<form action="subscribe.php" method="post">
<p>
      Email address:<br />
<input type="text" name="email" size="20" maxlength="50" value="" />
</p>
<p>
      Password:<br />
<input type="password" name="pswd" size="20" maxlength="15" value="" />
</p>
<p>
<input type="submit" name="subscribe" value="subscribe!" />
</p>
</form>

以下POST变量将通过目标subscribe.php脚本可用:$_POST['email']$_POST['pswd']$_POST['subscribe']

$_GET一样,$_POST超全局默认是访问POST变量的唯一方式。你不能像这样引用POST变量:$email, $pswd,和$subscribe。我将在第十三章中更多地谈论POST超级全球。

如果表单中的action参数看起来像“subscribe.php?mode=subscribe”,即使请求方法是 POST,模式变量也将在$_GET数组中可用。换句话说,$_GET数组将包含作为查询字符串的一部分传入的所有参数。

了解操作系统环境的更多信息

超级全局提供了关于 PHP 解析器底层服务器环境的信息。该数组中的一些变量包括:

  • $_ENV['HOSTNAME']:服务器主机名

  • $_ENV['SHELL']:系统外壳

注意

PHP 支持另外两个超级全局变量,即$GLOBALS$_REQUEST$_REQUEST超全局是各种各样的集合,记录通过GETPOSTCookie方法传递给脚本的变量。这些变量的顺序不取决于它们在发送脚本中出现的顺序;相反,它取决于由variables_order配置指令指定的顺序。$GLOBALS超全局数组可以被认为是超全局超集,它包含了全局范围内所有变量的完整列表。虽然这可能很诱人,但是您不应该使用这些超全局变量作为处理变量的方便方法,因为这是不安全的。参见第二十一章获取解释。

用常量管理常量数据

一个常量是一个在程序执行过程中不能被修改的值。常数在处理绝对不需要修改的值时特别有用,例如 Pi (3.141592)或一英里的英尺数(5,280)。一旦常量被定义,它就不能在程序的任何其他地方被改变(或重新定义)。使用define()函数或const关键字定义常量。

定义常数

define()函数通过给名称赋值来定义常数。考虑下面的例子,其中定义了数学常数 Pi:

define("PI", 3.141592);

或者使用 const 关键字:

Const PI = 3.141592;

该常数随后用于以下代码中:

printf("The value of Pi is %f", PI);
$pi2 = 2 * PI;
printf("Pi doubled equals %f", $pi2);

这段代码会产生以下结果:

The value of pi is 3.141592.
Pi doubled equals 6.283184.

关于这段代码有几点需要注意。第一个是常量引用没有以美元符号开头。第二是一旦定义了常量就不能重定义或者取消定义(比如 PI =2*PI);如果需要基于常量生成一个值,该值必须存储在另一个变量或常量中。最后,常数是全局的;除了下面提到的例外,它们可以在脚本中的任何地方被引用,通常的做法是将常量名称定义为全部大写字母。

使用const关键字和define()函数有一些不同。const键是在编译时计算的,因此在函数或 if 语句中使用是无效的。define 函数在运行时计算。用const键定义的常量总是区分大小写的,其中define()函数有第三个可选参数,允许不区分大小写的定义。

用表情采取行动

一个表达式是一个表示程序中特定动作的短语。所有表达式至少由一个操作数和一个或多个运算符组成。下面是几个例子:

$a = 5;                   // assigns integer value 5 to the variable $a
$a = "5";                 // assigns string value "5" to the variable $a
$sum = 50 + $some_int;    // assigns sum of 50 + $some_int to $sum
$wine = "Zinfandel";      // assigns "Zinfandel" to the variable $wine
$inventory++;             // increments the variable $inventory by 1

用操作数定义输入

操作数是一个表达式的输入。不仅通过日常的数学计算,而且通过以前的编程经验,您可能已经熟悉了操作数的操作和使用。操作数的一些例子如下:

$a++; // $a is the operand
$sum = $val1 + val2; // $sum, $val1 and $val2 are operands

用运算符定义操作

一个操作符是一个在表达式中指定一个特定动作的符号。很多运营商你可能都很熟悉。无论如何,您应该记住 PHP 的自动类型转换将根据放置在两个操作数之间的运算符的类型来转换类型,这在其他编程语言中并不总是如此。

运算符的优先性和结合性是编程语言的重要特征。这两个概念都将在本节中介绍。表 3-3 包含所有操作符的完整列表,按优先级从高到低排序。

表 3-3

运算符优先级、结合性和用途

|

结合性

|

经营者

|

附加说明

|
| — | — | — |
| 非联想性的 | 克隆新的 | clonenew |
| left | `` | array() |
| right | ** | arithmetic |
| right | +±~(int)(float)(string)(array)(object)(bool)@ | typesincrement/decrement |
| non-associative | instanceof | types |
| right | ! | logical |
| left | * / % | arithmetic |
| left | + -。 | arithmetic and string |
| left | << >> | bitwise |
| non-associative | < <= > >= | comparison |
| non-associative | == != === !== <> <=> | comparison |
| left | & | bitwise and references |
| left | ^ | bitwise |
| left | &#124; | bitwise |
| left | && | logical |
| left | &#124;&#124; | logical |
| right | ?? | comparison |
| left | ? : | ternary |
| right | = += -= *= **= /= .= %= &= &#124;= ^= <<= >>= | assignment |
| left | and | logical |
| left | xor | logical |
| left | or | logical |

运算符优先级

运算符优先级是运算符的一个特征,它决定了运算符对周围操作数求值的顺序。PHP 遵循小学数学课中使用的标准优先规则。考虑几个例子:

$total_cost = $cost + $cost * 0.06;

这与编写以下代码是一样的,因为乘法运算符的优先级高于加法运算符:

$total_cost = $cost + ($cost * 0.06);

理解运算符结合性

运算符的结合性特性指定了相同优先级的运算(即具有相同的优先级值,如表 [3-3 所示)在执行时的求值方式。关联性可以在两个方向上执行,从左到右或从右到左。从左到右的结合性意味着组成表达式的各种操作是从左到右计算的。考虑以下示例:

$value = 3 * 4 * 5 * 7 * 2;

前面的示例与下面的示例相同:

$value = ((((3 * 4) * 5) * 7) * 2);

这个表达式产生值840,因为乘法(*)运算符是从左到右关联的。

相反,从右到左的结合性从右到左计算相同优先级的运算符:

$c = 5;
echo $value = $a = $b = $c;

前面的示例与下面的示例相同:

$c = 5;
$value = ($a = ($b = $c));

当这个表达式被求值时,变量$value, $a, $b,$c都将包含值5,因为赋值操作符(=)具有从右向左的结合性。

算术运算符简介

表 3-4 中列出的算术运算符,执行各种数学运算,可能会在你的许多 PHP 程序中频繁使用。幸运的是,它们很容易使用。

顺便提一下,PHP 提供了大量预定义的数学函数,能够执行基数转换和计算对数、平方根、几何值等等。查看手册,获取这些功能的更新列表。

表 3-4

算术运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| $a + $b | 添加 | $a$b之和 |
| $a - $b | 减法 | $a$b的区别 |
| $a * $b | 增加 | $a$b的乘积 |
| $a / $b | 分开 | $a$b的商 |
| $a % $b | 系数 | $a除以$b的余数 |

赋值运算符

赋值运算符将数据值赋给变量。最简单的赋值操作符只是赋值,而其他的(被称为快捷赋值操作符)在赋值之前执行一些其他的操作。表 3-5 列出了使用这种操作器的例子。

表 3-5

赋值运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| $a = 5 | 分配 | $a等于 5 |
| $a += 5 | 加法-赋值 | $a等于$a加 5 |
| $a *= 5 | 乘法-赋值 | $a等于$a乘以 5 |
| $a /= 5 | 分工-分配 | $a等于$a除以 5 |
| $a .= 5 | 串联赋值 | $a等于与 5 连接的$a |

字符串运算符

PHP 的字符串操作符(见表 3-6 )提供了一种将字符串连接在一起的便捷方式。有两个这样的运算符,包括串联运算符(。)和串联赋值运算符(。=)在上一节讨论过。

注意

连接的意思是将两个或更多的对象结合在一起,形成一个单一的实体。

表 3-6

字符串运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| $a = "abc"."def"; | 串联 | $a被赋予字符串“abcdef" |
| $a .= "ghijkl"; | 串联赋值 | $a等于其与"ghijkl"连接的当前值 |

下面是一个涉及字符串运算符的示例:

// $a contains the string value "Spaghetti & Meatballs";
$a = "Spaghetti" . "& Meatballs";

$a .= " are delicious."
// $a contains the value "Spaghetti & Meatballs are delicious."

这两个串联操作符很难扩展 PHP 的字符串处理能力。参见第九章了解这一重要功能的完整说明。

递增和递减运算符

表 3-7 中列出的增量 ( ++)和减量 ( --)运算符在代码清晰性方面提供了一点便利,提供了一种简化的方法,通过这种方法可以将变量的当前值加 1 或减 1。

表 3-7

递增和递减运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| ++$a$a++ | 增量 | 将$a增加 1 |
| --$a$a-- | 减量 | 将$a减 1 |

这些操作符可以放在变量的任何一边,放在哪一边会产生稍微不同的效果。考虑以下示例的结果:

$inv = 15;         // Assigns integer value 15 to $inv
$oldInv = $inv--;  // Assigns $oldInv the value of $inv, then decrement $inv
$origInv = ++$inv; // Increments $inv, then assign the new $inv value to $origInv

如您所见,递增和递减运算符的使用顺序对变量值有重要影响。在操作数前面加上这些运算符之一称为前递增和前递减运算,而在操作数后面加上前缀称为后递增和后递减运算

逻辑运算符

就像算术运算符一样,逻辑运算符(见表 3-8 )可能会在许多 PHP 应用中扮演重要角色,提供一种基于多个变量的值做出决策的方法。逻辑操作符可以引导程序的流程,经常与控制结构一起使用,如if条件、whilefor循环。

逻辑运算符还通常用于提供其他运算结果的详细信息,尤其是那些返回值的运算:

$file = fopen("filename.txt", 'r') OR die("File does not exist!");

将会出现两种结果之一:

表 3-8

逻辑运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| $a && $b | 和 | 如果$a$b都为真,则为真 |
| $a AND $b | 和 | 如果$a$b都为真,则为真 |
| $a &#124;&#124; $b | 运筹学 | 如果$a$b为真,则为真 |
| $a OR $b | 运筹学 | 如果$a$b为真,则为真 |
| !$a | 不 | 如果$a不为真,则为真 |
| NOT $a | 不 | 如果$a不为真,则为真 |
| $a XOR $b | 异或 | 如果仅$a或仅$b为真,则为真 |

  • 文件filename.txt存在。

  • 句子“文件不存在!”将被输出。

等式运算符

相等运算符(见表 3-9 )用于比较两个值,测试是否相等。

表 3-9

等式运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| $a == $b | 等于 | 如果$a$b相等,则为真 |
| $a != $b | 不等于 | 如果$a不等于$b则为真 |
| $a === $b | 与相同 | 如果$a$b等价并且$a$b类型相同,则为真 |

即使是有经验的程序员也很容易犯这样的错误:试图只使用一个等号(例如$a = $b)来测试相等性。请记住,这将导致将$b的内容分配给$a,从而不会产生预期的结果。它将根据$b的值评估为真或假。

比较运算符

比较运算符(见表 3-10 )像逻辑运算符一样,通过检查两个或多个变量的比较值,提供了一种引导程序流程的方法。

表 3-10

比较运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| $a < $b | 不到 | 如果$a小于$b则为真 |
| $a > $b | 大于 | 如果$a大于$b则为真 |
| $a <= $b | 小于或等于 | 如果 a 小于或等于 ‘ a 小于或等于` a小于或等于b,则为真 | | $a >= b ‘ ∣ 大于或等于 ∣ 如果 ‘ b` | 大于或等于 | 如果` b‘∣大于或等于如果a大于或等于 b ‘ 则为真 ∣ ∣ ‘ b`则为真 | | ` b则为真∣∣‘a <=> b ‘ ∣ 小于、等于或大于 ∣ o 如果两个值相等,如果 b` | 小于、等于或大于 | o 如果两个值相等,如果 b‘∣小于、等于或大于o如果两个值相等,如果a 小于 b ,则为 − 1 ,如果 b,则为-1,如果 b,则为1,如果a 大于 b ,则为 1 。这是 P H P 7.0 中引入的“飞船”运算符 ∣ ∣ ‘ ( b,则为 1。这是 PHP 7.0 中引入的“飞船”运算符 | | `( b,则为1。这是PHP7.0中引入的飞船运算符∣∣‘(a == 12) ? 5 : -1 | 第三的 | 如果 a ‘ 等于 ‘ 12 ‘ ,返回值为 ‘ 5 ‘ ;否则,返回值为 ‘ – 1 ‘ ∣ ∣ ‘ a`等于`12`,返回值为`5`;否则,返回值为`–1` | | ` a等于‘12‘,返回值为‘5‘;否则,返回值为‘–1‘∣∣‘a ?: 5| 三元速记 | 如果真值与表达式相同,则可以省去三元运算符的中间部分。 | | a ? ? ′ d e f a u l t ′ ‘ ∣ 零合并算子 ∣ 这是 P H P 7.0 中引入的,它首先检查是否给 a ?? 'default'` | 零合并算子 | 这是 PHP 7.0 中引入的,它首先检查是否给 a??default‘∣零合并算子这是PHP7.0中引入的,它首先检查是否给a 赋值,如果是,它将返回$a,如果没有赋值,将返回“默认”值。 |

请注意,比较运算符应该只用于比较数值。尽管您可能想用这些操作符来比较字符串,但如果您这样做,很可能不会得到预期的结果。有一组预定义的函数来比较字符串值;第九章详细讨论了这些问题。

按位运算符

按位运算符在构成整数值(因此得名)的单个位的级别上检查和操作整数值。要完全理解这个概念,您至少需要十进制整数的二进制表示的介绍性知识。表 3-11 显示了一些十进制整数及其相应的二进制表示。

表 3-11

二进制表示

|

十进制整数

|

二进制表示法

|
| — | — |
| Two | Ten |
| five | One hundred and one |
| Ten | One thousand and ten |
| Twelve | One thousand one hundred |
| One hundred and forty-five | Ten million ten thousand and one |
| One million four hundred and fifty-two thousand and twelve | 101100010011111101100 |

表 3-12 中列出的按位运算符是一些逻辑运算符的变体,但可能会导致截然不同的结果。

表 3-12

按位运算符

|

例子

|

标签

|

结果

|
| — | — | — |
| $a & $b | 和 | 以及包含在$a$b中的每个位 |
| $a &#124; $b | 运筹学 | 或者包含在$a$b中的每个位 |
| $a ^ $b | 异或 | 异或——将包含在$a$b中的每一位相加 |
| ~ $b | 不 | 对$b中的每一位取反 |
| $a << $b | 左移位 | $a将接收到左移两位的$b的值 |
| $a >> $b | 右移 | $a将接收到的$b的值右移两位 |

对于初学者来说,很少使用按位运算符,但是如果您有兴趣了解更多关于二进制编码和按位运算符以及它们为什么重要的信息,请查看 Randall Hyde 的大量在线参考资料“汇编语言编程的艺术”,可在 http://webster.cs.ucr.edu 获得。

字符串插值

为了给开发人员在处理字符串值时提供最大的灵活性,PHP 提供了字面和比喻解释的方法。例如,考虑以下字符串:

The $animal jumped over the wall.\n

您可能会假设$animal是一个变量,而\n是一个换行符,因此两者都应该被相应地解释。但是,如果您希望完全按照书写的内容输出字符串,或者您希望呈现换行符,但希望变量以文字形式显示($animal),或者反之亦然,该怎么办呢?所有这些变化在 PHP 中都是可能的,这取决于字符串是如何封装的,以及某些关键字符是否通过预定义的序列进行转义。这些主题是本节的重点。

双引号

双引号中的字符串是 PHP 脚本中最常用的,因为它们提供了最大的灵活性。这是因为变量和转义序列都会被相应地解析。考虑以下示例:

<?php
    $sport = "boxing";
    echo "Jason's favorite sport is $sport.";
?>

此示例返回以下内容:

Jason's favorite sport is boxing.

转义序列

转义序列也被解析。考虑这个例子:

<?php
    $output = "This is one line.\nAnd this is another line.";
    echo $output;
?>

这将返回以下内容:

This is one line.And this is another line.

值得重申的是,这个输出是在浏览器源代码中找到的,而不是在浏览器窗口中。只要内容类型设置为 text/html,浏览器窗口就会忽略这种风格的换行符。但是,如果您查看源代码,您会看到输出实际上出现在两个单独的行上。如果数据被输出到文本文件,同样的想法也适用。

除了换行符之外,PHP 还识别许多特殊的转义序列,所有这些都在表 3-13 中列出。

表 3-13

公认的转义序列

|

顺序

|

描述

|
| — | — |
| \n | 换行符 |
| \r | 回车 |
| \t | 横表 |
| \\ | 反斜线符号 |
| \$ | 美元符 |
| \" | 双引号 |
| \[0-7]{1,3} | 八分音符 |
| \x[0-9A-Fa-f]{1,2} | 十六进制符号 |

单引号

当字符串应该被准确地解释时,用单引号将字符串括起来非常有用。这意味着在解析字符串时,变量和转义序列都不会被解释。例如,考虑以下单引号字符串:

print 'This string will $print exactly as it\'s \n declared.';

这会产生以下结果:

This string will $print exactly as it's \n declared.

注意,位于 it 的中的单引号被转义。省略反斜杠转义字符将导致语法错误。考虑另一个例子:

print 'This is another string.\\';

这会产生以下结果:

This is another string.\

在这个例子中,出现在字符串末尾的反斜杠必须被转义;否则,PHP 解析器会理解尾部的单引号将被转义。但是,如果反斜杠出现在字符串中的任何其他地方,就没有必要对它进行转义。

花括号

虽然 PHP 完全能够插入表示标量数据类型的变量,但您会发现,表示复杂数据类型(如数组或对象)的变量在嵌入到echo()语句中时就不那么容易解析了。您可以通过在花括号中分隔变量来解决这个问题,如下所示:

echo "The capital of Ohio is {$capitals['ohio']}.";

就个人而言,我更喜欢这种语法,因为它清楚地表明了字符串的哪些部分是静态的,哪些部分是动态的。

埃多克

语法为输出大量文本提供了一种方便的方法。使用两个相同的标识符,而不是用双引号或单引号来分隔字符串。下面是一个例子:

<?php
$website = "http://www.romatermini.it";
echo <<<EXCERPT
<p>Rome's central train station, known as <a href = "$website">Roma Termini</a>, was built in 1867\. Because it had fallen into severe disrepair in the late 20th century, the government knew that considerable resources were required to rehabilitate the station prior to the 50-year <i>Giubileo</i>.</p>
EXCERPT;
?>

关于这个例子,有几点是没有价值的:

  • 开始和结束标识符(在本例中,EXCERPT)必须相同。您可以随意选择任何标识符,但它们必须完全匹配。唯一的限制是标识符必须只由字母数字字符和下划线组成,并且不能以数字或下划线开头。

  • 开始标识符前面必须有三个左尖括号(<<<))。

  • Heredoc 语法遵循与双引号中的字符串相同的解析规则。也就是说,变量和转义序列都被解析。唯一的区别是双引号不需要转义。

  • 结束标识符必须从一行的最开头开始。它不能以空格或任何其他无关字符开头。这是用户中经常出现的困惑点,所以要特别注意确保您的 heredoc 字符串符合这个烦人的要求。此外,在开始或结束标识符后出现任何空格都会产生语法错误。

当您需要处理大量材料,但又不想忍受转义引号的麻烦时,Heredoc 语法特别有用。

单引号

nowdoc 语法的操作与 heredoc 语法相同,只是不解析 nowdoc 中的任何分隔文本。例如,如果您想在浏览器中显示一段代码,您可以将它嵌入到 nowdoc 语句中;当随后输出 nowdoc 变量时,您可以确信 PHP 不会试图将任何字符串作为代码插入。

用控制结构进行控制

控制结构决定了应用中的代码流,定义了执行特性,如特定代码语句是否执行以及执行多少次,以及代码块何时放弃执行控制。这些结构还提供了一种简单的方法,将全新的代码部分(通过文件包含语句)引入到当前正在执行的脚本中。在这一节中,您将了解 PHP 语言可用的所有此类控制结构。

用条件语句做决策

条件语句使你的计算机程序能够对各种各样的输入做出相应的反应,使用逻辑根据输入值辨别各种条件。这种功能对于创建计算机软件来说是如此的基础,所以各种各样的条件语句成为包括 PHP 在内的所有主流编程语言的主食也就不足为奇了。

if 语句

if语句是任何主流编程语言中最常见的构造之一,为条件代码执行提供了一种方便的方法。以下是语法:

if (expression) {
    statement
}

当只需要一条语句时,可以省去花括号,将 if 语句写在一行中。如果需要一个以上的语句,它们必须用花括号括起来,告诉解释器在语句为真的情况下执行什么。例如,假设您希望在用户猜出一个预定的秘密数字时显示一条祝贺消息:

<?php
    $secretNumber = 453;
    if ($_POST['guess'] == $secretNumber) {
        echo "Congratulations!";
    }
?>

else 语句

前一个例子的问题是,输出只提供给正确猜出密码的用户。所有其他使用者都变得一无所有,完全被冷落,原因可能与他们缺乏精神力量有关。如果无论结果如何,您都希望提供量身定制的响应,该怎么办?为此,您需要一种方法来响应那些不满足if条件要求的用户,这是通过else语句方便地提供的特性。下面是对上一个示例的修改,这次在两种情况下都提供了响应:

<?php
    $secretNumber = 453;
    if ($_POST['guess'] == $secretNumber) {
        echo "Congratulations!";
    } else {
        echo "Sorry!";
    }
?>

if一样,如果只包含一个代码语句,那么else语句括号可以跳过。

埃尔塞夫声明

在“非此即彼”的情况下——也就是说,在只有两种可能结果的情况下,if-else组合工作得很好。但是如果几种结果都有可能呢?您需要一种方法来考虑每种可能的结果,这可以通过elseif语句来实现。让我们再次修改秘密数字的例子,这次如果用户的猜测与秘密数字相对接近(在 10 以内),则提供一条消息:

<?php
    $secretNumber = 453;
    $_POST['guess'] = 442;
    if ($_POST['guess'] == $secretNumber) {
        echo "Congratulations!";
    } elseif (abs ($_POST['guess'] - $secretNumber) < 10) {
        echo "You're getting close!";
    } else {
        echo "Sorry!";
    }
?>

像所有条件句一样,elseif支持在只包含一个语句时取消括号。

switch 语句

您可以将switch语句视为if-else组合的变体,通常在需要将一个变量与大量值进行比较时使用:

<?php
    switch($category) {
        case "news":
            echo "What's happening around the world";
            break;
        case "weather":
            echo "Your weekly forecast";
            break;
        case "sports":
            echo "Latest sports highlights";
            echo "From your favorite teams";
            break;
        default:
            echo "Welcome to my web site";
    }
?>

请注意,在每个 case 块的结尾都有 break 语句。如果 break 语句不存在,所有后续的 case 块都将执行,直到找到 break 语句。为了说明这种行为,让我们假设 break 语句已从前面的示例中删除,并且$category已设置为 weather。您会得到以下结果:

Your weekly forecast
Latest sports highlights
Welcome to my web site

用循环语句重复迭代

尽管存在各种各样的方法,但是循环语句是每一种广泛使用的编程语言中的一个固定部分。循环机制为完成编程中的普通任务提供了一种简单的方法:重复一系列指令,直到满足特定的条件。PHP 提供了几个这样的机制,如果你熟悉其他编程语言的话,这些机制都不足为奇。

while 语句

while语句指定了在其嵌入代码的执行被终止之前必须满足的条件。其语法如下:

while (expression) {
    statements
}

在下面的例子中,$count被初始化为值1。然后将$count的值平方并输出。然后$count变量增加 1,循环重复,直到$count的值达到5

<?php
    $count = 1;
    while ($count < 5) {
        printf("%d squared = %d <br>", $count, pow($count, 2));
        $count++;
    }
?>

输出如下所示:

1 squared = 1
2 squared = 4
3 squared = 9
4 squared = 16

do…while 语句

do...while循环语句是while,的变体,但是它在块的结尾而不是开始时验证循环条件。以下是它的语法:

do {
    statements
} while (expression);

whiledo...while的功能都差不多。唯一真正的区别是嵌入在while语句中的代码可能永远不会被执行,而嵌入在do...while语句中的代码至少会执行一次。考虑以下示例:

<?php
    $count = 11;
    do {
        printf("%d squared = %d <br />", $count, pow($count, 2));
    } while ($count < 10);
?>

以下是结局:

11 squared = 121

尽管事实上 11 超出了while条件的界限,但是嵌入式代码将执行一次,因为条件直到结束时才被评估。

for 语句

for语句提供了比while更复杂的循环机制。以下是它的语法:

for (expression1; expression2; expression3) {
    statements
}

当使用 PHP 的for循环时,有一些规则要记住:

  • 默认情况下,第一个表达式expression1在循环的第一次迭代时计算。

  • 第二个表达式expression2在每次迭代开始时计算。这个表达式决定循环是否继续。

  • 第三个表达式expression3在每个循环结束时计算。

  • 任何表达式都可以是空的,它们的用途由嵌入在for块中的逻辑代替。

记住这些规则,考虑下面的例子,所有这些例子都显示了部分公里/英里等值图:

// Example One
define('KILOMETER_TO_MILE', 0.62140);
for ($kilometers = 1; $kilometers <= 5; $kilometers++) {
    printf("%d kilometers = %f miles <br>", $kilometers, $kilometers*constant('KILOMETER_TO_MILE'));
}

// Example Two
define('KILOMETER_TO_MILE', 0.62140);
for ($kilometers = 1; ; $kilometers++) {
    if ($kilometers > 5) break;
    printf("%d kilometers = %f miles <br>", $kilometers, $kilometers*constant('KILOMETER_TO_MILE'));
}

// Example Three
define('KILOMETER_TO_MILE', 0.62140);
$kilometers = 1;
for (;;) {
    // if $kilometers > 5 break out of the for loop.
if ($kilometers > 5) break;
    printf("%d kilometers = %f miles <br>", $kilometers, $kilometers*constant('KILOMETER_TO_MILE'));
    $kilometers++;
}

所有三个示例的结果如下:

1 kilometers = 0.621400 miles
2 kilometers = 1.242800 miles
3 kilometers = 1.864200 miles
4 kilometers = 2.485600 miles
5 kilometers = 3.107000 miles

foreach 语句

foreach循环构造语法擅长循环遍历数组,从数组中取出每个键/值对,直到所有的项都被检索到或者满足了其他一些内部条件。有两种语法变体,每种都有一个示例介绍。

第一个语法变体从数组中复制每个值,每次迭代都将指针移近末尾。以下是它的语法:

foreach ($array_expr as $value) {
    statement
}

假设您想要输出一个链接数组,如下所示:

<?php
    $links = array("www.apress.com","www.php.net","www.apache.org");
    echo "Online Resources<br>";
    foreach($links as $link) {
echo "{$link}<br>";
}
?>

这将导致以下结果:

Online Resources
www.apress.com
www.php.net
www.apache.org

第二种变化非常适合处理数组的键和值。语法如下:

foreach (array_expr as $key => $value) {
    statement
}

修改前面的例子,假设$links是一个关联数组,包含一个链接和一个相应的链接标题:

$links = array("The Apache Web Server" => "www.apache.org",
               "Apress" => "www.apress.com",
               "The PHP Scripting Language" => "www.php.net");

每个数组项都由一个键和一个对应的值组成。foreach语句可以轻松地从数组中剥离每个键/值对,如下所示:

echo "Online Resources<br>";
foreach($links as $title => $link) {
echo "<a href=\"http://{$link}\">{$title}</a><br>";
}

结果是每个链接都嵌入在各自的标题下,就像这样(为了清楚起见,输出包括 HTML 格式):

Online Resources:<br />
<a href="http://www.apache.org">The Apache Web Server</a><br />
<a href="http://www.apress.com">Apress</a><br />
<a href="http://www.php.net">The PHP Scripting Language</a><br />

这种键/值检索方法还有其他变化,所有这些都在第五章中介绍。

中断语句

遇到break语句将立即结束do...whilefor, foreach, switchwhile块的执行。例如,如果一个素数是伪随机发生的,下面的for循环将终止:

<?php
    $primes = array(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47);
    for($count = 1; $count++; $count < 1000) {
        $randomNumber = rand(1,50);
        if (in_array($randomNumber,$primes)) {
printf("Prime number found! %d <br />", $randomNumber);
            break;
        } else {
            printf("Non-prime number found: %d <br />", $randomNumber);
        }
    }
?>

示例输出如下:

Non-prime number found: 48
Non-prime number found: 42
Prime number found: 17

continue 语句

continue语句导致当前循环迭代的执行结束,并在下一次迭代开始时开始执行。例如,如果发现$usernames[$x]具有值missing,将重新开始执行下面的while主体:

<?php
    $usernames = array("Grace","Doris","Gary","Nate","missing","Tom");
    for ($x=0; $x < count($usernames); $x++) {
        if ($usernames[$x] == "missing") continue;
        printf("Staff member: %s <br />", $usernames[$x]);
    }
?>

这会产生以下输出:

Staff member: Grace
Staff member: Doris
Staff member: Gary
Staff member: Nate
Staff member: Tom

文件包含语句

高效的程序员总是考虑确保可重用性和模块化。确保这一点的最普遍的方法是将功能组件隔离到单独的文件中,然后根据需要重新组装这些文件。PHP 提供了四种将这类文件包含到应用中的语句,本节将对每种语句进行介绍。

include()语句

include()语句将评估一个文件,并将它包含到被调用的位置。只要包含的文件只包含 PHP 代码,包含文件产生的结果与将代码从指定的文件复制到语句出现的位置相同。如果文件包含 HTML,它将被传递到客户端而不做进一步处理。当页面包含 HTML 的静态部分时,这是很有用的。其原型如下:

include(/path/to/filename)

printecho语句一样,您可以选择在使用include().时省略括号。例如,如果您想要包含一系列预定义的函数和配置变量,您可以将它们放入一个单独的文件中(例如,称为init.inc.php,然后将该文件包含在每个 PHP 脚本的顶部,如下所示:

<?php
    include "/usr/local/lib/php/wjgilmore/init.inc.php";
?>

关于include()语句的一个误解是,因为包含的代码将被嵌入到 PHP 执行块中,所以不需要 PHP 转义标签。然而,事实并非如此;必须始终包含分隔符。因此,您不能只是将一个 PHP 命令放在一个文件中,并期望它能正确解析,如下所示:

echo "this is an invalid include file";

相反,任何 PHP 语句都必须用正确的转义标记括起来,如下所示:

<?php
    echo "this is an invalid include file";
?>

小费

在包含文件中找到的任何代码都将继承其调用方位置的变量范围。范围的概念将在关于函数的第四章中进一步讨论。

确保一个文件只包含一次

include_once()函数与include()的目的相同,只是它首先验证文件是否已经被包含。其原型如下:

include_once (filename)

如果已经包含了一个文件,include_once()将不会执行。否则,它将根据需要包含该文件。除此之外,include_once()的运行方式与include()完全相同。

两个include() and include_once()都可以在条件语句中使用,允许基于逻辑包含不同的文件。这可用于包含基于配置值的特定数据库抽象。

需要一个文件

在大多数情况下,require()的操作类似于include(),,包括一个模板到require()调用所在的文件中。其原型如下:

require (filename)

require()include()的区别是没有找到被引用文件时的结果。require()将发布一个编译器错误并停止执行,而include()将导致一个警告并继续执行。

小费

只有在默认情况下启用了allow_url_fopen时,URL 才能与require()一起使用。注意不要加载超出你控制范围的内容。

第二个重要的区别是,如果一个require()语句失败,脚本执行将会停止,而在一个include() statement语句的情况下,脚本执行可能会继续。对require()语句失败的一个可能的解释是错误引用的目标路径。

确保一个文件只需要一次

随着站点的增长,您可能会发现自己冗余地包含了某些文件。虽然这可能并不总是一个问题,但有时您不希望被包含文件中修改的变量被随后包含的同一个文件覆盖。出现的另一个问题是函数名的冲突,如果它们存在于包含文件中的话。你可以用require_once()函数解决这些问题。其原型如下:

require_once (filename)

require_once()函数确保包含文件在脚本中只包含一次。遇到require_once()后,任何后续的包含相同文件的尝试都将被忽略。

除了require_once(),的验证程序,该功能的所有其他方面与require()相同。

摘要

尽管这里提供的材料没有后面章节中的那么吸引人,但它对你成为一名成功的 PHP 程序员来说是无价的,因为所有后续的功能都是基于这些构件的。

下一章正式介绍了函数的概念,函数是用来执行特定任务的可重用代码块。这些材料将引导您开始构建模块化、可重用的 PHP 应用。