用PHP和MySQL构建一个数据库驱动的网站--------共8篇文章

 
1.准备工作
摘要

  在这篇文章中,我们会着手解决在构建一个
数据库 驱动的 网站 的过程中将会遇到的问题。而我们只会使用两个新的工具,PHP和MySQL。如果你的Web主机支持PHP/MySQL,那么你会省掉不少麻烦。如果不是这样,你也不用提心,我们也会学习如何在Unix和Windows下安装相应 程序
    对于今天的Web来说,内容是最重要的。当你熟练掌握了HTML,而且也学到了一些JavaScript和DHTML的小决窍后,你现在也许可能设计一个漂亮的能让人“一见钟情”的
网站 了。下一步的工作是向网页中添加一些真实的信息。许多站点不得不通过不断地更新来成功地吸引回头客。在传统的 网站 建设中,这意味着不断地更新众多的HTML文件。

  现在问题出来了,在更多的情况下,提供内容给站点的人并不是设计网页的人。内容的提供者甚至还不知道HTML。那么内容的提供者怎么把内容添加到
网站 中去呢?不是所有的公司都有一个全职的Webmaster的,而且,让一个Webmasters整天忙着将Word文件拷贝到HTML模板中也实在是一种浪费。

  要唯护一个文本驱动的站点实在是件很痛苦的事。许多站点(是不是也包括你的站点?)被过时的信息所困扰。因为要保证信息的正常更新,你将不得不重写数以百计的HTML文件。服务器端包含
技术 (SSI:HTML文件中,可以通过注释行调用的命令或指针)也许能稍微减轻一些麻烦。但是你还是得面对数以百计的HTML文件,即使你只是想对你的站点作一些基本的变动。

  解决这些头疼问题是设计一个
数据库 的站点。通过把你的站点的内容和设置完全分开,你可以对其中的一项进行处理,而不会对另一项发生影响。你将不再需要为每一条信息写一个HTML页面,你只需要为一类信息写一个HTML页面就足够了。你再也不需要不断地添加新的内容到你的页面中去了,你现在所要做的只是建立一个简单的信息管理 系统 ,通过这个 系统 ,作者可以不通过HTML就自行添加新的内容。

  在这篇文章中,我们会着手解决在构建一个
数据库 驱动的 网站 的过程中将会遇到的问题。而我们只会使用两个新的工具,PHP和MySQL。如果你的Web主机支持PHP/MySQL,那么你会省掉不少麻烦。如果不是这样,你也不用提心,我们也会学习如何在Unix和Windows下安装相应 程序

  这篇文章是提供给那些有可能学会服务器端
程序 开发的中高级的网页设计者的。我们会认为我们的读者熟悉HTML,所以我们在使用HTML时不会给出什么解释。另外,在有些地方我们可能还会用到少量的JavaScript,但是我们会尽量保证这即使对于未入门者也是足够简单的。

  在读完这篇文章后,你应该已经领会了如何构建一个
数据库 驱动的 网站 ,你也应该基本上学会了PHP和SQL。最重要的是,你会学到如何开始构建你自己的 数据库 驱动的 网站

第一章:安装

前言
  首先,感谢你阅读这个
教程 !在下面的几个月里,我会带着你实现从客户端设计的HTML和JavaScript的世界中的超越。目前文本驱动的 网站 是如此的成功,而我们在这里所要学的是如果解决维护这个难题。

  在我们开始前,我们有必要先了解一下我们的工作所需要的两个工具。在第一章内,我们会学习下载并安装我们将会用到的两个软件包:PHP和MySQL。

  PHP是一个服务器端的
脚本 语言。你可以将其理解成“插件”,通过这个“插件”,你的Web服务器可以在接到浏览器的请求后不再仅仅发出一个文本的Web页面。安装了PHP后,你的Web服务器可以阅读一种新的类型的文件(PHP 脚本 ),通过这种文件,服务器可以在响应浏览器的请求之前从 数据库 中读取实时的信息并将其加入到Web页面中去。PHP是完全免费的,你可以自由地下载和使用。

  要从一个
数据库 中获取信息,你首先需要拥有一个 数据库 ,这时我们就得提到MySQL了。MySQL是一个关系型 数据库 管理 系统 (RDBMS)。它到底扮演了一个什么样的角色以及它是如果工作的,我们将在下面进行具体地讲解。基本上,它是一个软件包,这个软件包可以很好地组织和管理大量的数据。MySQL也使得我们可以很容易地通过象PHP这样的服务器端 脚本 语言来获取信息。MySQL的for Unix-based平台(例如Linux)的非商业应用是免费的。

  如果你足够幸运的话,你的Web主机可能已经为你安装了MySQL和PHP。如果是这种情况,有一些章节对你来说就没有作用了,你可以直接跳到如果你的Web主机提供PHP和MySQL。

  我们在本
教程 中所讨论的大多数内容都适用于Windows-based或者Unix-based的服务器。但是根据你使用的服务器类型的不同,安装过程会不一样下一节讲解如何在Windows-based的Web 服务器上安装。再下面的一节讲解如何在Linux(以及其他Unix-based的平台)下安装。如果你不是特别对安装过程感兴趣,你只需要选择阅读适合你的那一节。

在Windows下的安装

  你可以到http://www.mysql.com/(或者在http://www.mysql.com/mirrors.html列出的镜像站点之一)并选择Downloads for Windows MySQL related software->Downloads->Register and download shareware version of MySQL-Win32,下载完文件后,将其解压并运行其中的setup.exe。

  当你安装好之后,MySQL已经可以使用了(不包括我们不久将要执行的一些配置)。象你的Web服务一样,MySQL也是一个可以在后台运行的服务,所以它可以在任何时候响应对信息的请求。这个服务
程序 ,你可以在你安装MySQL目录下的bin子目录下找到。如果你使用的是一个共享的版本,这个服务被称之为mysqld-shareware.exe。在执行前,将其改名为 mysqld.exe。在MS-DOS提示符下,通过如下命令开启这个服务:

C:mysql> mysqld


  要确保在Windows启动时就开启这个服务,你需要建立一个快捷方式,并将其加入到启动
程序 组中。此外,你还可以通过这个命令作为Windows NT/2000的一个服务安装:

C:mysql> mysqld-nt --install


  如果你在Windows NT/2000下运行共享版本有问题,你可以试试用单机模式运行这个服务:

C:mysql> mysqld --standalone


  下一步是安装PHP。在写这本
教程 的时候,PHP 4.0已经基本上成熟了。我自己就试过PHP 4.0-RC2,并没有遇到任何问题。估计最终的稳定版很快将会发布(可能到时候我们这个 教程 还没写完),我建议你安装最新的版本,这样当正式版出来时你将不需要做任何变动。

  PHP可以从http://www.
