文章目录
- PHP运行原理和机制
- PHP 的设计理念及特点
- PHP 的四层体系
- 1) Zend 引擎(核心)
- 2) Extensions(扩展)
- 3) SAPI(服务器应用程序编程接口)
- 4) Application(上层应用)
- 总结
- PHP 常见的运行模式
- CGI
- FastCGI
- APACHE2HANDLER
- apache 模块的 DLL
- ISAPI
- CLI
- PHP 的执行流程和 opcode
- HashTable
- Zval
- 静态网页与动态网页的区别
- 静态网页
- 动态页面
- 动态网页与传统网页的区别
- 1) 更新和维护
- 2) 交互性
- 3) 响应速度
- 搭建PHP开发环境
- 第一个PHP程序
- MySQL数据库简介
- MySQL 是什么
- MySQL 特点
- 1) 功能强大
- 2) 支持跨平台
- 3) 运行速度快
- 4) 支持面向对象
- 5) 安全性高
- 6) 成本低
- 7) 支持各种开发语言
- 8) 数据库存储容量大
- 9) 支持强大的内置函数
- 数据库的应用
- 数据库在 Web 开发中的重要地位
- PHP 和 MySQL 的合作方式
- PHP连接数据库
- 连接 MySQL 数据库
- 1) 面向过程风格的写法
- 2) 面向对象风格的写法
- PHP mysqli_select_db():选择数据库
- 面向对象风格的写法:
- 面向过程风格的写法:
- 1) 面向对象风格的写法:
- 2) 面向过程风格的写法:
- PHP mysqli_query():执行SQL语句
- 面向对象风格的写法:
- 面向过程风格的写法:
- 1) 面向对象风格的写法
- 2) 面向过程风格的写法
- PHP获取SQL的查询结果
- 1、mysqli_fetch_row() 函数
- 面向对象风格的写法
- 面向过程风格的写法
- 2、mysqli_fetch_assoc() 函数
- 面向对象风格的写法
- 面向过程风格的写法
- 3、mysqli_fetch_array() 函数
- 面向对象风格的写法
- 面向过程风格的写法
- 4、mysqli_fetch_all() 函数
- 面向对象风格的写法
- 面向过程风格的写法
- 5、mysqli_fetch_object() 函数
- 面向对象风格的写法
- 面向过程风格的写法
- Apache教程
- Apache支持PHP程序
- Apache中的Php处理程序
PHP运行原理和机制
虽然说 PHP 学起来相对简单,但是要精通也不是一件简单的事,我们除了要知道怎么使用之外,还得知道它的工作原理。
PHP 是一种适用于 Web 开发的脚本语言,可以将它看做是一个用C语言实现的包含大量组件的软件框架。
了解 PHP 的底层实现,有助于我们更好的运用它,优化我们程序的性能,从而实现更加强大的功能。
PHP 的设计理念及特点
PHP 被设计为一种适用于 Web 开发的动态脚本语言,底层完全由C语言实现,它具备以下特点。
- 解释型:程序一行一行的边解释边运行;
- 弱类型:和 C/C++、JAVA、C# 等语言不同,PHP 是一种弱类型的语言。定义 PHP 变量时不用指明它的类型,它的类型根据赋值的数据自动调整;另外,一个变量的类型也不是一成不变的,在运行过程中可以给变量赋值不同类型的数据,从而修改变量的类型。这种机制的灵活性在 Web 开发中非常方便和高效;
- 多进程模型:由于 PHP 是多进程模型,不同请求间互不干涉,这样保证了一个请求挂掉不会对全盘服务造成影响;当然,随着时代发展,PHP 也已经支持了多线程模型;
- 使用引擎(Zend) + 组件(ext)的模式降低内部耦合;
- 中间层(sapi)隔绝 web server 和 PHP。
PHP 的四层体系
PHP 的核心架构如下图所示:
图1:PHP的核心架构
从上图可以看出,PHP 从下到上是可以分为 4 层:
1) Zend 引擎(核心)
Zend 引擎整体用C语言实现,是 PHP 的内核部分,它负责将 PHP 代码翻译(词法、语法解析等一系列编译过程)为可执行的 opcode 操作码,并实现相应的处理方法、基本的数据结构(如 hashtable、oo)、内存分配及管理、提供相应的 API 方法供外部调用。
Zend 是一切的核心,所有的外围功能均围绕 Zend 实现。
2) Extensions(扩展)
围绕着 Zend 引擎,Extensions 通过组件化的方式提供各种基础服务,我们常见的各种内置函数(例如变量操作函数、字符串操作函数等)以及标准库等都是通过 Extensions 来实现。
用户也可以根据需要实现自己的 Extension 组件以达到功能扩展、性能优化等目的,这就是高手常说的“编写 PHP 扩展”。
3) SAPI(服务器应用程序编程接口)
SAPI 全称是 Server Application Programming Interface,译为“服务器应用程序编程接口”。
SAPI 通过一系列钩子函数,使得 PHP 可以和外围交互数据,这是 PHP 非常优雅和成功的一个设计,通过 SAPI 成功的将 PHP 本身和上层应用解耦隔离,PHP 可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。
4) Application(上层应用)
这就是我们平时编写的 PHP 程序,通过不同的 SAPI 方式得到各种各样的应用模式,例如通过 Web 服务器实现网站后台、在命令行下以脚本方式运行等。
总结
如果将 PHP 看作一辆汽车,那么车的框架就是 PHP 本身,Zend 是车的引擎(发动机),Ext 下面的各种组件就是车的轮子,SAPI 可以看做是公路,车可以跑在不同类型的公路上,而一次 PHP 程序的执行就是汽车真正跑在公路上。
要想让汽车跑得快,性能优异的引擎+合适的车轮+正确的跑道都是缺一不可的。
PHP 常见的运行模式
SAPI 即服务器应用程序编程接口,是 PHP 与其他应用交互的接口,PHP 脚本要执行有很多方式,比如通过 Web 服务器、命令行下或者嵌入在其他程序中。
SAPI 提供了一个和外部通信的接口,常见的 SAPI 有:cgi、fast-cgi、cli、apache 模块的 DLL、isapi 等。
CGI
CGI 即通用网关接口(Common Gateway Interface),它是一段程序,通俗的讲 CGI 就象是一座桥,把网页和 WEB 服务器中的执行程序连接起来,它把 HTML 接收的指令传递给服务器的执行程序,再把服务器执行程序的结果返还给 HTML。
CGI 的跨平台性能极佳,几乎可以在任何操作系统上实现。
CGI 在遇到连接请求后,会先要创建 CGI 的子进程,激活一个 CGI 进程,然后处理请求,处理完后结束这个子进程,这就是 fork-and-execute 模式。
综上所述,使用 CGI 方式的服务器有多少连接请求就会有多少 CGI 子进程,子进程反复加载 会导致 CGI 性能低下。当用户请求数量非常多时,会大量挤占系统的资源,如内存、CPU 时间等,造成性能低下。
FastCGI
fast-cgi 是 CGI 的升级版本,FastCGI 像是一个常驻(long-live)型的 CGI,它激活后可以一直执行着。
FastCGI 的工作原理:
- Web Server 启动时载入 FastCGI 进程管理器(IIS ISAPI 或 Apache Module);
- FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程(可见多个 php-cgi)并等待来自 Web Server 的连接;
- 当客户端请求到达 Web Server 时,FastCGI 进程管理器选择并连接到一个 CGI 解释器。Web server 将 CGI 环境变量和标准输入发送到 FastCGI子进程 php-cgi;
- FastCGI 子进程完成处理后将标准输出和错误信息从同一连接返回 Web Server。当 FastCGI 子进程关闭连接时,请求便处理完成了。FastCGI 子进程接着等待并处理来自 FastCGI 进程管理器(运行在 Web Server 中)的下一个连接。 在 CGI 模式中,php-cgi 在此便退出了。
APACHE2HANDLER
PHP 作为 Apache 的模块,Apache 服务器在系统启动后,预先生成多个进程副本驻留在内存中,一旦有请求出现,就立即使用这些空余的子进程进行处理,这样就不存在生成子进程造成的延迟了。这些服务器副本在处理完一次 HTTP 请求之后并不立即退出,而是停留在计算机中等待下次请求。对于客户浏览器的请求反应更快,性能较高。
apache 模块的 DLL
该运行模式是我们以前在 windows 环境下使用 apache 服务器经常使用的,而在模块化(DLL)中,PHP 是与 Web 服务器一起启动并运行的。(是 apache 在 CGI 的基础上进行的一种扩展,可以加快 PHP 的运行效率)
ISAPI
ISAPI 即 Internet Server Application Program Interface,是微软提供的一套面向 Internet 服务的 API 接口。一个 ISAPI 的 DLL,可以在被用户请求激活后长驻内存,等待用户的另一个请求,还可以在一个 DLL 里设置多个用户请求处理函数,此外 ISAPI 的 DLL 应用程序和 WWW 服务器处于同一个进程中,效率要显著高于 CGI。
CLI
CLI(全称:command-line interface)命令行界面,是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。也有人称之为字符用户界面(CUI)。
PHP 的执行流程和 opcode
我们再来看看 PHP 代码执行所经过的流程。
图2:PHP 的执行流程
一段PHP代码会经过词法解析、语法解析等阶段,会被翻译成一个个指令(opcode),然后 zend 虚拟机会顺序执行这些指令。PHP 本身是用C语言实现的,因此最终调用的也是C语言的函数,实际上我们可以把 PHP 看做一个C语言开发的软件。
PHP 执行的核心就是翻译出来的一条一条指令,也就是 opcode,opcode 是 PHP 程序执行的最基本单位。
在计算机科学领域中,操作码(Operation Code)被用于描述机器语言指令中,指定要执行某种操作的那部分机器码,构成 opcode 的指令格式和规范由处理器的指令规范指定。
一个 opcode 由两个参数(op1,op2)、返回值和处理函数组成。PHP 程序最终被翻译为一组 opcode 处理函数的顺序执行。
下面列举了几个常见的处理函数:
- ZEND_ASSIGN_SPEC_CV_CV_HANDLER : 变量分配 (b);
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER:函数调用;
- ZEND_CONCAT_SPEC_CV_CV_HANDLER:字符串拼接 b;
- ZEND_ADD_SPEC_CV_CONST_HANDLER: 加法运算 $a+2;
- ZEND_IS_EQUAL_SPEC_CV_CONST:判断相等 $a==1;
- ZEND_IS_IDENTICAL_SPEC_CV_CONST:判断相等 $a===1。
HashTable
HashTable是Zend的核心数据结构,在PHP里面几乎并用来实现所有常见功能,我们知道的PHP数组即是其典型应用,此外在zend内部,如函数符号表、全局变量等也都是基于HashTable。
HashTable具有如下特点:
- 支持典型的key->value查询;
- 可以当做数组使用;
- 添加、删除节点是O(1)复杂度;
- key支持混合类型,同时存在关联数组合索引数组;
- Value支持混合类型:array(“string”,2332);
- 支持线性遍历,如 foreach。
Zval
由于PHP 是一门弱类型语言,本身不严格区分变量的类型。PHP 在声明变量的时候不需要指定类型。PHP 在程序运行期间可能进行变量类型的隐式转换。和其他强类型语言一样,程序中也可以进行显式的类型转换。Zval 是 Zend 中另一个非常重要的数据结构,用来标识并实现 PHP 变量。
Zval 主要由以下 3 部分组成。
- Type:指定了变量所述的类型(整数、字符串、数组等);
- refcount&is_ref:用来实现引用计数;
- value:是核心部分,存储了变量的实际数据。
Zval 用来保存一个变量的实际数据。因为要存储多种类型,所以 zval 是一个 union,也由此实现了弱类型。
引用计数在内存回收、字符串操作等地方使用得非常广泛。PHP 中的变量就是引用计数的典型应用。Zval 的引用计数通过成员变量 is_ref 和 ref_count 实现。通过引用计数,多个变量可以共享同一份数据,避免频繁复制带来的大量消耗。
在进行赋值操作时,Zend 将变量指向相同的 Zval,同时 ref_count++,在 unset 操作时,对应的 ref_count-1。只有 ref_count 为 0 时才会真正执行销毁操作。如果是引用赋值,Zend 就会修改 is_ref 为 1。
PHP 变量通过引用计数实现变量共享数据,当试图写入一个变量时,Zend 若发现该变量指向的 Zval 被多个变量共享,则为其复制一份 ref_count 为 1 的 Zval,并递减原 Zval 的 refcount,这个过程称为“Zval分离”。可见,只有在有写操作发生时,Zend 才进行复制操作,因此也叫 copy-on-write(写时复制)。
对于引用型变量,其要求和非引用型相反,引用赋值的变量间必须是捆绑的,修改一个变量就修改了所有捆绑变量。
静态网页与动态网页的区别
网页可分为静态网页与动态网页两种形式。在介绍这两种网页之前,我们先来了解一下网络构成中的服务器(Server)与客户机(Client)。
服务器是安装有服务器软件并且可以向客户机提供网页浏览、数据库查询等服务的设备。而客户机则与之相反,它通过客户端软件(如浏览器)从服务器上获得网页浏览、软件下载等服务。简单地讲服务器就是服务提供者,而客户机则是服务获得者。
静态网页
在网站设计中,静态网页是网站建设的基础,纯粹 HTML 格式的网页通常被称为“静态网页”,静态网页是标准的 HTML 文件,它的文件扩展名是 .htm、.html,可以包含文本、图像、声音、FLASH 动画、客户端脚本和 ActiveX 控件等。
静态网页是相对于动态网页而言,是指没有后台数据库、不含程序和不可交互的网页。静态网页相对更新起来比较麻烦,适用于一般更新较少的展示型网站。
容易误解的是,静态网页并不是静止不动的,它也可以出现各种动态的效果,如 GIF 动画、FLASH、滚动字幕等。
静态网页服务的实现首先需要客户机通过浏览器向服务器发出请求,然后服务器接受请求并根据请求从服务器端的网页中找到对应的页面,最后返回给客户机浏览器。这个过程中所发送的页面都是事先编辑好的,它并不能自动生成。
图1:静态网页的实现模式
静态网页有以下特点:
- 静态网页不能自动更新,若要对静态页面进行更新,就要重新编写 HTML 源文件,然后再上传。因此静态网页的制作和维护工作量相当大。
- 静态网页的内容不随浏览用户、浏览时间等条件的变化而变化。无论何人、何时、何地浏览网页,它的内容都是一成不变的(不包括使用 JavaScript 实现的一些简单特效)。
- 静态网页一经发布,无论浏览者浏览与否,它都是真实存在的一个文件,都对应一个 URL(文件在网上的地址)。
- 用静态网页实现人机交互有相当大的局限性。由于不能动态生成页面,所以用静态网页来实现人机交互是很困难的,在功能上有很大限制。
动态页面
动态网页是基本的 HTML 语法规范与 PHP、Java、Python 等程序语言、数据库等多种技术的融合,以期实现对网站内容和风格的高效、动态、交互式的管理。因此,可以理解为凡是结合了 HTML 以外的高级程序设计语言和数据库技术进行的网页编程技术生成的网页都是动态网页。
也就是说,动态网页相对于静态网页来说,页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。
动态网页与网页上的各种动画、滚动字幕等视觉上的动态效果没有直接关系,动态网页也可以是纯文字内容的,也可以包含各种动画的内容,这些只是网页具体内容的表现形式,无论网页是否具有动态效果,只要是采用了动态网站技术(如 PHP、JSP 等)生成的网页都可以称为动态网页。
与静态网页相比,动态网页有以下特点:
- 动态网页在服务器端运行,客户机上看到的只是它的返回结果,不可能看到它的源文件。而静态网页则只能通过服务器把网页文件原封不动地传给客户机,本身不进行任何处理。
- 不同的人、不同时间、不同地点浏览同一个动态网页,根据代码处理结果不同,会返回不同的内容。
- 动态网页只有经客户浏览时才会返回一个完整的网页,而其本身并不是一个独立存在于服务器的网页文件。
- 与静态网页相比,动态网页更容易实现人机交互。与数据库相联系,能实现更为强大的功能。
- 由动态网页构建的网站维护起来比由静态网页构建的网站容易,只需要更新调用的数据(如数据库内容)即可。
与静态网页的实现方法不同,动态网页服务的实现首先需要客户机向服务器发送请求,然后服务器根据用户请求把动态网页内部的代码先在服务器上进行相应的处理,最后服务器把生成的结果发送给客户机,如下图所示:
图2:动态网页的实现模式
动态网页与传统网页的区别
1) 更新和维护
静态网页内容一经发布到网站服务器上,无论是否有用户访问,这些网页内容都是保存在网站服务器上的。如果要修改网页的内容,就必须修改其源文件,然后重新上传到服务器上。静态网页没有数据库的支持,当网站信息量很大的时候网页的制作和维护都很困难。
动态网页可以根据不同的用户请求,时间或者环境的需求动态的生成不同的网页内容,并且动态网页一般以数据库技术为基础,可以大大降低网站维护的工作量。
2) 交互性
静态网页由于很多内容都是固定的,在功能方面有很大的限制,所以交互性较差。
动态网页则可以实现更多的功能,如用户的登录、注册、查询等。
3) 响应速度
静态网页内容相对固定,容易被搜索引擎检索,且不需要连接数据库,因此响应速度较快。
动态网页实际上并不是独立存在于服务器上的网页文件,只有当用户请求时服务器才返回一个完整的网页,其中涉及到数据的连接访问和查询等一系列过程,所以响应速度相对较慢。
搭建PHP开发环境
对于初学者,推荐在 Windows 操作系统下使用 XAMPP 一键安装 PHP 集成开发环境(Apache、PHP、MySQL),XAMPP 提供 PHP 7 的安装版本,读者只需要到官方网站 https://www.apachefriends.org/download.html 下载即可。下载界面如图所示。
下载后得到一个 EXE 文件,双击该文件安装。安装完成后,查看该集成环境安装目录,如图所示。
双击 manager-windows.exe 即可打开管理窗口,在 Manage Servers 选项卡查看 MySQL 及 Apache 运行状态,如图所示。
应用目录默认位于安装目录的 apache2/htdocs 目录下,在该目录下新建 test.php 并编辑其内容:
<?phpecho phpinfo();
在浏览器中访问 http://localhost/test.php,页面显示如图所示。
出现以上页面,则说明安装成功。
第一个PHP程序
通过前面对 PHP 的介绍,相信大家已经对 PHP 有了一定的了解,那么本节我们就带领大家实现一个简单 PHP 程序——在浏览器中输出“Hello World!”。
想要在页面输出“Hello World!”非常简单,仅需要几行代码就可以搞定,如下所示:
<?php echo "Hello World!";?>
上面代码中<?php
和?>
分别表示 PHP 文件的开始和结束标记,在这里结束标记?>
并不是必须的,可以省略。两个标记之间是我们所写的 PHP 代码,代码与开始/结束标记也可以在同一行,但必须以空格分开,如下所示:
<?php echo 'Hello World!'; ?>
其中,echo 是输出语句,用于输出一个字符串,也就是 echo 后面以" "
包裹的部分(这里使用' '
也是可以的)。末尾的英文状态的分号;
表示一条语句的结束。
PHP 源文件的格式为“.php”,理论上 PHP 的源文件可以放在任意目录下,但是为了方便运行我们还是尽量将它放置在服务器环境相应的目录下,比如下面列举的这些:
- XAMPP 集成环境:XAMPP 安装目录下的 htdocs 文件夹中;
- PHPStudy 集成环境:PHPStudy 安装目录下的 WWW 文件夹中。
提示:因开发环境的不同,PHP 源文件的存放目录略有不同,比较常见的就是 htdocs、WWW 这两个目录。
本教程中使用的就是 XAMPP 集成环境,所以首先需要在 htdocs 目录下创建一个 index.php 文件,index 在这里是首页的意思,PHP 程序默认会首先运行名为 index 的文件(如 index.php、index.html 等),当然这也不是绝对的,我们也可以通过修改配置文件的方式让 PHP 程序首先运行指定的文件,这些我们会在后面详细介绍。
图:新建一个index.php文件
创建好 index.php 文件后,将我们上面的代码复制到文件中并保存。
在开始运行之前,我们首先需要确认一下 XAMPP 的 apache 服务处于开启状态,如下图所示:
图:开启 apache 服务
然后就可以在浏览器中输入 localhost,或者点击上图红框中的 Admin 按钮就可以运行我们的 PHP 程序了,如下图所示:
图:运行第一个PHP程序
MySQL数据库简介
PHP 在开发 Web 站点或一些管理系统时,需要对大量的数据进行保存,虽然 XML 文件或者文本文件也可以作为数据的载体,但不易进行管理和对大量数据的存储,所以在项目开发时,数据库就显得非常重要。
PHP 可以连接的数据库种类较多,其中 MySQL 数据库与其兼容较好,在 PHP 数据库开发中被广泛地应用。
MySQL 是什么
MySQL 是一款安全、跨平台、高效的,并与 PHP、Java 等主流编程语言紧密结合的数据库系统。该数据库系统是由瑞典的 MySQL AB 公司开发、发布并支持,由 MySQL 的初始开发人员 David Axmark 和 Michael Monty Widenius 于 1995 年建立的。
MySQL 的象征符号是一只名为 Sakila 的海豚,代表着 MySQL 数据库的速度、能力、精确和优秀本质。
图:MySQL 图标
目前 MySQL 被广泛地应用在 Internet 上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,使得很多公司都采用 MySQL 数据库以降低成本。
MySQL 数据库可以称得上是目前运行速度最快的 SQL 语言数据库之一。除了具有许多其他数据库所不具备的功能外,MySQL 数据库还是一种完全免费的产品,用户可以直接通过网络下载 MySQL 数据库,而不必支付任何费用。
MySQL 特点
下面总结了一下 MySQL 具备的特点。
1) 功能强大
MySQL 中提供了多种数据库存储引擎,各引擎各有所长,适用于不同的应用场合,用户可以选择最合适的引擎以得到最高性能,可以处理每天访问量超过数亿的高强度的搜索 Web 站点。MySQL5 支持事务、视图、存储过程、触发器等。
2) 支持跨平台
MySQL 支持至少 20 种以上的开发平台,包括 Linux、Windows、FreeBSD 、IBMAIX、AIX、FreeBSD 等。这使得在任何平台下编写的程序都可以进行移植,而不需要对程序做任何的修改。
3) 运行速度快
高速是 MySQL 的显著特性。在 MySQL 中,使用了极快的 B 树磁盘表(MyISAM)和索引压缩;通过使用优化的单扫描多连接,能够极快地实现连接;SQL 函数使用高度优化的类库实现,运行速度极快。
4) 支持面向对象
PHP 支持混合编程方式。编程方式可分为纯粹面向对象、纯粹面向过程、面句对象与面向过程混合 3 种方式。
5) 安全性高
灵活和安全的权限与密码系统,允许基本主机的验证。连接到服务器时,所有的密码传输均采用加密形式,从而保证了密码的安全。
6) 成本低
MySQL 数据库是一种完全免费的产品,用户可以直接通过网络下载。
7) 支持各种开发语言
MySQL 为各种流行的程序设计语言提供支持,为它们提供了很多的 API 函数,包括 PHP、ASP.NET、Java、Eiffel、Python、Ruby、Tcl、C、C++、Perl 语言等。
8) 数据库存储容量大
MySQL 数据库的最大有效表尺寸通常是由操作系统对文件大小的限制决定的,而不是由 MySQL 内部限制决定的。InnoDB 存储引擎将 InnoDB 表保存在一个表空间内,该表空间可由数个文件创建,表空间的最大容量为 64TB,可以轻松处理拥有上千万条记录的大型数据库。
9) 支持强大的内置函数
PHP 中提供了大量内置函数,几乎涵盖了 Web 应用开发中的所有功能。它内置了数据库连接、文件上传等功能,MySQL 支持大量的扩展库,如 MySQLi 等,可以为快速开发 Web 应用提供便利。
数据库的应用
数据库是计算机应用系统中的一种专门管理数据资源的系统。数据有多种形式,如文字、数码、符号、图形、图像及声音等,数据是所有计算机系统所要处理的对象。我们所熟知的一种处理办法是制作文件,即将处理过程编成程序文件,将所涉及的数据按程序要求组成数据文件,再用程序来调用,数据文件与程序文件保持着一定的关系。
在计算机应用迅速发展的情况下,这种文件式管理方法便显出它的不足。比如,它使得数据通用性差、不便于移植、在不同文件中存储大量重复信息、浪费存储空间、更新不便等。
而数据库系统便能解决上述问题。数据库系统不从具体的应用程序出发,而是立足于数据本身的管理,它将所有数据保存在数据库中,进行科学的组织,并借助于数据库管理系统,以它为中介,与各种应用程序或应用系统接口,使之能方便地使用数据库中的数据。
其实简单地说,数据库就是一组经过计算机整理后的数据,存储在一个或多个文件中,而管理这个数据库的软件就称为数据库管理系统。一般一个数据库系统(Database System)
可以分为数据库(Database)与数据管理系统(Database Management System,DBMS)两个部分。主流的数据库软件有 Oracle、Informix、Sybase、SQL Server、PostgreSQL、MySQL、Access、FoxPro 和 Teradata 等等。
数据库在 Web 开发中的重要地位
归根结底,动态网站都是对数据进行操作,我们平时浏览网页时,会发现网页的内容会经常变化,而页面的主体结构框架没变,新闻就是一个典型。这是因为我们将新闻存储在了数据库中,用户在浏览时,程序就会根据用户所请求的新闻编号,将对应的新闻从数据库中读取出来,然后再以特定的格式响应给用户。
Web 系统的开发基本上是离不开数据库的,因为任何东西都要存放在数据库中。所谓的动态网站就是基于数据库开发的系统,最重要的就是数据管理,或者说我们在开发时都是在围绕数据库在写程序。所以作为一个 Web 程序员,只有先掌握一门数据库,才可能去进行软件开发。
下图展示了项目中一个模块的开发流程:将网站的内容存储在 MySQL 数据库中;然后使用 PHP 通过 SQL 查询获取这些内容并以 HTML 格式输出到浏览器中显示。或者将用户在表单中输出的数据,通过在 PHP 程序中执行 SQL 查询,将数据保存在 MySQL 数据库中。也可以在 PHP 脚本中接受用户在网页上的其他相关操作,再通过 SQL 查询对数据库中存储的网站内容进行管理。
图:基于数据库的 Web 系统
PHP 几乎可以使用现有的所有的数据库,MySQL 与其他的大型数据库例如 Oracle、DB2、SQL Server 等相比,自有它的不足之处,比如规模小、功能有限(MySQL Cluster 的功能和效率都相对比较差)等,但这也丝毫没有减少它受欢迎的程度。 对于一般的个人使用者或者中小型企业来说,MySQL 提供的功能已经绰绰有余,而且由于 MySQL 是开放源码软件,因此可以大大降低总体拥有成本。
目前 Internet 上流行的网站构架方式分别是 LAMP(Linux + Apache + MySQL + PHP/Perl/Python)和 LNMP(Linux + Nginx + MySQL + PHP/Perl/Python),也就是使用 Linux 作为操作系统,Apache 和 Nginx 作为 Web 服务器,MySQL 作为数据库,PHP 作为服务器端脚本解释器。由于这四个软件都是免费或开放源码软件,因此使用这种方式不用花一分钱(除开人工成本外)就可以建立起一个稳定、免费的网站系统。
PHP 和 MySQL 的合作方式
在同一个 MySQL 数据库服务器中可以创建多个数据库,如果把每个数据库看成是一个“仓库”,那么网站中的内容数据就存储在这个仓库中。而对数据库中数据的存取及维护等,都是通过数据库管理系统软件进行管理的。
同一个数据库管理系统可以为不同的网站分别建立数据库,但为了使网站中的数据便于维护、备份及移植,最好为一个网站创建一个数据库(在大数据量时则采用分库分表)。数据库和数据库管理系统,以及 PHP 应用程序之间的关系如下图所示。
图:PHP 程序与数据库之间的关系
PHP连接数据库
使用 PHP 操作 MySQL 数据库是进行 Web 开发的必然要求之一,PHP 中提供了完整的操作 MySQL 数据库的函数,这些函数包括了从连接数据库、执行 SQL 语句、处理数据结果集到关闭数据库的方方面面。通过这些函数,使基于 MySQL 数据库的 Web 开发高效而简单。通常 PHP 访问 MySQL 数据库的步骤如下图所示。
图:PHP 访问数据库的步骤
在此之前,我们需要确保开启了 PHP 中的 mysqli 扩展。以 Windows 系统为例,开启 mysqli 扩展就是将 php.ini 配置文件中extension=mysqli
(php7)或extension=php_mysqli.dll
(php5)一项的注释去掉即可。
注意:在学习 PHP 操作 MySQL 数据库的过程中,会涉及到一些 MySQL 的相关知识,不了解的同学可以阅读本站的《MySQL教程》。
开启成功后可以使用 phpinfo() 函数查看,示例代码如下:
<?php phpinfo();?>
在输出的界面中搜索 mysqli,出现如下界面则表示开启成功。
图:使用 phpinfo() 函数查看是否开启成功
连接 MySQL 数据库
前面我们成功开启了 PHP 中的 mysqli 扩展,使用扩展中的 mysqli_connect() 函数就可以实现 MySQL 数据库的连接,函数语法格式如下:
mysqli_connect(
[string $host = ini_get(“mysqli.default_host”)
[, string $username = ini_get(“mysqli.default_user”)
[, string $password = ini_get(“mysqli.default_pw”)
[, string $dbname = “”
[, int $port = ini_get(“mysqli.default_port”)
[, string $socket = ini_get(“mysqli.default_socket”)
]]]]]] )
参数说明如下:
- $host:可选参数,要连接的服务器。可以是主机名或者是 IP 地址;
- $username:可选参数,登录所使用的 MySQL 用户名;
- $password:可选参数,登录所用的密码;
- $dbname:可选参数,执行查询时使用的默认数据库;
- $port:可选参数,指定连接到 MySQL 服务器的端口号;
- $socket:可选参数,指定 socket 或要使用的已命名 pipe,这个参数在开发中很少用到。
另外需要注意的是,mysqli_connect() 函数是 mysqli::__construct() 函数的别名,所有使用对象 mysqli() 也可以实现连接数据库。
【示例】下面通过一个简单的代码实现连接数据库。
1) 面向过程风格的写法
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$port = '3306';
$link = @mysqli_connect($host,$username,$password,$dbname,$port); // 连接到数据库
if($link){
mysqli_set_charset($link,'UTF-8'); // 设置数据库字符集
$sql = 'select * from user'; // SQL 语句
$result = mysqli_query($link, $sql); // 执行 SQL 语句,并返回结果
$data = mysqli_fetch_all($result); // 从结果集中获取所有数据
mysqli_close($link);
}else{
die('数据库连接失败!');
}
echo '<pre>';
print_r($data);
?>
2) 面向对象风格的写法
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$mysql = new Mysqli($host, $username, $password, $dbname);
if($mysql -> connect_errno){
die('数据库连接失败:'.$mysql->connect_errno);
}else{
$mysql -> set_charset('UTF-8'); // 设置数据库字符集
$sql = 'select * from user'; // SQL 语句
$result = $mysql -> query($sql);
$data = $result -> fetch_all();
$mysql -> close();
}
echo '<pre>';
print_r($data);
?>
运行结果如下:
Array
(
[0] => Array
(
[0] => 1
[1] => 张三
)
)
PHP mysqli_select_db():选择数据库
通过前面《mysqli_connect() 函数》的介绍我们知道,对应数据库名称的参数是可以省略的,如果省略该参数的话,就需要我们在后面来指定一个默认的数据库。PHP 中可以使用 mysqli_select_db() 函数来指定一个默认数据库,它和 MySQL 命令中的use dbname
的功能相似,函数的语法格式如下:
面向对象风格的写法:
mysqli::select_db(string $dbname)
其中,$dbname 为指定的数据库名称
面向过程风格的写法:
mysqli_select_db(mysqli $link, string $dbname)
其中,dbname 为指定的数据库名称。
函数执行成功会返回 TRUE,执行失败则返回 FALSE。
【示例】使用 mysqli_select_db() 函数选择默认数据库
1) 面向对象风格的写法:
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$mysql = new Mysqli($host, $username, $password);
if($mysql -> connect_errno){
die('数据库连接失败:'.$mysql->connect_errno);
}else{
$mysql -> select_db($dbname); // 选择名为 test 的数据库
$sql = 'select name,sex,age from user'; // SQL 语句
$result = $mysql -> query($sql); // 执行上面的 SQL 语句
$data = $result -> fetch_all();
$mysql -> close();
}
echo '<pre>';
print_r($data);
?>
2) 面向过程风格的写法:
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$link = @mysqli_connect($host, $username, $password);
if($link){
mysqli_select_db($link, $dbname); // 选择名为 test 的数据库
$sql = 'select name,sex,age from user'; // SQL 语句
$result = mysqli_query($link, $sql); // 执行 SQL 语句,并返回结果
$data = mysqli_fetch_all($result); // 从结果集中获取所有数据
mysqli_close($link);
}else{
echo '数据库连接失败!';
}
echo '<pre>';
print_r($data);
?>
运行结果如下:
Array
(
[0] => Array
(
[0] => 张三
[1] => 男
[2] => 12
)
[1] => Array
(
[0] => 李四
[1] => 男
[2] => 11
)
[2] => Array
(
[0] => 王五
[1] => 男
[2] => 13
)
[3] => Array
(
[0] => 小明
[1] => 女
[2] => 12
)
)
通常我们可以将数据库连接和选择默认数据库的过程写在一个单独的 PHP 脚本文件中。在其他需要对数据库操作的 PHP 脚本中,只要使用 require() 或 include() 等函数将该文件包含进来即可,不需要再重复编写连接数据库的代码了。
这样做不仅可以提高开发效率,更重要的是当数据库的用户名和密码需要变化时,只需要更改这一个文件即可,所有使用该文件的 PHP 脚本都是使用新用户与数据库服务器建立的连接。
PHP mysqli_query():执行SQL语句
成功选择好 MySQL 数据库后,接下来就可以对所选数据库中的数据表进行查询、更改以及删除等操作,PHP 中我们使用 mysqli_query() 函数就可以实现上述的所有操作,函数的语法格式如下:
面向对象风格的写法:
mysqli::query( string $query [, int $resultmode = MYSQLI_STORE_RESULT ] )
参数说明:
- $query:要执行的 SQL 语句;
- $resultmode:可选参数,用来修改函数的行为。可以是下列值的任意一个:
- MYSQLI_USE_RESULT(如果需要查询大量数据,使用这个);
- MYSQLI_STORE_RESULT(默认值)。
面向过程风格的写法:
mysqli_query( mysqli $link , string $query [, int $resultmode = MYSQLI_STORE_RESULT ] )
参数说明:
- $link:表示由 mysqli_connect() 函数返回的数据库连接;
- $query:要执行的 SQL 语句;
- $resultmode:可选参数,用来修改函数的行为。可以是下列值的任意一个:
- MYSQLI_USE_RESULT(如果需要查询大量数据,使用这个);
- MYSQLI_STORE_RESULT(默认值)。
提示:函数执行失败时会返回 FALSE;而通过 mysqli_query() 成功执行 SELECT、SHOW、DESCRIBE 或 EXPLAIN 查询时则会返回一个 mysqli_result 对象;其他查询执行成功则返回 TRUE。
演示之前我们先在数据表中添加一些数据,如下所示:
mysql> select * from user;
±—±-------±-----±-----+
| id | name | age | sex |
±—±-------±-----±-----+
| 1 | 张三 | 12 | 男 |
| 2 | 李四 | 11 | 男 |
| 3 | 王五 | 13 | 男 |
| 4 | 小明 | 12 | 女 |
±—±-------±-----±-----+
4 rows in set (0.00 sec)
【示例】使用 mysqli_query() 函数执行指定的 SQL 语句。
1) 面向对象风格的写法
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$mysql = new Mysqli($host, $username, $password, $dbname);
if($mysql -> connect_errno){
die('数据库连接失败:'.$mysql->connect_errno);
}else{
$mysql -> set_charset('UTF-8'); // 设置数据库字符集
$sql = 'select name,sex,age from user'; // SQL 语句
$result = $mysql -> query($sql); // 执行上面的 SQL 语句
$data = $result -> fetch_all();
$mysql -> close();
}
echo '<pre>';
print_r($data);
?>
2) 面向过程风格的写法
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$link = @mysqli_connect($host, $username, $password, $dbname);
if($link){
$sql = 'select name,sex,age from user'; // SQL 语句
$result = mysqli_query($link, $sql); // 执行 SQL 语句,并返回结果
$data = mysqli_fetch_all($result); // 从结果集中获取所有数据
mysqli_close($link);
}else{
echo '数据库连接失败!';
}
echo '<pre>';
print_r($data);
?>
运行结果如下:
Array
(
[0] => Array
(
[0] => 张三
[1] => 男
[2] => 12
)
[1] => Array
(
[0] => 李四
[1] => 男
[2] => 11
)
[2] => Array
(
[0] => 王五
[1] => 男
[2] => 13
)
[3] => Array
(
[0] => 小明
[1] => 女
[2] => 12
)
)
PHP获取SQL的查询结果
前面我们介绍了如何执行一条 SQL 语句,也就是调用《mysqli_query() 函数》。当我们执行一条 SELECT 命令的 SQL 语句时,mysqli_query() 函数会返回一个 PHP 资源的引用指针(结果集),也就是这条 SQL 语句的查询结果。通常我们需要对这一结果集进行处理才能得到我们想要的信息。
在 PHP 中处理数据结果集的函数主要有以下几个:
- mysqli_fetch_row():从结果集中取得一行,并以索引数组的形式返回;
- mysqli_fetch_assoc():从结果集中取得一行,并以关联数组的形式返回;
- mysqli_fetch_array():从结果集中取得一行,并以关联数组、索引数组或二者兼有的形式返回;
- mysqli_fetch_all():从结果集中取得所有行,并以关联数组、索引数组或二者兼有的形式返回;
- mysqli_fetch_object():从结果集中取得一行,并以对象的形式返回。
1、mysqli_fetch_row() 函数
mysqli_fetch_row() 函数可以从结果集中取得一行,并以索引数组的形式返回,其语法格式如下:
面向对象风格的写法
mysqli_result::fetch_row()
其中 mysqli_result 为使用 mysqli_query() 函数获取的结果集。
面向过程风格的写法
mysqli_fetch_row(mysqli_result $result)
其中 $result 为使用 mysqli_query() 函数获取的结果集。
【示例】使用 mysqli_fetch_row() 函数获取结果集中的一条数据。
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$mysql = new Mysqli($host, $username, $password, $dbname);
if($mysql -> connect_errno){
die('数据库连接失败:'.$mysql->connect_errno);
}else{
$sql = 'select name,sex,age from user'; // SQL 语句
$result = $mysql -> query($sql); // 执行上面的 SQL 语句
$data = $result -> fetch_row();
$mysql -> close();
}
echo '<pre>';
print_r($data);
?>
运行结果如下:
Array
(
[0] => 张三
[1] => 男
[2] => 12
)
2、mysqli_fetch_assoc() 函数
mysqli_fetch_assoc() 函数可以从结果集中取得一行,并以关联数组的形式返回,其语法格式如下:
面向对象风格的写法
mysqli_result::fetch_assoc()
其中 mysqli_result 为使用 mysqli_query() 函数获取的结果集。
面向过程风格的写法
mysqli_fetch_assoc(mysqli_result $result)
其中 $result 为使用 mysqli_query() 函数获取的结果集。
【示例】使用 mysqli_fetch_assoc() 函数获取结果集中的一条数据。
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$link = @mysqli_connect($host, $username, $password, $dbname);
if($link){
$sql = 'select name,sex,age from user'; // SQL 语句
$result = mysqli_query($link, $sql); // 执行 SQL 语句,并返回结果
$data = mysqli_fetch_assoc($result); // 从结果集中获取一条数据
mysqli_close($link);
}else{
echo '数据库连接失败!';
}
echo '<pre>';
print_r($data);
?>
运行结果如下:
Array
(
[name] => 张三
[sex] => 男
[age] => 12
)
3、mysqli_fetch_array() 函数
mysqli_fetch_array() 函数可以从结果集中取得一行,并根据参数以关联数组、索引数组或二者兼有的形式返回,函数的语法格式如下:
面向对象风格的写法
mysqli_result::fetch_array([int $resulttype = MYSQLI_BOTH])
其中 mysqli_result 为使用 mysqli_query() 函数获取的结果集;$resulttype 为可选参数,它是一个常量,用来设定返回值的类型,它的取值可以是 MYSQLI_ASSOC、MYSQLI_NUM 或 MYSQLI_BOTH。
面向过程风格的写法
mysqli_fetch_array(mysqli_result $result[, int $resulttype = MYSQLI_BOTH])
其中 resulttype 为可选参数,它是一个常量,用来设定返回值的类型,它的取值可以是 MYSQLI_ASSOC、MYSQLI_NUM 或 MYSQLI_BOTH。
【示例】使用 mysqli_fetch_array() 函数获取结果集中的数据。
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$link = @mysqli_connect($host, $username, $password, $dbname);
if($link){
$sql = 'select name,sex,age from user'; // SQL 语句
$result = mysqli_query($link, $sql); // 执行 SQL 语句,并返回结果
$data = mysqli_fetch_array($result, MYSQLI_ASSOC);// 从结果集中获取所有数据
mysqli_close($link);
}else{
echo '数据库连接失败!';
}
echo '<pre>';
print_r($data);
?>
运行结果如下:
Array
(
[name] => 张三
[sex] => 男
[age] => 12
)
4、mysqli_fetch_all() 函数
mysqli_fetch_all() 函数可以获取结果集中的所有数据,并根据参数以关联数组、索引数组或二者兼有的形式返回,函数的语法格式如下:
面向对象风格的写法
mysqli_result::fetch_all([int $resulttype = MYSQLI_NUM])
其中 mysqli_result 为使用 mysqli_query() 函数获取的结果集;$resulttype 为可选参数,它是一个常量,用来设定返回值的类型,它的取值可以是 MYSQLI_ASSOC、MYSQLI_NUM 或 MYSQLI_BOTH。
面向过程风格的写法
mysqli_fetch_all(mysqli_result $result [, int $resulttype = MYSQLI_NUM])
其中 resulttype 为可选参数,它是一个常量,用来设定返回值的类型,它的取值可以是 MYSQLI_ASSOC、MYSQLI_NUM 或 MYSQLI_BOTH。
【示例】使用 mysqli_fetch_all() 函数获取结果集中的所有数据。
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$mysql = new Mysqli($host, $username, $password, $dbname);
if($mysql -> connect_errno){
die('数据库连接失败:'.$mysql->connect_errno);
}else{
$sql = 'select name,sex,age from user'; // SQL 语句
$result = $mysql -> query($sql); // 执行上面的 SQL 语句
$data = $result -> fetch_all(MYSQLI_ASSOC);
$mysql -> close();
}
echo '<pre>';
print_r($data);
?>
运行结果如下:
Array
(
[0] => Array
(
[name] => 张三
[sex] => 男
[age] => 12
)
[1] => Array
(
[name] => 李四
[sex] => 男
[age] => 11
)
[2] => Array
(
[name] => 王五
[sex] => 男
[age] => 13
)
[3] => Array
(
[name] => 小明
[sex] => 女
[age] => 12
)
)
5、mysqli_fetch_object() 函数
mysqli_fetch_object() 函数可以从结果集中取得一行,并以对象的形式返回。函数的语法格式如下:
面向对象风格的写法
mysqli_result::fetch_object([string $class_name = “stdClass”[, array $params]])
其中 mysqli_result 为使用 mysqli_query() 函数获取的结果集;params 为可选参数,用来规定一个传给 $classname 的构造函数的可选参数数组。
面向过程风格的写法
mysqli_fetch_object(mysqli_result $result[, string $class_name = “stdClass”[, array $params]])
其中 class_name 为可选参数,用来规定实例化的类名称,设置属性并返回;$params 为可选参数,用来规定一个传给 $classname 的构造函数的可选参数数组。
【示例】使用 mysqli_fetch_object() 函数返回结果集中的当前行,并输出每个字段的值。
<?php
$host = 'localhost';
$username = 'root';
$password = 'root';
$dbname = 'test';
$mysql = new Mysqli($host, $username, $password, $dbname);
if($mysql -> connect_errno){
die('数据库连接失败:'.$mysql->connect_errno);
}else{
$sql = 'select name,sex,age from user'; // SQL 语句
$result = $mysql -> query($sql); // 执行上面的 SQL 语句
if($result){
while($obj = $result -> fetch_object()){
printf('姓名:%s,性别:%s,年龄:%s <br>', $obj->name,$obj->sex,$obj->age);
}
}
$mysql -> close();
}
?>
运行结果如下:
姓名:张三,性别:男,年龄:12
姓名:李四,性别:男,年龄:11
姓名:王五,性别:男,年龄:13
姓名:小明,性别:女,年龄:12
Apache教程
Apache HTTP Server(简称Apache)是一款非常有名的应用软件。它是世界上使用最广泛的Web服务器应用程序,在商业Web服务器市场中占有超过50%的份额。 Apache是类Unix操作系统中使用最广泛的Web服务器应用程序,但几乎可用于所有平台,如Windows,OS X,OS/2等。Aracle这个词取自Native的名称 美国部落’阿帕奇’,以其在战争和战略制定方面的技能而闻名。
Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩展,将Perl/Python等解释器编译到服务器中。
它是一个基于流程的模块化Web服务器应用程序,它通过每个同时连接创建一个新线程。 它支持许多功能; 其中许多模块都被编译为单独的模块并扩展其核心功能,并且可以提供从服务器端编程语言支持到身份验证机制的所有功能。虚拟主机就是这样一种功能,它允许单个Apache Web服务器为许多不同的网站提供服务。
Apache支持PHP程序
在Apache上运行Php文件需要在服务器上启用mod_php
。它允许Apache解析.Php
文件。mod_php
可以解释apache中的Php代码并将HTML发送到Web服务器。
如果在服务器上启用了mod_php
,则/etc/httpd/conf.d/
目录中将有一个名为php.conf
的文件。还可以查看:
httpd -M | grep "php5_module"
Shell
输出类似于以下结果:
Apache中的Php处理程序
Apache中的Php处理程序常用的有以下几种 -
- mod_php
- CGI
- FastCGI
- suPHP
mod_php 是最古老的PHP处理程序,它使PHP成为apache的一部分,并且不会调用任何外部PHP进程。默认情况下,此模块安装在每个Linux分发存储库中,因此启用/禁用此模块非常简单。
如果使用FastCGI作为PHP处理程序,则可以设置多个版本的PHP以供服务器上的不同帐户使用。
FastCGI即mod_fastcgi
是mod_fcgid
的扩展,其中mod_fcgid是CGI的高性能替代,即mod_cgi
。它启动足够数量的CGI实例来处理并发Web请求。它还使用suexec
来支持不同用户使用自己的PHP实例并提高Web安全性。