php .net/ (或者在http://www. php .net/mirrors. php 列出的镜像站点之一)免费地下载。你需要“binaries for Win32”软件包。你可以从以下地址获得一个很好的PHP 3.0 for Windows的安装指南:http://www.umesd.k12.or.us/ php /win32install.html。 当PHP 4.0发布最终版时,你可能需要升级,但是4.0的安装基本上与3.0一样。你不会因为所选择的版本不同而遇到什么麻烦。

  MySQL和PHP安装好之后,你可以进入安装配置了。

在Linux下的安装

  这一节所讲述的是在RedHat Linux下安装PHP和MySQL的过程。如果你使用的是Linux的不同版本,或者是使用的是其它Unix-based的操作
系统 ,这些步骤也是非常相似的,即使不是完全相同的。

  作为RedHat Linux的用户,你可能会对下载和安装PHP和MySQL的RPM发布感兴趣。RPM的确是优秀的,预打包的软件的安装非常容易。不幸的是,它们也会限制你选择怎么配置软件。因为这个原因,我认为使用PHP和MySQL的RPM版本所带来的麻烦要比其实际价值来得更多。

  因为有些RedHat Linux的默认配置会自动替你安装PHP,所以第一步就是从你的
系统 删除旧版本的PHP和MySQL。你需要以超级用户的身份登录来执行下面的命令。注意在下面的命令中,“%”表示shell的提示符,是不需要你输入的。


% rpm -e mysql
% rpm -e
php



  如果这两个命令或其中一个显示 程序 没安装,不要担心。如果第二个命令成功执行(也就是说,不显示任何信息),那就证明的确安装了老版本的PHP,你必须完全删除它。用你所习惯的文本编辑器打开Apache的配置文件(通常是/etc/httpd/conf/httpd.conf),寻找下面的这两行内容。这两行通常是分在文件的不同地方,所以如果这两行不在一起,那实在没什么好担心的。


LoadModule
php 3_module modules/lib php 3.so
AddModule mod_
php 3.c



  这两行是用来告诉Apache将PHP作为plug-in模块装入的。当你卸载了这个模块,你还需要删除这两行以保证Apache正常工作。你也可以在这两行的开头加(#)使其成为注释。

  为了确保Apache还在正常工作,你现在必须在没有PHP插件的情况下重启它:


% /etc/rc.d/init.d/httpd stop
% /etc/rc.d/init.d/httpd start



  一切安排妥当后,你可以准备下载安装MySQL和PHP了。

在Linux下安装MySQL

  MySQL for Linux的版本是免费的,你可以从http://www.mysql.com/(或http://www.mysql.com/downloads/mirrors.html中列出的镜像站点之一)下载最后的稳定版(列在下载页的“recommended”中)。你应该获取“tarball source download”的版本,其文件名是mysql-version.tar.gz。

  下载完文件后,你必须确保以超级用户的身份登录进行安装,除非你只想在你自己的home目录下安装MySQL。开始解开下载的文件并进入刚建立的目录中:


% tar xfz mysql-version.tar.gz
% cd mysql-version



  下面你需要配置MySQL的安装。除非你有绝对的把握,否则你需要指定安装的目录。我推荐使用 /usr/local/mysql:

% ./configure --prefix=/usr/local/mysql


  在对显示器和显示器配置进行过检测之后,你最终将返回到命令提示符下。现在你可以编译MySQL了:

% make


  在编译后,你会重新返回到命令提示符下。现在你可以安装你新编译的
程序 了:

% make install


  现在MySQL已经安装好了,但是在使用前,你还得安装它的
数据库 文件。在你的开始安装的目录下,输入下面命令:

% scripts/mysql_install_db


  一切都做好后,你可以删除你正在其中工作的目录了,在这个目录中仅仅包括了源
程序 和安装的临时文件。如果你可能还需要重新安装,你只需要重新解开mysql-version.tar.gz 文件。

  当MySQL安装完成并且可以存储数据后,剩下的工作就是在你的计算机中运行这个服务了。你可以用超级用户或者你自己的用户(如果你是将这个服务安装在你自己的home目录下),但是,最好的方法是设置一个特殊的用户,这个用户只能启动MySQL服务。这会防止有人通过MySQL服务侵占你的
系统 。你可以使用以下命令建立一个特殊的MySQL用户:


% /usr/sbin/groupadd mysqlgrp
% /usr/sbin/useradd -g mysqlgrp mysqlusr


  
  在默认情况下,MySQL的所有
数据库 信息都存储在你安装的目录的var子目录下。我们想设置这个目录只有我们的新的MySQL用户能访问。下面的这个命令能完成这个工作(我假定你将MySQL安装到/usr/local/mysql目录):


% cd /usr/local/mysql
% chown -R mysqlusr.mysqlgrp var
% chmod -R go-rwx var



  现在一切都安排好了。在MySQL目录下,输入以下命令:

% bin/safe_mysqld --user=mysqlusr &


  现在MySQL服务已经被MySQL用户开启,除非你关闭你的计算机,这个服务将一直运行下去(就象Web和FTP服务一样)。要测试这个服务是不是正常运行,输入以下命令:

% bin/mysqladmin -u root status


  现在应该会显示MySQL服务的一些简单的统计信息。如果你看到的是一个错误信息,那就是出错了。你可以试一下重新安装。

  如果你想让你的MySQL服务在你的
系统 启动时自动运行(就象你的Web服务那样),你需要作相应设置。在MySQL目录的share/mysql子目录下,你会发现一个叫mysql.server的 脚本 ,将它添加到你的 系统 的启动事务中就行了。

  如果你已经设定了一个特殊的MySQL用户来启动MySQL服务,你需要编辑mysql.server
脚本 。用你熟悉的文本编辑器打开它并改变mysql_daemon_user设定,使其指向你上面创建的用户:

mysql_daemon_user=mysqlusr


  这篇文章是提供给那些有可能学会服务器端
程序 开发的中高级的网页设计者的。我们会认为我们的读者熟悉HTML,所以我们在使用HTML时不会给出什么解释。另外,在有些地方我们可能还会用到少量的JavaScript,但是我们会尽量保证这即使对于未入门者也是足够简单的。
----------------------------------------------------------------------------
2. 将这个
脚本 添加到启动事务中是个比较复杂的任务。如果你使用的不是RedHat Linux而且你没有把握做这件事,你最好请教一下了解的人。在RedHat Linux中,执行以下命令(在MySQL目录下)会完成这个工作:


% cp share/mysql/mysql.server /etc/rc.d/init.d/
% cd /etc/rc.d/init.d
% chmod 500 mysql.server
% cd /etc/rc.d/rc3.d
% ln -s ../init.d/mysql.server S99mysql
% cd /etc/rc.d/rc5.d
% ln -s ../init.d/mysql.server S99mysql



  现在一切都做好了!要测试这个工作,你可以重启你的
系统 并对这个服务作出请求,看看它是不是正常工作了。
在Linux下安装PHP

  正如我们前面提到的,PHP并不是一个独立运行的
程序 。它实际上是你的Web服务(可能是Apache)的一个插件。实际上你有三种方法在Apache中安装PHP插件:

  作为一个CGI
程序 ,Apache每次需要处理PHP页面时运行它。

  作为一个模块编译到Apache
程序 中。

  在Apache每次启动时作为一个模块载入。

  第一种方法的安装和配置最简单,但是这需要Apache每次接收到PHP页面的请求时就将PHP作为一个
程序 调用。这肯定会降低你的Web服务器的响应时间,特别是同时接收到不止一个的请求时更是这样。

  第二种方法和第三种方法在性能方面同样的优秀,但是很可能你已经安装好了Apache,你大概不想再去下载一次,并重新编译和重新安装。因此,我们使用第三种方法。

  首先,我们从http://www.
php .net/(或者在http://www. php .net/mirrors. php 中列出的镜像站点之一)下载PHP的软件包。当我们在写这个 教程 的时候,PHP 4.0已经基本上成熟了。我自己就试过PHP 4.0-RC2,并没有遇到任何问题。估计最终的稳定版很快将会发布(可能到时候我们这个 教程 还没写完),我建议你安装最新的版本,这样当正式版出来时你将不需要做任何变动。在这里,我们安装的是3.0,我会注意指出3.0和4.0在安装时可能会有的差别。

  你所下载的文件的文件名将是
php -version.tar.gz。我们的第一步是解开这个文件:


% tar xfz
php -version.tar.gz
% cd
php -version



  要将PHP作为Apache可载入的模块安装,你需要Apache的apxs
程序 。在个 程序 在绝大多数的Apache的版本中应该都已包括,但是如果你使用的是通过RedHat Linux安装的拷贝,你需要安装Apache高级RPM软件包来获得它。你可以从你的RedHat光盘上找到这个软件包,你也可以从http://www.redhat.com/下载。在默认的情况下,RedHat会将这个 程序 安装到/usr/sbin/apxs。如果你看到了这个文件,这证明它已经被安装了。

  在这个安装过程中,你必须以超级用户的身份登录,因为其中包括了一些对Apache配置文件的变动。

  下一步是配置PHP安装
程序 ,以使它知道选择哪些选项,并在哪儿寻找它所需要的 程序 (例如Apache和MySQL)。除非你很有把握,否则你只需输入下面的命令(在同一行中):

% ./configure --prefix=/usr/local/
php --with-config-file-path=/usr/local/ php --with-apxs=/usr/sbin/apxs --enable-track-vars --enable-magic-quotes --enable-debugger


  如果你已经安装了PHP 3.0(不是4.0或更迟的版本),你也需要通过以下附加的参数告诉它在你的
系统 中从哪儿寻找MySQL:

  --with-mysql=/usr/local/mysql/


  当经过几屏对显示器的测试后,你会回到命令提示符下。下面两个命令会编译和安装PHP:


% make
% make install



  PHP现在已经被安装在/usr/local/
php (除非你通过上面./configure的--prefix参数指定了不同的目录),你应该能在同一目录下(除非你通过上面./configure的--with-config-file-path参数指定了不同的目录)找到名为 php .ini的配置文件, PHP提供了一个 php .ini的模块文件,其文件名是 php .ini-optimized (在PHP3.0中是 php .ini-dist)。将这个文件拷贝到相应的目录:

% cp
php .ini-optimized /usr/local/ php / php .ini


  对于PHP 3.0:

% cp
php .ini-dist /usr/local/ php / php .ini


  你暂时不要担心
php .ini的优化调整。现在,我们需要确保Apache知道从哪儿找PHP,这样它才能在启动时装载它。使用你熟悉的文本编辑器打开你的Apache httpd.conf 配置文件(在RedHat Linux中,在/etc/httpd/conf/httpd.conf)。 寻找象下面这样的一行:

LoadModule
php 4_module lib/apache/lib php 4.so


  如果你安装的是PHP 3.0,这一行中的
php 4换成 php 3。 你所寻找的应该是一个新的未注释的行(不是以#开头的行),而不是你之前注释掉的那一行。一般情况下,它会和文件中其他LoadModule行显示在一起。当你找到它后,你需要改变路径以使它能够匹配文件中所有其他的LoadModule行。在RedHat Linux下,这意味着将这一行改变为:

LoadModule
php 4_module modules/lib php 4.so


  然后,寻找以DirectoryIndex开始的行。这一行告诉Apache对于一个给定的目录寻找默认页时所使用的文件名。通常,你会看到index.html和其他一些文件名,你需要将index.
php 和index. php 3添加到这一行:

DirectoryIndex index.html index.cgi ... index.
php index. php 3


  最后,到这个文件的最后并添加一个新行来告诉Apache哪些文件的扩展名被看成PHP文件:

AddType application/x-httpd-
php .phtml . php . php 3


  一切都做好后,保存改变并重启你的Apache服务。Apache启动时不应该有任何出错信息。

安装后的设置

  当PHP和MySQL都安装好之后,不管你是在Windows下、Linux下或其他操作
系统 下,第一件事都是为MySQL设置一个“root口令”。MySQL仅仅允许经授权的用户访问并操作它的 数据库 中所存储的信息,所以你必须让MySQL清楚谁是经授权的,谁是未经授权的。当MySQL第一次被安装时,它会生成一个叫“root”的用户,该用户可以不用口令访问所有的东西。你的第一个任务就是为root用户设置口令,这样才能保证不会任何人都可以搞乱你的 数据库

  你必须认识到MySQL的重要性,正如Web服务和FTP服务一样,在同一个
网络 上的任何机器都可以访问它。如果你在一个连接到Internet的计算机上工作,这就意味着这个世界上的任何人都可以试图连接你的MySQL服务器!你必须立即选择一个很难猜的口令!

  要设置MySQL中的root口令,在你安装MySQL的目录的bin子目录下输入下面的命令(包括引号):

mysqladmin -u root password "your new password"


  要确保MySQL接受这个改变,你必须告诉它重新载入经论证的用户和口令的列表:

mysqladmin -u root reload


  如果这个命令显示一个错误信息告诉你无法访问,不要担心,这仅仅证明口令已经生效了。

  要测试你的新密码,你可以请求MySQL服务器告诉你有关它的当前的状态:

mysqladmin -u root -p status


  当有提示时,输入密码。你会看到一些简单的信息,这些信息包含了服务的当前状态。-u root参数告诉
程序 你想要以“root”用户登入。-p参数告诉 程序 在连接之前提示你输入你的口令。status参数告诉 程序 你想要看看 系统 状态。

  如果你需要关闭MySQL服务器,你可以使用下面的命令。注意这里的-u root和-p参数的含义和上面提到的一样:

mysqladmin -u root -p shutdown


  现在你的MySQL
数据库 系统 已经 安全 运行了,现在剩下的工作就是配置PHP了。PHP是使用一个叫 php .ini的文本文件配置的。如果你是在Windows下安装PHP的,你应该已经拷贝了 php .ini到你的Windows目录。如果你是使用上面的说明在Linux安装PHP的,你应该已经拷贝了 php .ini到PHP安装目录下(/usr/local/ php )。

  用你熟悉的文本编辑器打开
php .ini 并大致浏览一下。绝大多数的设置已经被很好地说明,而且绝大多数的默认设置也可以适应你的要求。只要检查并确认你的配置与下面匹配:

magic_quotes_gpc = Ondoc_root = extension_dir =


  如果你运行的是PHP 4.0,你还需要检查下面这一行:

register_globals = On


  如果你是在Windows下运行PHP 3.0,去除开头的“;”来取消下面这一行的注释(4.0不需要):

extension=
php _mysql.dll


  保存
php .ini的变动,然后重启你的Web服务器。在Linux下,如果你是以超级用户登录的,你可以重启Apache:

/etc/rc.d/init.d/httpd restart


现在万事俱备!现在唯一剩下的就是测试并确认是不是一切OK了(参看你的第一个PHP
脚本 )。

如果你的Web主机提供PHP和MySQL

  如果为你提供Web空间的主机已经为你安装并设置了MySQL和PHP,你只希望学会如何使用它们,你需要做的事实在不多。现在你应该和你的主机提供商取得联系,以获取如何访问这些服务的信息。

  特别重要的,你需要获得为你设置的访问MySQL服务的用户名和口令。他们可能已经为你设置了一个空
数据库 (这会防止你和同一MySQL服务器上的其他用户在 数据库 上发生混乱),你这时还需要知道这个 数据库 的名字。

  有两个方法访问MySQL服务。第一种方法是使用telnet登入主机并使用安装MySQL客户端
程序 (mysql、mysqladmin、mysqldump等)来直接实现和MySQL服务实现互动。第二种方法是在你自己的计算机上安装那些客户端 程序 并连接上MySQL服务器。你的Web主机可能会支持其中的一种或两种方法,所以你得先问清楚。

  如果他们支持通过telnet登入进行你的工作,你还需要一个通过telnet登入的用户名和口令(这个用户名和口令可能和你访问MySQL服务的不一样)。你得把这两个设置信息都问清楚。

  如果他们支持远程访问MySQL服务,你需要下载一个
程序 去连接并实现与服务器的互动。这个 教程 会假设你已经从http://www.mysql.com/下载了一套MySQL客户端 程序 。这个软件包既可以在Window下运行,也可以在Unix下运行,而且是免费的。包含在软件包中的安装说明非常简单。如果你更喜欢一些图形化界面的,你可以下载类似MySQLWinAdmin for Windows(也可以从http://www.mysql.com/获得)。我推荐你首先学会使用基本的客户端 程序 ,尽管,在这些 程序 中使用的命令会与在PHP 脚本 中访问MySQL 数据库 脚本 很相像。

你的第一个PHP
脚本

  为你讲了那么多安装的事,却还一直没有让你尝试PHP驱动的Web页面的滋味,对我来说实在是不公平的,所以在这里为你安排了一道开胃的小菜。

  打开你所熟悉的文本或HTML编辑器并建立一个叫today.
php 的新文件。在文件中输入下面的内容:







Today's Date (according to this Web server) is






  将它保存下来并按通常你放置HTML文件的那样将其放置在你的Web站点上,现在你再通过你的浏览器看看这一页。

  很棒,不是吗?如果你通过你的浏览器显示源文件,你所看到将是规范的HTML文件。在发送到你的浏览器之前,PHP代码(上面的
程序 中所有在之间的代码)都已经被Web服务器解释并转换成通常的文本。PHP(以及其他服务器端的 脚本 语言)的一个优点就是 网站 浏览者不会知道 脚本 语言自身。

  不要太多地在意我在这个
程序 中使用的代码。不久你就会对它很熟悉了。

结语

  现在所有工作都如期做完了,你应该已经在你的Web服务器上安装好MySQL和PHP了。如果这个小例子不能正常工作(例如,它显示了未加处理的PHP源代码),那肯定是安装中出了什么问题。

  在下一章内,我们会学习关系型
数据库 的基本知识,并开始使用MySQL来工作。如果你之前没有接触过 数据库 ,我肯定你会大开眼界!
--------------------------------------------------------------------------------------
3. 在这一章,我们将集中学习如何使用结构化查询语言(SQL)在MySQL
数据库 中工作。
第二章: MySQL入门

  欢迎回到这个
教程 !在上一章,我们学习了安装和配置PHP和MySQL这两个软件。在这一章,我们将集中学习如果使用结构化查询语言(SQL)在MySQL 数据库 中工作。
上一章简要说明的那样,PHP是一个服务器端的
脚本 语言,通过这个语言你可以在你的Web页面中添加指令,这样你的Web服务软件(可能是Apache,Personal Web Server或其他任何软件)会在向发出请求的浏览器发送这些页面前首先执行它。在那个简单的例子中,我展示了如何每次在接受请求的Web页面中插入当前的日期。


  都很清楚了,但是如果在其中添加一个
数据库 会真正引起我们的兴趣。一个 数据库 服务器(我们这里是MySQL)是一个使用一定格式存储大量信息的 程序 ,通过这个 程序 你可以很简单地使用象PHP这样的 脚本 语言来访问数据。例如,你可以使用PHP在 数据库 中获得一个笑话的列表并将其显示到你的Web站点。


  子中,笑话被完全存储在
数据库 中。这样做有两个好处。首先,你不再需要为你的每个笑话写一个HTML文件,你只需要写一个PHP文件来从 数据库 中引出任何的笑话并显示它;其次,要添加笑话到你的Web站点中,也仅仅是添加笑话到 数据库 中。PHP代码在新笑话包含在列表中时可以自动显示新的笑话。


  们通过这个例子来看看数据是如何在
数据库 中存储的。一个 数据库 包含一个或几个数据表(table),每一个数据表包含了一个事物的列表。对于我们的笑话 数据库 来说,我们一开始可能需要一个名为“jokes”的数据表,这个数据表包含了一个笑话列表。 数据库 中每个数据表包含一个或几个数据列(column)或数据域(field)。回到我们的例子中来,我们的“jokes”数据表可能有这样的两列:笑话的正文以及笑话添加到 数据库 中的日期。每个存储在数据表中的笑话我们称之为一行。要了解这儿提到的所有术语,你可以看下面这张图:


  在笑话正文(“JokeText”)和添加日期(“JokeDate”)这两个数据列之外,我还增加了一个叫做“ID”的数据列。这个数据列的作用是给每个笑话分配一个唯一的号码,这样我们可以很容易地查阅并区分这些笑话。


  习一下,上面的数据表中有三个数据列、两行。每一行包含了一个笑话的ID、它的正文以及它的添加日期。掌握了这些基本术语后,我们将开始使用MySQL。


登录MySQL

  SQL
数据库 的标准界面是连接到MySQL服务软件(在第一章内安装)并同时输入命令。要连接上服务器,我们需要使用MySQL客户端 程序 。如果你自己安装了MySQL服务软件,不管你是在Windows下安装的,还是在一些Unix的版本下安装的,你应该已经在安装服务 程序 的同一地点安装了这个客户端 程序 。在Linux,这个 程序 被称之为mysql,其位置默认是/usr/local/mysql/bin 目录。在Windows下,这个 程序 被称之为mysql.exe,其位置默认是C:mysqlin目录。


  是自己安装的MySQL服务器(例如,你是在你的Web主机提供商的MySQL服务器上工作),那么有两个方法连接到MySQL服务器,第一个方法是使用telnet登录到你的Web主机的服务器上,然后在那儿运行mysql。第二种方法是从http://www.mysql.com/(for Windows和for Linux的都可以免费获得) 下载并安装MySQL客户端
程序 。这两种方法都可以很好地工作,你的Web主机可能支持其中的一种,或者两种都支持(你需要去问清楚)。


  择了哪种方法,不管你使用的是哪种
系统 ,你最终都应该在一个命令行执行MySQL客户端 程序 去连接你的MySQL服务器,你需要输入下面的命令:

mysql -h  -u  -p



  换成你的MySQL服务器正在其上运行的计算机的主机名或IP地址。如果你在运行服务的同一台计算机上运行客户端
程序 ,你可以不使用-h 而且直接使用-h localhost。应该是你的MySQL用户名。如果你是自己安装的MySQL服务器,这应该就是root。如果你是使用的你的Web主机提供商的MySQL服务,这应该是他们为你指定的MySQL用户。


  参数告诉
程序 提示你输入你的口令,这将在你输入上面的命令后立即显示。如果你是自己安装的MySQL,你的口令就是你在第一章内选择的root的口令。如果你是使用的你的Web主机提供商的MySQL服务,这应该是他们给你的MySQL口令。


  切都输入好了,MySQL客户端
程序 会连接上MySQL服务器并返回给你一个MySQL的命令行:

mysql>



  ySQL服务器实际上是连接了好几个
数据库 (这使得一个Web主机可以为几个用户设置同一个MySQL服务器)。所以你的下一步应该是选择一个工作的 数据库 。首先,获得当前服务器上的 数据库 列表。输入下面的命令(不要忘了分号!),然后打回车。

mysql> SHOW DATABASES;



  L会显示给你服务器上的
数据库 列表。如果这是一个新安装的服务器(也就是说,这是你在第一章里自己安装的)。这个列表将会是这样:


+----------+
| Database |
+----------+
| mysql |
| test |
+----------+
2 rows in set (0.11 sec)




  L服务器使用第一个被称之为mysql的
数据库 来管理用户及其口令和权限。现在我们暂时不会关心这个 数据库 ,在以后的章节中,我们会讨论它。第二个叫test是一个数据模块。你可以删除这个 数据库 ,在我们的 教程 中不会使用到它(我们会自己建立一些 数据库 )。删除什么东西在MySQL中被称之为“dropping”,要删除test 数据库 ,其正确的命令应该是:

mysql> DROP DATABASE test;



  入了这个命令,并打了回车,MySQL会删除这个
数据库 ,并返回Query OK。注意,并不会提示你诸如“这是否确定”这样的信息。所以你在MySQL输入命令必须十分小心。就象我们在这儿看到的,你可以完全删除 数据库 --包含它其中的所有信息--仅仅只用一个命令!


  入下一步之前,让我们先来看看MySQL命令行的连接。正如我们已经注意到的,在MySQL中的所有命令都必须以分号(;)结束。如果你忘记了这个分号,MySQL会认为你还没有结束输入你的命令,并会让你这下一行中继续录入:


mysql> SHOW
    -> DATABASES;




  L在等待你输入命令中的剩余部分时,提示符会从mysql>改变为->。对于一个长命令,这是很有用的,你可以将你的命令分几行输入。


  途发现你的命令出错了,你可以完全取消当前的命令(译者注:是指尚未执行的命令)并从头来过。要完成这个工作,你只需要输入c并按回车:

mysql> DROP DATABASEcmysql>



  L会完全忽略你刚才输入的命令,并返回到提示符等待你的下一个命令。


  你要退出MySQL客户端
程序 时,你只需要输入quit或者exit (这两个命令是完全一样的)。这是唯一不用以分号结尾就可以执行的命令。

mysql> quitBye



什么是SQL?

  程中我们用来告诉MySQL去做什么的命令其实是一个叫结构化查询语言(SQL)的规范的一部分。SQL中的命令也被称之为查询(在这篇
教程 中,我们会交替地采用这两种称呼)。


  实现与绝大多数的
数据库 的交互的标准语言,所以即使你将来不再使用MySQL,转而使用Microsoft SQL Server,你会发现绝大多数命令是相同的。你必须理解SQL和MySQL的区别。MySQL是你正在使用的 数据库 服务软件。SQL是你用来实现和 数据库 的交互的语言。


建立一个
数据库

  Web主机提供商已经为你分配了一个用来工作的 数据库 。你先耐心地等待一下,等一下我们会和你继续讨论下面的问题。如果你是在自己安装的MySQL服务器上工作。执行下面的命令,很容易地你就可以建立一个 数据库 了:

mysql> CREATE DATABASE jokes;



  库的名字是jokes,这是为了与我们工作的例子一致。其实你可以给你的
数据库 起任何你自己喜欢的名字。不过,如果你是在Web主机提供商的MySQL服务器上工作,它们可能已经为你建立了一个 数据库 ,你就没法选择 数据库 的名字了。


  已经有了一个
数据库 ,我们需要告诉MySQL我们想要使用这个 数据库 。下面这个命令应该也不太难记:

mysql> USE jokes;



  以开始使用你的
数据库 了。在你在其中添加数据表之前,这个 数据库 将是空的,我们的第一步工作应该是建立一个数据表来保存我们的笑话。


建立一个数据表

  遇到的SQL命令都是非常简单的,但是因为数据表是比较灵活的,相应地建立它们的命令就要复杂得多了。建立数据表的基本格式是这样的:


mysql> CREATE TABLE <table name;> (
    -> <column 1 name;> <col. 1 type;> <col. 1 details;> ,
    -> <column 2 name;> <col. 2 type> <col. 2 details;> ,
    -> ...
    -> );




  现在回到我们的例子“Jokes”表。这个表有三个数据列:ID(一个数字)、JokeText(笑话的正文)和JokeDate(加入的日期)。建立这个表的命令应该是这样的:


mysql> CREATE TABLE Jokes (
    -> ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> JokeText TEXT,
    -> JokeDate DATE NOT NULL
    -> );



  看上去很复杂,是吧?让我们将它分解一下:

  第一行是比较简单的;它说明我们想要建立一个新的名为Jokes的数据表。

  第二行说明我们需要一个数据列叫ID,这个列的类型应该是一个整数(INT)。这一行还定义了这个数据列的其他一些信息。首先,这一行不允许为空(NOT NULL)。第二,如果你没有为一列指定一个值,MySQL会选择使用一个比当前最大值大的值(AUTO_INCREMENT)。最后,这个数据列还是这数据表的唯一的标识符,所以这个数据列中的所有值都应该是不重复的(PRIMARY KEY)。

  第三行是非常简单的;这说明我们需要一个数据列叫JokeText,这个列的类型应该是一个文本(TEXT)。

  第四行定义了我们的最后一列,列名是JokeDate,这个列的类型是日期型(DATE)这个列也不能为空(NOT NULL)。

  请注意,我们在输入SQL命令时,大小写是完全自由的,但是在一个Unix-based
系统 下运行的MySQL服务,因为我们必须与MySQL数据目录下的目录和文件一致,当遇到 数据库 名和表名时,我们必须区分大小写。否则,MySQL是完全对大小写不敏感的,只有一种情况例外,在同一命令中多次出现的表名、列名以及其他名字必须在拼写上完全一致。

  我们还应该注意到,我们为我们建立的每一列指定了一个指定的类型。 ID是一个整型,JokeText是一个文本型,JokeDate是一个日期型。MySQL允许我们为每一个列定义一个类型。 这不仅仅可以帮助你组织数据,而且你可以利用它对数据进行比较(我们在下面会看到)。要想得到一个关于MySQL支持的数据类型的完整的列表,你可以参看MySQL用户手册。

  总之,如果你正确输入了上面的命令,MySQL会返回 Query OK并会为你建立你的第一个数据表。如果你在输入中出了什么错误,MySQL会告诉你输入的语名有问题,而且会给你一些提示,说明什么地方它不能理解。

  对于这样一个复杂的命令,最终只出现Query OK是相当单调的。让我们看看你的新数据表是不是正常地建立了。输入下面的命令:

mysql> SHOW TABLES;


  响应应该是这样的:


+-----------------+
| Tables in jokes |
+-----------------+
| Jokes |
+-----------------+
1 row in set



  这是一个关于我们的
数据库 (我们在前面将其命名为jokes)中的所有表的列表。这个列表仅仅包含了一个数据表:Jokes,这个表是我们刚刚建立的。看来一切都好了,让我们再来近看一下这个Jokes表:


mysql> DESCRIBE Jokes;
+----------+---------+------+-----+------------+- -
| Field | Type | Null | Key | Default | ...
+----------+---------+------+-----+------------+- -
| ID | int(11) | | PRI | 0 | ...
| JokeText | text | YES | | NULL |
| JokeDate | date | | | 0000-00-00 |
+----------+---------+------+-----+------------+- -
3 rows in set



  这儿提供了一个数据列的列表。正如我们看到的,这个表中有三个列,在返回的结果表中这被表示为三行。详细资料比较难以看懂,但是你认真看一下,应该还是能了解其大致的含义的。不要为这件事过于担心。我们还会继续学习,我们还会在这个表中添加一些笑话。

  我们还需要知道一些其他的事,例如删除一个表。这和删除一个
数据库 一样的简单,简单得令人恐怖。命令也几乎一样:

mysql> DROP TABLE ;


数据库 中添加数据

  我们的
数据库 和数据表都已经建立好了,现在我们该向我们的 数据库 中添加笑话了。向 数据库 中添加数据的命令被称之为INSERT。这个命令有两种基本格式:


mysql> INSERT INTO <table name;> SET
    -> columnName1 = value1,
    -> columnName2 = value2,
    -> ...
    -> ;
mysql> INSERT INTO <table name;>
    -> (columnName1, columnName2, ...)
    -> VALUES (value1, value2, ...);
    所以要向我们的数据表中添加笑话,我们可以在下面的两个命令中选择一个:
mysql> INSERT INTO Jokes SET
    -> JokeText = "Why did the chicken cross theroad? To get to the other side!",
    -> JokeDate = "2000-04-01";
mysql> INSERT INTO Jokes
    -> (JokeText, JokeDate) VALUES (
    -> "Why did the chicken cross the road? Toget to the other side!",
    -> "2000-04-01"
    -> );



  请注意在INSERT命令的第二种格式中,你给出的列的顺序必须与你给出的数据的顺序一致。

  现在你知道如何向表中添加了,下面让我们来看看如何显示表的内容。

显示存储的数据

  显示你的
数据库 中表的存储数据的命令,被称之为SELECT,这个命令无疑是SQL语言中最复杂的命令。说它复杂,是因为 数据库 的最主要的优点就是可以机动地给出数据。而机动性就是通过这个命令实现的。

  下面的命令会列出存储在表Jokes中的所有数据:

mysql> SELECT * FROM Jokes;


  这个命令意味着“从Jokes中挑选所有的东西”。如果你试着输入这个命令,你会看到这样的显示:


+----+---------------------------------------
------------------------+------------+
| ID | JokeText
                        | JokeDate |
+----+---------------------------------------
------------------------+------------+
| 1 | Why did the chicken cross the road? To
get to the other side! | 2000-04-01 |
+----+---------------------------------------
------------------------+------------+
1 row in set (0.05 sec)



  这看上去有点混乱,这是因为JokeText列实在是太长了。因为这个原因,我们可能想要告诉MySQL省去JokeText列,这个命令会实现这个功能:

mysql> SELECT ID, JokeDate FROM Jokes;


  这一次我们不再告诉它“挑选所有的东西”了,我们告诉它我们对显示哪些列感兴趣。结果应该是这样的:


+----+------------+
| ID | JokeDate |
+----+------------+
| 1 | 2000-04-01 |
+----+------------+
1 row in set (0.00 sec)



  但是我们是不是可以多少显示一点笑话正文的内容呢?作为对我们所想显示的列的补充,我们可用“函数”来更改我们所要显示的列。有一个叫做LEFT的函数,可以让我们告诉MySQL当我们显示一个数据列时最多显示几个字符。例如,如果我们只想显示JokeText列的前20个字符:


mysql> SELECT ID, LEFT(JokeText,20), JokeDate FROM Jokes;
+----+----------------------+------------+
| ID | LEFT(JokeText,20) | JokeDate |
+----+----------------------+------------+
| 1 | Why did the chicken | 2000-04-01 |
+----+----------------------+------------+
1 row in set (0.05 sec)



  明白它是如果工作的了吗?另一个有用的函数是COUNT,通过这个函数,我们可以很简单地得到返回结果的个数。例如,如果我们想要找出在我们的表中我们存储了多少笑话,我们可以用下面这个命令:


mysql> SELECT COUNT(*) FROM Jokes;
+----------+
| COUNT(*) |
+----------+
| 1 |
+----------+
1 row in set (0.06 sec)



  正如我们看到的,在我们的表中只有一个笑话。

  到目前为止,我们的所有的例子都是针对表中的所有记录的。作为对SELECT命令的补充,我们可以使用“WHERE子句”,这样我们可以对返回的结果进行限制。看看下面这个例子:


mysql> SELECT COUNT(*) FROM Jokes
    -> WHERE JokeDate >= "2000-01-01";



  这个查询语句会数出所有日期“大于或等于”2000年1月1日的记录,对于一个日期来说“大于或等于”意味着“在当天或在此之后”。

  有一种比较特殊的用法可以找出包含某一段文字的记录。你可以看看这个查询语句:

mysql> SELECT JokeText FROM Jokes
    -> WHERE JokeText LIKE "%chicken%";



  这个查询语句显示了所有JokeText列包含单词chicken的笑话的正文。LIKE关键字告诉MySQL指定的列必须匹配给定的表达式。在这里,我们使用的表达式是"%chicken%"。这儿的%说明单词chicken可以出现在任何字符串的前面或后面。

  条件也可以在WHERE子句中组合使用,这样可以做更复杂的查询。例如我们要显示2000年4月份的knock-knock笑话,我们可以使用下面的查询语句:


mysql> SELECT JokeText FROM Jokes WHERE
    -> JokeText LIKE "%knock knock%" AND
    -> JokeDate >= "2000-04-01" AND
    -> JokeDate < "2000-05-01";



  在表中添加再一些笑话,再试验试验SELECT语句。熟悉SELECT语句会有助于学习这个
教程

  我们还可以用SELECT语句做很多事,但是我们在这里将不再详细讨论它,我们在需要的时候才会再讲到其他一些高级的功能。如果你太好奇,没法再等下去的话,你可以去看MySQL用户手册。

修改存储的数据

  一旦你已经向
数据库 的表中输入了一些数据,你可能想要进行一些修改。例如改正拼写错误,以及其他有关笑话的数据,所有的这些改变都可以用UPDATE命令来完成。这个命令包含了一些INSERT命令(在设置列的数值方面)和 SELECT命令(在选取改变对象方面)的基本原理。UPDATE命令的基本格式是这样的:


mysql> UPDATE  SET
    -> =, ...
    -> WHERE ;



  例如,如果你想要改变上面输入的笑话的日期,你需要输入下面的命令:

mysql> UPDATE Jokes SET JokeDate="1990-04-01" WHERE ID=1;


  这儿我们用到了ID列。通过它你可以很方便地指定你要改变的笑话。WHERE子句也可以用在这里,就象在SELECT命令中那样。下面的命令是改变所有正文中包含单词chicken的笑话的日期:


mysql> UPDATE Jokes SET JokeDate="1990-04-01"
    -> WHERE JokeText LIKE "%chicken%";



删除存储数据

  在SQL中删除一个内容是令人恐怖的简单,下面是这个命令的格式:

mysql> DELETE FROM  WHERE ;


  要删除所有包含chicken的笑话,你只需要输入下面的命令:

mysql> DELETE FROM Jokes WHERE JokeText LIKE "%chicken%";


  这里的WHERE子句是可选的,但是如果你不用它,你应该清楚你在干什么,因为这时其实你是在清空这个数据表。下面这个命令将清空Jokes数据表:

mysql> DELETE FROM Jokes;


结语

  事实上除了我们在这里已经看到的这些基本的命令,MySQL
数据库 系统 和SQL语句还有许多其它值得学的东西,但是我们提到的这些命令是一些最常用的命令。到目前为止,我们只是在一个数据表中工作。要理解关系型 数据库 引擎的真正的强大功能,你还需要学会如果同时使用几个表以描述表之间可能存在的复杂的关系。

  所有的这些内容以及一些其他的内容,我们都会在我们的这个
教程 的第四章内讲到,在第四章中,我们会讨论 数据库 的设计原理并参考一些复杂一点的例子。现在,我们需要能够熟练地使用命令行界面来操作MySQL。

  在第三章内,我们将深入研究PHP这个服务器端的
脚本 语言,并且学习使用它来建立一个动态的Web页面。
---------------------------------------------------------------------------------
4.  在这一章中,我们将介绍PHP这个服务器端的
脚本 语言。我们将会看到,这个语言可以很好地支持与MySQL 数据库 的通信。
第三章:PHP入门

  在上一章中,我们学习了如何使用MySQL
数据库 引擎在一个简单的 数据库 (只包含一个叫Jokes的数据表)中存储一个笑话的列表。当时,我们是通过在MySQL客户端的命令行来输入SQL命令(查询语句)来完成的。在这一章中,我们将介绍PHP这个服务器端的 脚本 语言。我们将会看到,这个语言可以很好地支持与MySQL 数据库 的通信。

PHP简介

  正如我们在前面提到的,PHP是一个服务器端的
脚本 语言。这个概念可能很难理解,特别是如果你以前只用过HTML和JavaScript来设计过网页时更是如此。一个服务器端的 脚本 程序 与JavaScript在许多地方有点相像,两者都允许你在Web页面的HTML中插入一些 程序 脚本 )。其结果就是,这些 脚本 使你可以控制在浏览器窗口内会显示什么,这显然要比直接使用HTML要来得灵活得多。

  JavaScript和PHP的关键的不同点是:当Web浏览器解释JavaScript时,包含这个
脚本 的Web页面已经被下载了,而对于象PHP这样的服务器端 脚本 程序 来说,解释的工作是由服务器在将页面发出到浏览器之前完全的。解释工作完成后,Web页面中的PHP的代码将由 脚本 运行的结果所代替,浏览者看到的完全是标准的HTML文件。 脚本 是完全由服务器来处理的。这也就是它的命名的由来:服务器端 脚本 程序

  让我们再回头看看我们在第一章里建立的示例today.
php


<HTML>
<HEAD>
<TITLE>Today's Date</TITLE>
</HEAD>
<BODY>
<P>Today's Date (according to this Web server) is</p>
<?ph
  echo( date("l, F dS Y.") );
?>
</BODY>
</HTML>



  这个
程序 中的绝大多数是采用HTML格式的。只有在中间的行是用PHP写的。 表示“结束PHP代码”。Web服务器在将这个Web页面发送到请求它的浏览器之前会对这个两个标识符之前的所有内容进行处理,并将其转换成标准的HTML代码。浏览器接受到的页面将是这样的:


<HTML>
<HEAD>
<TITLE>Today's Date</TITLE>
</HEAD>
<BODY>
<P>Today's Date (according to this Web server) is</p>
Wednesday, June 7th 2000.
</BODY>
</HTML>



  请注意,现在所有的PHP代码都没有被显示。它们被相应的标准的HTML所取代,能过这个例子,我们可以看到服务器端
脚本 的几个优势:

  不存在浏览器兼容的问题。PHP
脚本 仅仅是由Web服务器来解释的,所以我们不必担心你使用的语言是否能被你的访问者的浏览器所支持。

  可以访问服务器端的资源。在上面的例子中,我们在Web页面中放置了Web服务器的日期。而当我们使用的是JavaScript,要实现同样的功能,我们只能显示Web浏览器在上面运行的计算机的日期。这个例子还对于使用服务器端的资源还不是十分典型的,事实上我们可以很方便地插入一些其他的信息,而这些信息只能通过运行在服务器上的
脚本 来调用,例如,运行在Web服务器上的MySQL 数据库 中存储的信息。

  简化了客户端的装载。JavaScript会明显降低Web页面的显示速度,因为在显示这个Web页面之前,浏览器首先得运行JavaScript
脚本 。而对于服务器端 脚本 来说,这种负担将由Web服务器独自承担。

基本的语法和命令

  对于任何一个用过C、C++、Java、JavaScript、Perl或其他源自C的语言的人,PHP的语法都会让你觉得非常熟悉。一个PHP
脚本 包含一系列的命令(语句),Web服务器必须依次处理这些指令。与上面提到的其他语言一样,PHP语句也总是以分号(;)结束。

  这是一个典型的PHP语句:

echo( "This is a test!" );


  这个语句调用了一个叫echo的内置函数,并传递给它这么一个字符串:“This is a test! ”。内置函数你可以理解为“不需要另外的说明PHP就能知道该怎么做”的事情。PHP有很多的内置函数,我们可以利用它们来做许多事,从发送e-mail到处理存储在
数据库 中的不同类型的数据都是它们的管辖范围。echo函数只是简单地将传递给它的文本插入到HTML页面的当前位置。你可以看看下面这个例子:


<HTML>
<HEAD>
<TITLE> Simple PHP Example </TITLE>
</HEAD>
<BODY>
<P><?
php echo("This is a <B>test</B>!"); ?></P>
</BODY>
</HTML>



  如果你给这段代码起名为test.
php (或者test. php 3,如果你的Web主机还没有将. php 文件配置为PHP 脚本 ),并将它放置到你的Web服务器上,浏览器看到的将是这样的一页:


<HTML>
<HEAD>
<TITLE> Simple PHP Example </TITLE>
</HEAD>
<BODY>
<P>This is a <B>test</B>!</P>
</BODY>
</HTML>



  请注意,包含HTML标识符(和)在内的所有文本都被正确地显示了出来。

  你也许会感到疑惑,我们为什么要在这里使用括号和引号。引号在PHP中是用来标志字符串的开始和结束。括号有双重作用,首先,它指出echo是一个你想要调用的函数,其次,它标志了这个函数的参数的开始和结束。通过参数,你可以指挥你的函数去干什么。对于echo函数,我们只需要给它一个字符串,用来在页面上显示,但是我们将会看到有些函数有几个参数(在这种情况下,我们用逗号分开各个参数)。即使对于没有参数的函数,我们仍需要有括号,只不过在括号中间我们不必输入任何内容。

变量和运算符

  PHP中的变量与许多其它
程序 中的变量一样。当还未被初始化时,变量仅仅是一个假想的容器的名字,其中可以存放任何数值。下面的语句建立了一个叫$testvariable(在PHP中所有的变量都以一个美元符开始)并将其赋值为3:

$testvariable = 3;


  PHP是一个“宽松类型”的语言,这就是说,一个变量可以包含任何类型的数据(数字、字符串或者其他类型),在它的存活期内其类型可以自由地转换。所以如果在上面的语句后再出现这样的语句,这就意味着给我们的已经存在的$testvariable变量重新赋了一个值。这个变量从一个数值变量变成了一个字符串变量:

$testvariable = "Three";


  在上面的两个语句中我们用到的等于号被称之“赋值运算符”,它是用来给一个变量赋值的。另外,我们还有一些执行数学运算的运算符:


$testvariable = 1 + 1; //变量赋值为2。
$testvariable = 1 - 1; //变量赋值为0。
$testvariable = 2 * 2; //变量赋值为4。
$testvariable = 2 / 2; //变量赋值为1。



  上面的各行的最后都有一个注释。注释是通过插入解释性的文字来说明我们的代码的用途,同时它也会通知PHP解释
程序 忽略对这部分语句的解释。注释以//开始并在同一行内结束。如果你熟悉在其他语言中的/* */风格的注释,在PHP中你也可以这样用。在我们这个 教程 中,我们会经常使用注释来对 程序 作出解释。

  现在回到我们上面的四个语句,四个运算符分别被用来完成加、减、乘、除的运算。另外,还有一个运行符是用来连接字符串的:


//给变量赋值为"Hi there!".
$testvariable = "Hi " . "there!";



  变量可以被应用在很多使用实际数值的地方。你可以看看下面的例子:


$var1 = "PHP"; //将$var1赋值为"PHP"
$var2 = 5; //将$var2赋值为5
$var3 = $var2 + 1; //将$var3赋值为6
$var2 = $var1; //将$var2赋值为"PHP"
echo($var1); //输出"PHP"
echo($var2); //输出"PHP"
echo($var3); //输出6
echo($var1 . " rules!"); //输出"PHP rules!"
echo("$var1 rules!"); //输出"PHP rules!"
echo('$var1 rules!'); //输出'$var1 rules!'



  请特别注意最后的两行,你可以直接在一个字符串中包含一个变量名,如果你用双引号将其括起来,将会用该变量的值代替变量名。而最后一行证明,如果你使用的是单引号,是不会作这种转换的。

用户交互和表单

  对于许多我们感兴趣的PHP应用来说,最基本的功能是实现与浏览这个页面的用户的交互。如果你熟悉JavaScript,你可能会习惯于这么一种事务处理的模式,那就是对用户的许多行动直接作出反应(例如将鼠标移动到页面上的一个连接)。而对于PHP这样的服务器端
脚本 程序 而言,它用来实现与用户交互的活动范围要小得多,与用户的交互仅仅发生在用户向服务器发出请求以及服务器用一个动态页面作出回应之间。

  用户与PHP实现交互的关键是理解用户对一个新Web页面发出的请求中可能包含的发出信息。我们将会看到,PHP使得这个工作极为简单。

  最简单的方法是使用“URL查询字符串”在页面请求中发出信息。如果你曾经看到过一个在文件名后包含问号的URL,那就是采用的这种
技术 。让我们来看一个简单的例子。建立一个标准的HTML文件(不一定使用. php 扩展名,在这个文件中将不包含任何PHP代码),并在其中加入以下连接:

Hi, I'm Kevin!


  这是指向一个叫welcome.
php 的文件的连接,但是在连接这个文件的同时,我们还在页面请求中传递了一个变量。这个变量是被作为“查询字符串”的一部分传递的,它位于URL的问号后面。这个变量的名字是name,它的值是Kevin。也就是说,我们建立了一个连接,这个连接装载welcome. php 并告知这个文件中包含的PHP代码:name等于Kevin。

  要清楚这么做对我们有什么好处,我们需要看看welcome.
php 。 同样地将其作为一个新的HTML文件来建立,但是这一次要记得使用. php 扩展名,这会告诉Web服务器在这个文件中有一些PHP代码需要解释。如果你的Web服务器还不接受. php 作为PHP文件的扩展名,你可能需要将其改名为welcome. php 3(在这种情况下,你也需要相应调整上面的代码中的连接)。在这个新文件中,输入以下内容:


<?
php
  echo( "Welcome to our Web site, $name!" );
?>



  现在,如果你用第一个文件中连接去装载第二个文件,你会看到这一页显示“Welcome to our Web site, Kevin!”,这个通过URL的查询字符串传递过来的变量的值被自动地赋予了一个叫$name的变量,我们在一段文本中显示了这个传递过来的变量。

  如果你需要的话,你也可以通过查询字符串传递几个变量。让我们看看这个例子的稍微复杂一点的版本。将HTML文件中的连接改变为:



Hi, I'm Kevin Yank!



  这一次,我们传递了两个变量:firstname和lastname。这些变量在查询字符串中被&符号分开。你可以传递更多的变量,只要你将每一个name=value对以&符号分开。

  如前所述,我们可以在我们的welcome.
php 文件中使用这两个变量的值:


<?
php
  echo( "Welcome to our Web site,
$firstname $lastname!" );
?>
-----------------------------------------------------------------------------------
5.  虽然看上去一切都好了,但是我们仍没有达到我们真正地与用户交互的目的,我们的用户应该能够输入任意的信息,并将它交给PHP来处理。接着我们的个性化欢迎页面的例子,我们想要让我们的用户任意地输入他(或她)的名字并将其显示到信息中,要让用户输入数据,我们需要用到HTML的表单。

这儿是表单的代码:


<FORM ACTION="welcome.
php " METHOD=GET>
First Name: <INPUT TYPE=TEXT NAME="firstname"><BR>
Last Name: <INPUT TYPE=TEXT NAME="lastname">
<INPUT TYPE=SUBMIT VALUE="GO">
</FORM>
除了在这里你可以任意输入你的名字以外,这个表单所起的效果和我们上面的第二个连接(在查询字符串中使用firstname=Kevin&lastname=Yank)完全一样。当你按提交按钮(标志为“GO”)时,浏览器会装载welcome.
php 并自动为你在查询字符串中添加变量和它们的值。变量名就是在INPUT TYPE=TEXT标识中的NAME属性,变量值就是用户输入的相应的内容。

  INPUT TYPE=TEXT标识中的METHOD属性是用来告诉浏览器如何在请求中发送变量名及变量值的。GET(就是我们在上面使用的)表示在查询字符串中传递变量,但是还有另外一种选择。将变量显示在查询字符串中并不总是令我们满意的--甚至有的时候在
技术 上就是不可行的。如果在你的表单中包含了一个TEXTAREA标识用来让用户输入大量的文本,这部分文本也显示在查询字符串中实在是太长了,而且会超过浏览器所能支持的URL的最大长度。另外一种方法可以允许浏览器隐藏地传递信息。这种方法的代码和我们上面看到的表单的代码几乎一样,只是我们将表单的方法从GET变成了POST:


<FORM ACTION="welcome.
php " METHOD=POST>
First Name: <INPUT TYPE=TEXT NAME="firstname"><BR>
Last Name: <INPUT TYPE=TEXT NAME="lastname">
<INPUT TYPE=SUBMIT VALUE="GO">
</FORM>



  这个表单和我们之前的那个在功能上完全一样。唯一的不同是当用户在按“GO”按钮时所装载页面的URL将没有一个查询字符串。一方面,这可以让你通过表单提交大量的数据或者是敏感的数据(例如密码),而不在一个查询字符串中显示出来。另一方面,如果用户将提交表单生成的结果页添加到收藏夹,这个收藏夹是没有用的,因为它不包含提交的数据。另外,附带说一下,象AltaVista这样的搜索引擎总是利用查询字符串来提交查询条件,其主要原因就是为了便于用户将查询结果页添加到收藏夹中,以便在将来进行同样的搜索,因为搜索条件是包含在URL之中的。

  这儿讲了利用表单来实现用户与PHP的交互的基本的原理。在以后的例子中,我们将讨论一些更高级的问题和
技术

控制语句

  在我们之前看到的PHP的代码的例子中,要么是只有一个单独的向Web页面输出文本语句;要么是一系列的依次执行的语句。如果你用其他语言编写过
程序 ,你应该知道,实际上很少有这么简单的 程序

  和任何其他的编程语言一样,PHP也提供了很方便地处理
脚本 中的“控制流”的方法。就是说,PHP中包含了一些特殊的语句,通过这些语句你可是不受依次执行的顺序的束缚。这种语句被称之为“控制语句”。不理解?不要担心!有一些例子会很好地帮助你。

   最基本最常用到的控制语句是if-else语句。它的结构是这样的:


if ( <condition> ) {
  //如果<condition>是真,将执行的语句。
} else {
  //(可选)如果<condition>是假,将执行的语句。
}
    这个控制语可以让我们告诉PHP根据一些条件的真假来决定相应地执行哪一组语句。如果你不觉得我这么做有点空虚,我们可以将我们刚才建立的welcome.
php 文件修改为:
if ( $name == "Kevin" ) {
  echo( "Welcome, oh glorious leader!" );
} else {
  echo( "Welcome, $name!" );
}



  现在,如果传递给这个页面的name变量的值是Kevin,将显示一个特殊的信息。否则,将显示一个包含输入的name的普通的信息。

  需要指出的是,在这个结构中,“else子句”(它指出了if-else结构中条件为假时执行的内容)是可选的。对于上面的例子,如果我们的目的是当适当的名字被输入时,显示特殊的信息,否则就什么也不显示。这段代码应该是这样的:


if ( $name == "Kevin" ) {
  echo( "Welcome, oh glorious leader!" );
}



  在上面条件中所使用的==是用比较两个值是否相等的运算符。要特别记住的是在这儿你需要输入两个等号。如果你输入的是一个等号,你实际上使用的是前面我们讨论过的赋值运算符,你将不再是对两个变量的值进行比较,而是给变量赋了一个新值(这个操作会附带地返回一个true)。这样做的结果不仅仅是导致这个条件永远是true,它还可能改变我们所要检查的变量的值,这可能会导致很多问题。

  防止发生这种错误有一种
安全 的做法,那就是象下面这样颠倒用来比较的变量和常量的位置:

if ( "Kevin" == $name ) {


  这样做的效果是完全相同的,但是当你忘了第二个等号时,我们来看看会发生什么情况。PHP会试图将变量($name)的值插入常量("Kevin")中。因为你不能改变常量的值,PHP会中断并提示一个错误信息,这将立即提示你忘了第二个等于号!

  条件可以比单个的比较是否相等来得更复杂。回忆我们修改的welcome.
php 3,它是可以同时获取firstname和lastname的。如果我们想要为某个特定的人显示一个特殊的信息,我们可以同时比较这两个变量:


if ( "Kevin" == $firstname and "Yank" == $lastname ) {
  echo( "Welcome, oh glorious leader!" );
}



  只有$firstname的值是Kevin,而且$lastname的值是Yank时这个条件才会返回真。and的意义就是只有两个比较都为真时,整个条件才会返回真。还有一个符号是or,这使得两个比较中至少有一个为真时,整个条件就返回真。如果你对JavaScript和C中的运算符(&&(and)和||(or))熟悉的话,你也可以在PHP中同样地使用它们。

  在下面我们将看到一些更复杂的比较。现在,我们只需要对if-else语句有个基本的理解就可以了。

  另一个常用的PHP控制语句是while循环。if-else语句使我们可以根据条件选择是否执行一组语句,while循环使我们可以根据条件来决定重复执行一组语句多少次。while循环的基本格式应该是这样的:


while ( <condition> ) {
  //只要<condition>是真时反复执行的语句
}



  这和一个没有else子句的if-else 语句非常相象。不同点在于当条件为真时语句执行完后,将不再是接着执行结束符(})后面的语句,而是再次检查条件。如果这个条件仍为真。将会重复执行语句,直到条件不再为真时为止。当这个条件首次返回假时(不管是第几次检查它),将会跳转执行循环后面的语句(在结束符后面)。

  这样的循环可以用来处理一个事物的较长的列表(例如存储在
数据库 中的笑话),下面我们举了一个简单的例子:计数到10。


$count = 1;
while ($count <= 10) {
  echo( "$count " );
  $count++;
}



  我知道这段语句可能看上去挺恐怖,但是我们可以一行行地来看它。第一行定义了一个叫$count的变量并将其赋值为1。第二行是while循环的开始,条件是$count小于或等于(<=)10。第三行和第四行是while循环的循环体,当条件为真时,我们将重复执行它。第三行简单地输出了一$count的值,并在其后加了一个空格。第四行将$count的值加一($count++是$count = $count + 1的缩写--两者的意义是完全一样的)。

  现在我们可以看看这段
程序 是如何执行的了。当第一次检查条件时,$count的值是1,所以条件为真。$count的值(1)被输出,接着$count被赋予了一个新值2。当第二次检查条件时条件仍为真,所以2 被输出,并赋了一个新值3 。这个过程被继续下去,输出了3 ,4 ,5 ,6 ,7 ,8 ,9 直到10 。最后,$count被赋予值11,条件为假,循环结束。最终的结果是输出了这样一个字符串“1 2 3 4 5 6 7 8 9 10”。

  在这个例子的条件中我们使用了一个新的运算符:<= (小于或等于)。其他用于数值比较的运算符还有>=(大于或等于),<(小于),>(大于)和!=(不等于)。最后一个也可以使用于字符串比较中。

多用途的页面

  如果你想在你建立的
网站 的每一个网页的顶端都显示访问者的姓名。使用我们前面的自动显示欢迎信息的例子,我们已经基本上成功了一半。现在我们只要对我们示例解决这几个问题就行了:

  我们需要在站点的每一个页面都显示,而不是仅仅在一个页面上。

  我们无法控制在我们的站点上那一个页面会首先显示。

  第一个问题的解决不是太困难的。当我们在一个页面上获得了用户名这个变量后,我们可以在任何请求中通过将其添加到一个查询字符串来传递这个变量:

<A HREF="newpage.
php ?name=<? php echo(urlencode($name)); ?>"> A link </A>


  请注意我们在HTML标识符的中间嵌入了PHP的代码。实际上这是非常常用的。我们已经对echo这个函数很熟悉,但是我们还不熟悉urlencode函数。这个函数的功能是将字符串中一些特殊的字符(例如空格)转换成特定的编码,以使它们能够在查询字符串中显示。例如,如果$name变量的值是"Kevin Yank",其中的空格在查询字符串中不允许存在,urlencode的输出将是Kevin+Yank,在newpage.
php 中建立$name时,值将会被自动转换回来。

  Ok,现在已经可以将用户名传递给我们站点的第一个连接了。现在我们所需要的就是在其第一次出现时,要能获得它的值。在我们上面的例子中,我们已经做了一个HTML页面用来处理获得用户名的表单。而问题是我们不能强迫用户在每一次访问我们的站点时都从这个页面开始。

  解决方案是在我们站点的每一个页面都检查是否指定了一个用户名,如果需要,应该提求用户输入用户名。这意味着我们站点上的每一个页面都必须能显示用户名,在未指定用户名时,应提示用户输入。如果你现在就想到了使用if-else语句,那证明你的学习能力真的不错!

  我们的“多功能页面”应该根据不同的条件显示完全不同的内容,这个页面的源
程序 将会是这样的:


<HTML>
<HEAD>
<TITLE> Multi-Purpose Page Outline </TITLE>
</HEAD>
<BODY>
<?
php if (<condition>) { ?>
<!-- HTML content to display if <condition> is true -->
<?
php } else { ?>
<!-- HTML content to display if <condition> is false -->
<?
php } ?>
</BODY>
</HTML>



  这段
程序 初看上去很混乱,但是事实上这仍然是普通的if-else语句,只不过在其中插入了HTML代码,而不是我们之前使用的PHP语句。这个例子说明了PHP的一个很大的优点:你可以自由地选择在什么时候进行或退出“PHP模式”。你可以将<? php 看成是进入“PHP模式”的命令,将?>看成是返回到“普通的HTML模式”的命令。这样上面的例子就变得很容易理解了。

  if-else语句还有另外的一种格式,使用这种格式将使你的
程序 更易读懂。如果使用这种格式,我们的“多功能页面”的源 程序 将是这样的:


<HTML>
<HEAD>
<TITLE> Multi-Purpose Page Outline </TITLE>
</HEAD>
<BODY>
<?
php if (<condition>): ?>
<!-- HTML content to display if <condition> is true -->
<?
php else: ?>
<!-- HTML content to display if <condition> is false -->
<?
php endif; ?>
</BODY>
</HTML>



  Ok,现在我们已经有了所有我们需要的工具,让我们看看我们的站点中的一个样页:


<HTML>
<HEAD>
<TITLE> Sample Page </TITLE>
</HEAD>
<BODY>
<?
php if ( isset($name) ): ?>
  <P>Your name: <?
php echo($name); ?></P>
  <P>This paragraph contains a
<A HREF="newpage.
php ?name=<? php echo(urlencode
($name)); ?>">link</A> that passes the
name variable on to the next document.</P>
<?
php else: ?>
  <!-- No name has been provided, so we
       prompt the user for one. -->
  <FORM ACTION=<?
php echo($PHP_SELF); ?> METHOD=GET>
  Please enter your name: <INPUT TYPE=TEXT NAME="name">
  <INPUT TYPE=SUBMIT VALUE="GO">
  </FORM>
<?
php endif; ?>
</BODY>
</HTML>



  在上面的
程序 中出现了两个新的东西,但是理解它们应该不是太困难的。首先,我们在条件中使用了一个新的函数:isset。当变量已经被赋值(在我们这里也就是指提供了用户名),该函数将返回(输出)一个逻辑真;当变量没有被赋值(在我们这里也就是指没有提供用户名),该函数将返回(输出)一个逻辑假。第二个新东西是在指定FORM标志中的ACTION属性中使用了$PHP_SELF变量。这个变量是自动产生的 系统 变量之一。具体地说,$PHP_SELF总是被设置成当前页面的URL。当一个表单在提交时指向同一个页面时,这给我们提供一个简单的做法。只不过这时的 $name变量已经被赋值了。

  将这一段加到你的
网站 上的所有网页上后,不管访问者第一次访问的是什么网页,都会被提示输入用户名。只有在输入了用户名并按了“GO”,才能到达他们真正想要访问的网页。输入的用户名会被通过每个连接中的查询字符串传递到之后的各个页面,这样就可以确保只要求访问者输入一次用户名。

结语

  在这一章内,我们介绍了PHP的所有的基本语法:语句、变量、运算符以及控制语句。我们的例子是非常的简单。但是事实上PHP的强大功能在于它内置的数百个函数,利用这些函数你可以访问MySQL
数据库 中的数据来发送邮件,可以通过动态产生的图象来建立PDF文件,你还可以做其他的很多事情。

  在第四章,我们将探讨如果利用MySQL在Web上发布我们在上一章中建立的笑话
数据库
-----------------------------------------------------------------------------------------
6.   在这一章内我们会学习到如何在一个Web页面中向
数据库 中存储信息并显示它。
第四章: 用PHP访问MySQL
数据库

  在这一章内我们会学习到如何在一个Web页面中向
数据库 中存储信息并显示它。之前我们已经安装了MySQL这个关系型 数据库 引擎以及PHP这个服务器端 脚本 语言,并学习了有关它们的基本知识。在学完这一章后,我们将明白如何综合利用这两个新的工具来构建一个 数据库 驱动的 网站

对前一部分的回顾
在我们往下继续之前,回顾一下我们学习的目的应该是件有价值的事。现在有我们的
系统 中有了两个强有力的新的工具: 脚本 语言PHP和 数据库 引擎MySQL。搞清楚两者是如果协同工作是很重要的。

  
数据库 驱动的 网站 的实质就是允许站点的内容存在于一个 数据库 中,并且可以通过这个 数据库 来动态地产生Web页面来让我们的访问者通过标准的Web浏览器来显示它。所以在你的 系统 的一端是一个访问你的站点的浏览者,他通过访问http://www.yoursite.com/来获得一个标准的HTML格式的Web页面并在Web浏览器中显示它。在你的 系统 的另一端是通过一个或几个数据表存储在一个只理解如何响应SQL查询(命令)的MySQL 数据库 中的你的站点的内容。

  PHP
脚本 语言承担了两者之间的联络员的角色,使用PHP,你可以编写一个标准HTML的“模板”,这个“模板”决定了你的站点的外观(包括图画和页面设计)。这时内容是属于这个“模板”的,你可以使用一些PHP代码来连接MySQL 数据库 并且使用SQL查询来获得数据并在其相应位置显示它,这里的SQL查询是和我们在第二章中用来建立笑话数据表时一样的。

  现在对于访问者在访问你的
数据库 驱动的 网站 的一个页面时,到底会发生什么事,你应该有个明确的认识了:

  访问者的Web浏览器使用一个标准的URL请求这个页面。

  Web服务器软件(Apache、IIS或其他)认定被请求的页面是一个PHP
脚本 ,因而在响应这个页面请求之前用它的PHP插件来解释它。

  一些PHP命令(我们还没学到)会连接MySQL
数据库 并向 数据库 请求属于这个Web页面的内容。

  MySQL
数据库 作出响应并且向PHP 脚本 发出被请求的内容。

  PHP
脚本 将内容存储到一个或几个PHP变量中,并使用我们熟悉的echo函数将其作为Web页面的一部分输出。

  PHP插件完成处理并将生成的HTML副本返回到Web服务器。

  Web服务器将这个HTML副本发送到Web浏览器,这将是一个标准的HTML文件,只不过它不是直接来自于一个HTML文件,而是来自于PHP插件提供的输出。

用PHP连接MySQL

  在我们从我们的MySQL
数据库 中获取我们的Web页面所包含的内容之前,我们首先必须知道如何建立与MySQL的连接。在第二章中,我们使用了一个叫mysql的 程序 来做这样的连接。PHP不需要这样的一个 程序 ,对连接MySQL的支持是语言内置的。下面的这个函数用来建立这样的连接:

mysql_connect(<address>, <username>, <password>);


  在这里,<address>是MySQL服务软件在其上运行的计算机的IP地址或主机名(如果这与运行Web服务软件的计算机是同一台,你可以使用"localhost"),<username>和<password>就是你在第二章中用来连接到MySQL服务器的用户名及口令。

  你可能还记得PHP中的函数在被调用时往往会返回(输出)一个值。请不要担心我们没有提醒你,我们在最初接触一个函数时都会为你详细详细它。绝大多数的函数在被调用后,都会返回一个可以在存储在变量中的值以备下次使用。例如我们上面介绍的mysql_connect函数,会返回一个数字来标识已经建立的连接。因为我们会要使用这个连接,所以我们必须保存这个值。下面是一个关于如何连接我们的MySQL
数据库 的一个实例:

$dbcnx = mysql_connect("localhost", "root", "mypasswd");


  需要说明的是,对于你的MySQL服务器,上面这个函数中的三个参数的值可能是不同的。你应该注意到在这儿我们的mysql_connect 返回了一个值(我们称之为一个连接标识),这个值被我们存储在变量$dbcnx中。

  因为MySQL是一个完全分布式的软件,我们必须考虑到这些可能性:服务不可用、
网络 堵塞或者是我们的用户名及口令不匹配。在这些情况下,mysql_connect函数不能返回一个连接标识(因为连接未被建立)。这时,会返回一个逻辑假。这使得我们可以用一个if语句来处理连接的情况: $dbcnx = @mysql_connect("localhost", "root", "mypasswd");


if (!$dbcnx) {
  echo( "<P>Unable to connect to the " .
        "database server at this time.</P>" );
  exit();
}



  在上面的代码段中出现了三个新的东西,首先,我们在mysql_connect函数前加了一个@符号。包括mysql_connect在内的许多函数会在失败后显示难看的错误信息。在函数名前加一个@符号可以告诉这个函数当执行失败时,允许我们显示我们自己友好的出错信息。

  其次,在我们的if语句的条件中,$dbcnx变量前面加了一个惊叹号。这个惊叹号是PHP中的“否运算符”。也就是说将逻辑真变为逻辑假,将逻辑假变为逻辑真。这样,如果这个连接是失败的,mysql_connect会返回一个逻辑假,!$dbcnx将等于逻辑真,这样我们的if语句将被执行。相反,如果这个连接是成功的,存储在$dbcnx 中的连接标识将等于逻辑真(在PHP中,任何非零的数字都被认为是逻辑真),所以!$dbcnx会等于逻辑假,if语句将不会被执行。

  最后一个是exit函数,这是我们遇到的第一个没有参数的函数。这个函数的全部作用就是导致PHP停止对本页的阅读。如果
数据库 连接失败这是一个很好的响应,因为绝大多数情况下,如果不能连接到 数据库 ,这一页不会显示任何有用的信息。

  和我们在第二章做过的一样,连接被建立后下一步就是选择工作的
数据库 。我们将要在第二章中所建立的笑话 数据库 中工作。这个 数据库 被命名为jokes。在PHP中用来选择 数据库 的另外一个函数:

mysql_select_db("jokes", $dbcnx);


  请注意我们在这儿使用了$dbcnx变量来指出了这个函数所使用的连接标识。这个参数实际上是可省略的。当省略这个参数时,函数会自动使用最后开启的那一个连接。这个函数成功后返回逻辑真,失败后返回逻辑假。为了谨慎起见,我们也用了一个if语句来处理错误:


if (! @mysql_select_db("jokes") ) {
  echo( "<P>Unable to locate the joke " .
        "database at this time.</P>" );
  exit();
}



  当建立了连接并选择了
数据库 之后,我们可以开始使用存储在 数据库 中的数据了。

在PHP中执行SQL查询

  在第二章中,我们使用一个叫mysql的
程序 来连接到MySQL 数据库 服务器,在这个 程序 中,我们可以输入SQL查询(命令)并立即显示查询结果。在PHP中,有着类似的机制:mysql_query函数。

mysql_query(<query>, <connection id>);


  在这儿,<query>是一个包含将执行的SQL命令的字符串。和mysql_select_db一样,连接标识这个参数也是可选的。

  这个函数的返回决定于发出的查询的类型。对于绝大多数的SQL命令来说,mysql_query返回逻辑真或逻辑假来标明执行是否成功。请参看下面这个例子,这是用来建立我们在第二章中建立的Jokes数据表的:


$sql = "CREATE TABLE Jokes ( " .
       "ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, " .
       "JokeText TEXT, " .
       "JokeDate DATE NOT NULL " .
       ")";
if ( mysql_query($sql) ) {
  echo("<P>Jokes table successfully created!</P>");
} else {
  echo("<P>Error creating Jokes table: " .
       mysql_error() . "</P>");
}



  这儿使用的mysql_error将以字符串的形式返回MySQL服务器最后发出的错误信息。

  对于DELETE、 INSERT以及UPDATE(用来修改存储的数据),MySQL可以知道有多少数据行被这个查询影响。参看下面的SQL命令,这个命令我们曾在第二章中用来设置所有包含单词“chicken”的笑话的日期:


$sql = "UPDATE Jokes SET JokeDate='1990-04-01' " .
       "WHERE JokeText LIKE '%chicken%'";
    当我们执行这个查询时,我们可以使用mysql_affected_rows函数来显示这个修改所影响的数据行的数目:
if ( mysql_query($sql) ) {
  echo("<P>Update affected " .
        mysql_affected_rows() . " rows.</P>");
} else {
  echo("<P>Error performing update: " .
       mysql_error() . "</P>");
}



  SELECT命令会有一些不同,因为它会得到许多信息,而PHP必须提供方法来处理这些信息。

处理SELECT结果集

  对于绝大多数的SQL查询来说,mysql_query函数仅仅返回逻辑真或逻辑假。而对于SELECT查询来说,仅仅这样显然是不够的。你应该还记得SELECT查询是用来显示
数据库 中存储的数据的。除了指出查询成功还是失败之外,PHP还必须得到查询的结果。作为一个结果,当我们执行一个SELECT查询的时候,mysql_query会返回一个标识“结果集”的数字,这将包含了这个查询返回的所有行的列表。如果查询失败,函数仍然是返回一个逻辑假。


$result = mysql_query("SELECT JokeText FROM Jokes");
if (!$result) {
  echo("<P>Error performing query: " .
       mysql_error() . "</P>");
  exit();
}



  假定在执行查询时没有遇到错误,上面的代码会定位一个有关存储在笑话库中所有笑话的正文的结果集,这个定位被存储在变量$result中。因为
数据库 中的笑话的数目是没有限制的,这个结果集可能非常庞大。

  我们之前曾经提到过while循环对于处理大量的数据来说是一个非常有用的控制语句,这是我们逐个处理结果集中数据行的代码的基本格式:


while ( $row = mysql_fetch_array($result) ) {
  // process the row...
}



  在这个while循环中的条件可能看上去与我们曾经使用过的有所不同,所以我们有必要在这里解释它的工作机理。你可以先把这个条件看成一个独立的语句:

$row = mysql_fetch_array($result);


  mysql_fetch_array函数以一个参数(对于这个例子来说是存储在$result变量中)接受到一个结果集,并以一个数据的形式返回结果集中的下一行。如果你还不熟悉数组的概念,不要担心,我们会在下面详细讨论它。如果在这个结果集中不再有其它数据行时,mysql_fetch_array返回逻辑假。

  现在,我们上面的语句定义了一个值到$row变量中,与此同时,整个语句也获得了同样的值。这就是我们在while循环的条件中使用这个语句的原因,因为while循环会一直执行循环直到条件等于逻辑假,结果集有几行,这个循环就会执行几次,每一次$row都会得到一个下一行的值,现在剩下的就是如何在循环中从$row变量中获得相应的值了。

  结果集中的行被描述成一个数组。数组是一个特殊类型的变量,这个变量可以包含多个值,如果你把一个变量看成是值的容器,你可以把数组看成是有间隔的容器,在每一个间隔中可以存储一个单独的值。对于我们的数据行来说,这个间隔是以数据表的列名命名的。如果$row是我们结果集中的一行,那么$row["JokeText"]就是这一行中JokeText列的值。所以如果我们想要显示我们的
数据库 中所在笑话的正文,while循环应该是这样的:


while ( $row = mysql_fetch_array($result) ) {
  echo("<P>" . $row["JokeText"] . "</P>");
}



  最后,作为一个总结,这是一段完整的PHP的Web页面的代码,它用来连接我们的
数据库 ,取出 数据库 中所有笑话的正文,并将其在HTML中显示出来:


<HTML>
<HEAD>
<TITLE> Our List of Jokes </TITLE>
</HEAD>
<BODY>
<?
php

  // Connect to the database server
  $dbcnx = @mysql_connect("localhost",
           "root", "mypasswd");
  if (!$dbcnx) {
    echo( "<P>Unable to connect to the " .
          "database server at this time.</P>" );
    exit();
  }

  // Select the jokes database
  if (! @mysql_select_db("jokes") ) {
    echo( "<P>Unable to locate the joke " .
          "database at this time.</P>" );
    exit();
  }

?>
<P> Here are all the jokes in our database: </P>
<BLOCKQUOTE>

<?
php
    // Request the text of all the jokes
  $result = mysql_query(
            "SELECT JokeText FROM Jokes");
  if (!$result) {
    echo("<P>Error performing query: " .
         mysql_error() . "</P>");
    exit();
  }

  // Display the text of each joke in a paragraph
  while ( $row = mysql_fetch_array($result) ) {
    echo("<P>" . $row["JokeText"] . "</P>");
  }
?>
</BLOCKQUOTE>
</BODY>
</HTML>



数据库 中插入数据

  在这一节里,我们会看到我们会如何综合利用这些工具来让我们站点的访问者向
数据库 中添加他们自己的笑话。如果你喜欢挑战,你可以试试在向下看之前想想大致上应该怎么做。在这一节里只有很少新的东西。对于我们学过的东西来说,这只是一个简单的应用。

  如果我们想要让访问者能够输入新的笑话,我们首先需要一个表单,这儿是这个表单的代码:


<FORM ACTION="<?
php echo($PHP_SELF); ?>" METHOD=POST>
<P>Type your joke here:<BR>
<TEXTAREA NAME="joketext" ROWS=10 COLS=40 WRAP></TEXTAREA><BR>
<INPUT TYPE=SUBMIT NAME="submitjoke" VALUE="SUBMIT">
</FORM>



  正如我们上面看到的那样,这个表单在提交时会载入同一个页面(因为我们在表单的ACTION属性中使用了$PHP_SELF变量),但是在再次载入时请求中包含了两个变量,首先是$joketext,这是在text域中输入的笑话的正文,另一个是$submitjoke,这个变量的值将始终是"SUBMIT",这用来标志笑话已被提交。

   要将已提交的笑话添加到
数据库 中,我们需要用mysql_query来运行一个INSERT查询,这个查询中将包含已经提交的$joketext变量的值:


if ("SUBMIT" == $submitjoke) {
  $sql = "INSERT INTO Jokes SET " .
         "JokeText='$joketext', " .
         "JokeDate=CURDATE()";
  if (mysql_query($sql)) {
    echo("<P>Your joke has been added.</P>");
  } else {
    echo("<P>Error adding submitted joke: " .
         mysql_error() . "</P>");
  }
}



  在全部的内容中只有SQL代码中出现了一个新的东西。在这里我们使用了一个MySQL函数CURDATE()来将新插入
数据库 的笑话的JokeDate列的值置为当前日期。事实上,MySQL有很多这样的函数,但是我们只会在使用到他们时才会介绍他们,要得到一个完整的函数的说明,你可以参看MySQL参考手册。
----------------------------------------------------------------------------
7.  现在我们已经有了允许用户输入一个笑话并将其加入到我们的
数据库 中的 程序 代码。现在剩下的就是将其加入到我们已做好的笑话显示页面。因为绝大多数的用户只会想要看看笑话,所以我们不想对我们的页面做大的更改,除非用户表示想要添加一个新的笑话。因为这个原因,我们的应用 程序 应该是一个多功能的页面。下面是 程序 的代码:


<HTML>
...
<BODY>
<?
php
  // If the user wants to add a joke
  if (isset($addjoke)):
?>
<FORM ACTION="<?
php echo($PHP_SELF); ?>" METHOD=POST>
<P>Type your joke here:<BR>
<TEXTAREA NAME="joketext" ROWS=10 COLS=40 WRAP></TEXTAREA><BR>
<INPUT TYPE=SUBMIT NAME="submitjoke" VALUE="SUBMIT">
</FORM>

<?
php
  else:

    // Connect to the database server
    $dbcnx = @mysql_connect("localhost",
             "root", "mypasswd");
    if (!$dbcnx) {
      echo( "<P>Unable to connect to the " .
            "database server at this time.</P>" );
      exit();
    }

    // Select the jokes database
    if (! @mysql_select_db("jokes") ) {
      echo( "<P>Unable to locate the joke " .
            "database at this time.</P>" );
      exit();
    }

    // If a joke has been submitted,
    // add it to the database.
    if ("SUBMIT" == $submitjoke) {
      $sql = "INSERT INTO Jokes SET " .
             "JokeText='$joketext', " .
             "JokeDate=CURDATE()";
      if (mysql_query($sql)) {
        echo("<P>Your joke has been added.</P>");
      } else {
        echo("<P>Error adding submitted joke: " .
             mysql_error() . "</P>");
      }
    }
      echo("<P> Here are all the jokes " .
         "in our database: </P>");
      // Request the text of all the jokes
    $result = mysql_query(
              "SELECT JokeText FROM Jokes");
    if (!$result) {
      echo("<P>Error performing query: " .
           mysql_error() . "</P>");
      exit();
    }
      // Display the text of each joke in a paragraph
    while ( $row = mysql_fetch_array($result) ) {
      echo("<P>" . $row["JokeText"] . "</P>");
    }
    // When clicked, this link will load this page
    // with the joke submission form displayed.
    echo("<P><A HREF='$PHP_SELF?addjoke=1'>" .
         "Add a Joke!</A></P>");
    endif;
  ?>
</BODY>
</HTML>



  现在我们有了一个单独的文件,这个文件包含不太多的PHP代码,通过这个文件,我们可以显示我们的MySQL
数据库 中的笑话并能向我们的MySQL 数据库 中添加笑话。

一个挑战

  作为家庭作业,你可以看看你是不是能解决这么一个问题:在页面上显示的每一个笑话后面放置一个叫“Delete this Joke”的超连接,当单击这个连接时,会从
数据库 中删除这个笑话并显示更改过以后的笑话列表。下面是对你的一些提示:

  你可以还在一个多功能页面完成全部的功能。

  你需要使用SQL的DELETE命令,这个命令我们曾在第二章中学习过。

  这是一个关键的问题。要删除一个指定的
数据库 ,你需要能够唯一地标识它。Jokes表中的ID可以完成这个功能。你必须将要被删除的笑话的ID传递到删除笑话的请求中。将这个值放到“Delete this Joke”连接的查询字符串中是比较合适的。

  如果你觉得你已经有了答案,或者你只想知道解决方案,那就去看看下一页。祝你好运!

结语

  在这一章中,我们学习了一些新的用来实现与MySQL
数据库 服务接口的PHP函数。使用这些函数,我们建立了我们的第一个 数据库 驱动的 网站 ,我们的这个 网站 可以在线地发布我们 数据库 中笑话并允许访问者向其中添加他们自己的笑话。

  在第五章中,我们会回到MySQL命令行去学习如何使用关系型
数据库 的原理以及其他一些更高级的SQL查询去描述更为复杂的信息,并给予访问者对他们自己添加的笑话以特别的权限!

挑战的解决

  这是我们上面提出的“家庭作业”的解决方案。要在每一个笑话后面添加一个“Delete this Joke”连接,必须作下面的改动:

  之前,我们曾经在我们的页面的底端的“Add a Joke!”连接中传递过一个$addjoke变量,通过这个变量来通知我们的
脚本 不再显示通常的笑话列表,而是显示一个录入笑话的表单。与此相类似,我们在我们的“Delete this Joke”连接中传递一个$deletejoke变量来表示我们想要删除一个笑话。

  在获得每一个笑话的JokeText列的同时,我们还获得了ID列的值,所以我们获得了与
数据库 中每一个笑话关联的ID。

  我们将要删除的笑话的ID值赋予$deletejoke变量。这是通过将从
数据库 中获得的ID值插入到每一个笑话的“Delete this Joke”连接中来实现的。

  使用了一个if 语句,如果在载入这一页时,我们的$deletejoke被赋予了一个值(使用isset函数),我们会在一个SQLDELETE语句中使用这个值(将被删除的笑话的ID)来删除指定的笑话。

  这儿是全部的源代码:


<HTML>
...
<BODY>
<?
php
  // If the user wants to add a joke
  if (isset($addjoke)):
?>

<FORM ACTION="<?
php echo($PHP_SELF); ?>" METHOD=POST>
<P>Type your joke here:<BR>
<TEXTAREA NAME="joketext" ROWS=10 COLS=40 WRAP></TEXTAREA><BR>
<INPUT TYPE=SUBMIT NAME="submitjoke" VALUE="SUBMIT">
</FORM>
<?
php
  else:

    // Connect to the database server
    $dbcnx = @mysql_connect(
               "localhost", "root", "mypasswd");
    if (!$dbcnx) {
      echo( "<P>Unable to connect to the " .
            "database server at this time.</P>" );
      exit();
    }

    // Select the jokes database
    if (! @mysql_select_db("jokes") ) {
      echo( "<P>Unable to locate the joke " .
            "database at this time.</P>" );
      exit();
    }
    // If a joke has been submitted,
    // add it to the database.
    if ("SUBMIT" == $submitjoke) {
      $sql = "INSERT INTO Jokes SET " .
             "JokeText='$joketext', " .
             "JokeDate=CURDATE()";
      if (mysql_query($sql)) {
        echo("<P>Your joke has been added.</P>");
      } else {
        echo("<P>Error adding submitted joke: " .
             mysql_error() . "</P>");
      }
    }

    // If a joke has been deleted,
    // remove it from the database.
    if (isset($deletejoke)) {
      $sql = "DELETE FROM Jokes " .
             "WHERE ID=$deletejoke";
      if (mysql_query($sql)) {
        echo("<P>The joke has been deleted.</P>");
      } else {
        echo("<P>Error deleting joke: " .
             mysql_error() . "</P>");
      }
    }
      echo("<P> Here are all the jokes " .
         "in our database: </P>");
      // Request the ID and text of all the jokes
    $result = mysql_query(
                "SELECT ID, JokeText FROM Jokes");
    if (!$result) {
      echo("<P>Error performing query: " .
           mysql_error() . "</P>");
      exit();
    }
    // Display the text of each joke in a paragraph
    // with a "Delete this Joke" link next to each.
   while ( $row = mysql_fetch_array($result) ) {
      $jokeid = $row["ID"];
      $joketext = $row["JokeText"];
      echo("<P>$joketext " .
           "<A HREF='$PHP_SELF?deletejoke=$jokeid'>" .
           "Delete this Joke</A></P>");
    }
    // When clicked, this link will load this page
    // with the joke submission form displayed.
    echo("<P><A HREF='$PHP_SELF?addjoke=1'>" .
         "Add a Joke!</A></P>");
    endif;
  ?>
</BODY>
</HTML>
---------------------------------------------------------------------------------
8.  在这一章中,我们会对我们的例子进行扩充,学习一些有关MySQL的新知识,并试图理解并掌握关系型
数据库 所能提供的功能。
第五章:关系型
数据库 设计

  在这篇文章的第二章中,我们已经建立了一个供我们使用的非常简单的笑话
数据库 ,这个库中只包括了一个名叫Jokes的数据表。这作为我们使用MySQL 数据库 的入门已经是足够了,但是在关系型 数据库 的设计中还有很多其它的东西。在这一章中,我们会对我们的例子进行扩充,学习一些有关MySQL的新知识,并试图理解并掌握关系型 数据库 所能提供的功能。

  首先,我们得说明我们对许多问题的解决只是不正规的(也就是说非正式的)。正如你在许多计算机科学专业中了解的那样,
数据库 设计是一个严肃的领域, 数据库 设计必须包括对它的测试并会涉及到一些数学的原理。但这些可能是超过我们这篇文章的范围了。要得到更多的信息,你可以停下来到http://www.datamodel.org/去看看,在那儿你可以看到许多好的书籍,并得到一些关于这个问题的有用的资源。

给予应有的权限

  在开始之前,让我们回忆一下我们的Jokes数据表的结构,这个表包含三个列:ID、JokeText和 JokeDate。这些列可以使我们标识笑话(ID),明了他们的内容(JokeText)以及他们被加入的时间(JokeDate)。

  现在我们想要保存我们的笑话中的其它一些信息:提交者的姓名。这看上去很自然,我们需要在我们的Jokes数据表中添加一个新的列。SQL的ALTER命令(我们在之前没看到过这个命令)可以帮助我们完成这件事。使用mysql命令行
程序 登录到MySQL服务器,选择你的 数据库 (如果你使用我们在第二章中的命名, 数据库 名应该是joke),然后输入下面的命令:

mysql>
ALTER TABLE Jokes ADD COLUMN
    -> AuthorName VARCHAR(100);



  这将会在我们的数据表中增加一个叫AuthorName的列。其数据类型是一个可变长度的字符串,其最大长度是100个字符(这对于最复杂的名字应该也是足够了)。让我们再添加一列用来保存作者的e-mail地址:


mysql> ALTER TABLE Jokes ADD COLUMN
    -> AuthorEMail VARCHAR(100);



  要得到更多的有关ALTER命令的信息,请参看MySQL参考手册。要确认我们是不是正确地添加了两列,你可以要求MySQL为我们对这个表进行描述:


mysql> DESCRIBE Jokes;
+-------------+--------------+------+-----+-- - -
| Field | Type | Null | Key | Def...
+-------------+--------------+------+-----+-- - -
| ID | int(11) | | PRI | ...
| JokeText | text | YES | | ...
| JokeDate | date | | | ...
| AuthorName | varchar(100) | YES | | ...
| AuthorEMail | varchar(100) | YES | | ...
+-------------+--------------+------+-----+-- - -
5 rows in set (0.01 sec)



  看上去很不错。明显地,我们需要对我们在第四章中建立的添加新笑话的HTML以及PHP格式的代码进行调整,但是我们会把这留给你作为一个练习。使用UPDATE查询,你现在可以对表中的所有笑话添加作者的详细资料。然而,在你开始接受这个数据结构之前,我们必须考虑一下我们在这儿选择的设计是否确当。在这种情况下,我们会发现一些我们还没有做到的事情。

一个基本的规则:保持事物的分离

  在你建立
数据库 驱动的 网站 的过程中,你已经觉得仅仅是有一个笑话列表是不够的。事实上,除了你自己的笑话以外,你开始接收其他人提交的笑话。你决定做一个让全世界人都可以共享笑话的 网站 。你有没有听说过Internet电影 数据库 (IMDB)?实际上你现在做的是Internet笑话 数据库 (IJDB)!对每一个笑话添加作者的姓名和e-mail地址肯定是最容易想到的办法,但是这种方法会导致一些潜在的问题:

  如果一个经常投稿的名叫Joan Smith的人改变了她的e-mail地址将会发生什么什么情况呢?她会开始使用新地址来提交新的笑话,但是对于所有的旧笑话,你所能看到的还是旧的地址。从你的
数据库 来看,你也许只能认为有两人名字都叫Joan Smith的人在向你的 数据库 中提交笑话。如果她是特别体贴的,她也许会通知你改变地址,你可以将所有的旧笑话改成新的地址,但是如果你遗漏了一个,那就意味着你的 数据库 中存储了错误的信息。 数据库 设计专家将这种类型的问题称之为一个“更正异常”。

  很自然地你会想到从你的
数据库 中得到所有曾经向你的站点提交过笑话的人的列表。实际上,你可以使用下面的查询很容易地得到这样的列表:

mysql> SELECT DISTINCT AuthorName, AuthorEMail -> FROM Jokes;


  上面查询中DISTINCT是告诉MySQL不输出重复的结果行。例如,如果Joan Smith向我们的站点提交过20个笑话,如果我们使用了DISTINCT选项,她的名字和e-mail地址将会只在列表中出现一次,否则会出现20次。

  如果因为某种原因,你决定要从
数据库 中删除某个特定的作者所提交的所有笑话,但是,与此同时,你将不能再通过e-mail与他们联系!而你的e-mail清单可能是你的 网站 的收入的主要来源,所以你并不想只因为你不喜欢他们提交的笑话,就删除他们的e-mail地址。 数据库 设计专家将这称之为“删除异常”。

  你并不能保证不会出现这样的情况:Joan Smith输入的姓名一会儿是“Joan Smith”,一会儿是“J. Smith”,一会儿又是“Smith, Joan”。这将使得你要确定一个特定的作者变得非常困难(特别是Joan Smith又经常使用几个不同的email地址的时候)。

  这些问题的解决其实很简单。只要你不再将作者的信息存储到Jokes数据表中,而是建立一个新的数据表来存储作者列表。因为我们在Jokes数据表中使用了一个叫ID的列来用一个数据标识每个笑话,所以我们在新的数据表中使用了同样名字的列来标识我们的作者。我们可以在我们的Jokes表中使用“author ID's”来建立笑话和他的作者之间的关联。全部的
数据库 设计应该是这样的:

  上面的两个表包含了三个笑话和两个作者。Jokes表的AID列(“Author ID”的缩写)提供了两个表之间的关联(指出Kevin Yank 提交了笑话1和笑话2,Joan Smith提交了笑话3)。在这里,你还需要注意到每一个作者只会在
数据库 中出现一次,而且他们是独立于他们提交的笑话而存在的,因此我们已经解决了我们上面提出的那些问题。

  这个
数据库 设计的最重要的特征是,因为我们要存储两种类型的事物(笑话和作者),所以我们设计两个表。这是我们在 数据库 设计中要遵守的一个基本规则:对于每一个要存储其信息的实体(或事物),我们都应该给他一个自己的表。

  重新生成上面的数据是非常简单的(只要使用两个CREATE TABLE 查询就行了),但是因为我们想要在做这些变动时不会有破坏性的效果(也就是说不会丢失我们已经存入的笑话),所以我们需要再次使用ALTER命令。 首先,我们删除Jokes表中有关作者的列:


mysql> ALTER TABLE Jokes DROP COLUMN AuthorName;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE Jokes DROP COLUMN AuthorEMail;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
    现在我们建立我们的新的数据表:
mysql> CREATE TABLE Authors (
    -> ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> Name VARCHAR(100),
    -> EMail VARCHAR(100)
    -> );
    最后,我们在我们的Jokes表中添加AID列:
mysql> ALTER TABLE Jokes ADD COLUMN AID INT;



  现在剩下来的就是向新的表中添加一些作者,并通过填充AID列来对
数据库 中已经存在的笑话指定作者。

处理多个表

  现在我们的数据被分布在两个表当中,要从其中获得数据看上去变得更加复杂了。例如,我们最初的目标是:显示一个笑话的列表并在每一个笑话后面显示作者的姓名和e-mail地址。在我们的单表结构中,要获得所有的信息,只需要在我们的PHP代码中使用一个SELECT语句就行了:


$jokelist = mysql_query(
  "SELECT JokeText, AuthorName, AuthorEMail ".
  "FROM Jokes");

while ($joke = mysql_fetch_array($jokelist)) {
  $joketext = $joke["JokeText"];
  $name = $joke["AuthorName"];
  $email = $joke["AuthorEMail"];

  // Display the joke with author information
  echo( "<P>$joketext<BR>" .
        "(by <HREF='mailto:$email'>$name)</P>" );
}



  在我们的新
系统 中,这样做初看起来是不可能了。因为有关每个笑话的作者的详细资料不是存储在Jokes表中,我们可能想到的一个解决方案是我们对于我们想要显示的笑话单独地获得这些资料。代码将是这样的:


// Get the list of jokes
$jokelist = mysql_query(
  "SELECT JokeText, AID FROM Jokes");

while ($joke = mysql_fetch_array($jokelist)) {

  // Get the text and Author ID for the joke
  $joketext = $joke["JokeText"];
  $aid = $joke["AID"];
  // Get the author details for the joke
  $authordetails = mysql_query(
    "SELECT Name, Email FROM Authors WHERE ID=$aid");
  $author = mysql_fetch_array($authordetails);
  $name = $author["Name"];
  $email = $author["EMail"];

  // Display the joke with author information
  echo( "<P>$joketext<BR>" .
        "(by <A HREF='mailto:$email'>$name)</P>" );
}



  很混乱,而且对于每一个显示的笑话都包含了一个对
数据库 的查询,这将会我们的页面的显示非常缓慢。现在看来,“老方法”可能是更好的解决方案,尽管它有其自身的弱点。

  幸运的是,关系型
数据库 可以很容易地处理多个表中的数据!在SELECT语句中使用一个新的被称之为“join”的格式,我们可以找到两全其美的办法。连接可以使我们象对存储在单个表中的数据那样对待多个表中的关联数据。一个连接的格式应该是这样的:


mysql> SELECT <columns> FROM <tables>
    -> WHERE <condition(s) for data to be related>
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值