【php精品源码栏目提醒】:网学会员php精品源码为您提供【精品】php注册及登录模块 - 其它资料参考,解决您在【精品】php注册及登录模块 - 其它资料学习中工作中的难题,参考学习。
PHP 注册及登录验证模块设计本文来自谈笑涧 163 博客所谓“人过留名,雁过留声”,几乎每个动态交互式的网站都有一个注册模块用来保存用户信息,并提供一个登录模块以供注册用户登录。
本章将建立一个注册程序,以实现用户的登录和注册。
通过本章的学习,读者将了解:— 如何建立 HTML 表单;—
PHP 如何获取用户填写的信息;— 如何建立
PHP 与 MySQL 数据库的连接;— 如何使用
PHP 往数据库添加记录及如何在数据库中查找记录;— 如何使用 JavaScript 脚本语言在客户端编程;— 如何使用正则表达式进行数据验证;—
PHP 如何使用 Session 来记住用户的登录信息;— 数据库处理错误的调试方法。
通过本章的学习,读者将对
PHP 网络编程有一个总体性的认识,为以后章节的学习打下良好的基础。
2.1 建立用户信息表网站的开发是一个以数据为中心的开发过程,所以数据库的设计非常重要,在进行编程之前一定要做好需求分析和数据库设计。
本例将在 MySQL 安装时自动建立的 test 数据库中建立一张名为 t_user 的用户信息表。
t_user 的表结构如表 2-1 所示。
表 2-1 表 t_user 的结构列 名 数 据 类 型 长 度 允 许 空 默 认 值 字 段 说 明f_username char 50 否 无 用户名,主键f_password char 50 否 无 用户密码f_name char 50 否 无 用户姓名f_email char 50 否 无 用户 E-mail 地址f_logintimes int 4 否 0 登录次数f_lasttime datetime 8 是 最后登录时间f_loginip char 19 是 最后登录 IP在编程开发中,程序员的代码应当是自注释的,也就是代码能够向阅读者传达出自身作用的信息,额外的说明语句需要但不宜太多,否则会降低代码的可读性。
在编 程开发中,为每一个对象选择一个合适的名称是非常重要的,在进行数据库设计时为每张表及每个字段合适地命名也很重要。
给表名和字段名提供一个合适的前缀可 以显著提高代码的可读性,笔者就喜欢给表名加上前缀“t_”,为字段名加上前缀“f_”。
很多开发者可能会为用户信息表添加一个 int 型自动增量字段(如 f_uid)作为主键,但笔者认为这样做是弊大于利、得不偿失的。
一来造成空间的浪费,二 来时间效率上也有所降低。
因为在实际开发过程中用户名是使用得最为频繁的查询条件,而众所周知在主键上进行的查询,其速度是最快的;使用自动增量字段为主 键的话,在用户名作为条件的查询上则要先根据用户名查找到 f_uid,再根据 f_uid 去查找所要的信息。
无疑,这是一个吃力不讨好的选择。
另外,很多熟悉其他类型数据库的开发者转而使用 MySQL 时仍喜欢使用 Varchar 类型的字段。
其实如果空间不是非常紧张的话,在 MySQL 中一 般情况下 Char 类型是更好的选择。
一是 Char 型字段时间效率高,二是两者长度范围都在 255 个字符以内,空间上损失不会太大,再者在取出 Char 型字 段数据时,数据库会自动丢弃多余的空格,因此使用上两者一样方便。
2.2 为注册建立 HTML 表单能够用于网页设计的工具有很多,从简单的 Windows 自带的记事本、写字板到号称网页三剑客之一的Macromedia 公司出品的 Dreamweaver 都可以使用,这完全取决于开发人员的爱好。
不过如果读者正在使用所见即所得的网页设计工具,而又有志成为一名专业的网络编程人员的 话,笔者还是建议读者放弃这些工具,因为这些工具有一个统一的毛病就是把 HTML 代码排列得乱七八糟,极大地降低了代码的可读性;另外也会使开发人员对工 具产生依赖性而不去记基本的 HTML 标签的使用。
其实,HTML 是极其简单的一门语言,标签数也不多,用心的话很快就能掌握。
笔者一向比较喜欢 UltraEdit,有兴趣的读者可以试用。
注册页面的代码如下,输入这些内容并将其保存为 register.
php。
lthtmlgtltheadgtltmeta http-equivquotContent-Typequot contentquottext/html charsetgb2312quotgtlttitlegtRegistering formlt/titlegtlt/headgtltbodygtltform namequotfrmRegisterquot methodquotpostquot actionquotregister.phpquotgtlttable widthquot330quot borderquot0quot alignquotcenterquot cellpaddingquot5quot bgcolor quoteeeeeequotgtlttrgt lttd widthquot40quotgt用户名:lt/tdgt lttdgtltinput namequotusernamequot typequottextquot idquotusernamequotgt lt/tdgtlt/trgtlttrgt lttdgt密码:lt/tdgt lttdgtltinput namequotpwdquot typequotpasswordquot idquotpwdquotgtlt/tdgtlt/trgtlttrgt lttdgt重复密码:lt/tdgt lttdgtltinput namequotrepeat_pwdquot typequotpasswordquot idquotrepeat_pwdquotgtlt/tdgtlt/trgtlttrgt tinput namequotnamequot typequottextquot idquotnamequotgtlt/tdgtlt/trgtlttrgt lttdgtEmail:lt/tdgt lttdgtltinput namequotemailquot typequottextquot idquotemailquotgtlt/tdgtlt/trgtlttrgt lttd colspanquot2quot alignquotcenterquotgt ltinput typequotsubmitquot namequotSubmitquot valuequot提交quotgt ltinput typequotresetquot namequotresetquot valuequot重置quotgtlt/tdgtlt/trgtlt/tablegtlt/formgtlt/bodygtlt/htmlgt注意以上这段代码中以粗体标出的部分,其中“charsetgb2312”告诉浏览器本页使用 gb2312 编码(即简体中文)来显示文本内容,而使用标签括起来的这一部分就是 HTML 表单的内容。
标签的 name 属性用以指出表单的名称,以便客户端编程时引用表单内容;method 属性指出表单内的数据 将以何种方式提交到服务器端,常用的提交方式有两种,一种是 get 方式,另一种就是本例中使用的 post 方式,默认的是 get 方式,这两种方式的区别后面 会给出详细讲述;action 属性指出表单内的数据将提交给谁来处理,本例中的 actionquotregister. phpquot即指出表单内的数据将提交给 register.
php 文件,也就是说表单所在的文件本身将处理这些数据。
用户注册界面如图 2-1 所示。
列 名 数 据 类 型 长 度 允 许 空 默 认 值 字 段 说 明f_username char 50 否 无 用户名,主键f_password char 50 否 无 用户密码f_name char 50 否 无 用户姓名f_email char 50 否 无 用户 E-mail 地址f_logintimes int 4 否 0 登录次数f_lasttime datetime 8 是 最后登录时间f_loginip char 19 是 最后登录 IP在网页设计中,标签往往不像其字面意思那样用来制作一张表格,而是作为定位的工具,这时就要将其border 属性设为 0,也就是让表格不显示边框。
标签的 align 属性也很有用,其作用是指明排列方式,有 3个值可取:left,center 和 right,它们的意思很显然,勿庸赘述。
另外,标签也具 有这个属性,意义一样,而且更为常用。
2.3 处理注册数据本节将详细介绍
PHP 如何获取用户填写的数据信息,以及
PHP 如何连接数据库并将这些数据信息保存到数据库中。
2.3.1 获取用户填写的信息
PHP 有几个预定义的自动全局变量,这些变量各有用途,其中可以用来获取客户端提交的数据的变量有_REQUEST,_GET 和_POST。
_GET 和_POST 分别用以获取客户端以 get 方式和以 post 方式提交的数据;而不管以什么方式提交上来的数据,_REQUEST 都可以取到。
PHP 中的全局变量在使用之前必须以 global 关键字进行声明,很多开发人员在使用全局变量时经常会因为忘了将其声明为 global 而出错。
然而
PHP 的自动全局变量却是个例外,所谓自动,就是说在使用之前无须声明为 global,直接就可以使用。
还有一种其他
PHP 书籍介绍的获取客户端提交的数据的方式,即自动获取。
该方式必须打开
php.ini 中的register_globals 选项方能使用,而且更重要的是,在安全性上会给黑客以可乘之机,所以不推荐使用这种方式。
现在开始书写获取用户信息数据的代码,打开上一节建立的 register.
php 文件。
在文件的开始输入以下代码(输入时注意文本的对齐,这是优良代码风格的体现):ltphpusername _POSTusernamepwd _POSTpwdrepeat_pwd _POSTrepeat_pwdname _POSTnameemail _POSTemailgt接下来,在ltbodygt标签之后,ltformgt标签之前输入以下代码:ltphpif emptyusername // 有内容才输出 echo quot您填写的信息是:ltbrgtnquot echo quot用户名: username ltbrgtnquot echo quot密码: pwd ltbrgtnquot echo quot重复密码: repeat_pwd ltbrgtnquot echo quot姓名: name ltbrgtnquot echo quotEmail: email ltbrgtnquotgt这就是获取客户端提交的用户信息的全部代码。
运行后,在表单中输入各项信息并单击“提交”按钮,最后页面内容如图 2-2 所示。
图 2-2 获取用户信息后的页面
PHP 中的字符串有两种定界符,即单引号“”和双引号“quot”。
单引号是强引用定界符,两个单引号间的一切字符都被解释为相应的字符;双引号是弱引 用定界符,两个双引号间的变量会以相应的变量值替换,一些特殊的字符也会进行相应的转义,如“n”会在输出时产生一个新行。
另外,读者注意“n”只是 使
PHP 运行后产生的 HTML 源代码的相应位置启动一个新行,而标签ltbrgt将使得浏览器显示的页面的相应位置启动一个新行。
初学网页编程的 开发者,尤其是 C 语言开发者,易混淆二者。
2.3.2 建立
PHP 与 MySQL 数据库的连接获取到用户输入的信息后,就该把这些信息记录到数据库中。
不过在此之前,需要先建立
PHP 与 MySQL数据库的连接。
在
PHP 中要建立与 MySQL 数据库的连接,需要使用 mysqli 构造函数,其调用原型是:class mysqli __construct string host string username string passwd string dbname int port stringsocket 参数 host 指出 MySQL 数据库服务器,一般用 IP 地址(也可以是主机名,如 localhost)指出服务器所在的机器。
参数 username 和 password 分别指定连接时使用的用户名和密码。
参数 dbname 指定当前连接要使用的数据库。
默认情况下,
PHP 将连接到服务器的 3306 端口,开 发人员可以通过参数 port 指定使用其他的端口号。
参数 socket 较为少用,它可以进一步指定所用的套接字或命名管道。
在调用 mysqli 构造函数之后,应当调用 mysqli_connect_errno函数检查数据库连接是否建立成功,该函数原型是:int mysqli_connect_errno void 该函数返回的是最后一次建立连接时产生的错误代码,如果成功则返回 0,返回其他值说明产生了某种类型的错误。
调用 mysqli_connect_error函数可以获得具体的错误信息。
另外,如果在建立数据库连接时没有指定 dbname 参数,则还必须调用类 mysqli 的成员函数 select_db,以指定使用数据库服务器的哪一个数据库。
该函数的原型是:bool select_db string database_name调用如果成功返回 TRUE,失败返回 FALSE。
参数 database_name 指定要使用的数据库名称。
当操作完数据库后,还要调用类 mysqli 的成员函数 close来关闭之前打开的数据库连接,从而释放连接资源。
虽然在
PHP 脚本执行完毕时,
PHP 会自动关闭数据库连接,但是及时关闭数据库连接是一个更好的编程习惯。
本例中,连接并使用数据库的代码如下:// 调用 mysqli 的构造函数建立连接,同时选择使用数据库testdb new mysqliquot127.0.0.1quot quotdeveloperquot quot123456quot quottestquot// 检查数据库连接if mysqli_connect_errno echo quot数据库连接失败ltbrgtnquot echo mysqli_connect_error exit // 退出程序,后面的所有语句将不再执行printfquotHost information: s ltbr/gtltbr/gtnquot db-gthost_info//...... 一些操作数据库数据的语句// 关闭数据库连接db-gtclose到此为止,就已经建立好了一个操作数据库的
PHP 程序框架。
应当说明的是,
PHP5 的 MySQL 库提供了两套操作数据库的方法,一种是面向对象方式的,另一种是面向过程方式的。
面向对象的方法是较先进的也是本书主要使用的方法。
这两种方式使用时的区别在于,面向对象方式调用的是类 mysqli 的成员函数,要使用类变量来调用,而不需要另外指定数据库连接资源;面向过程方式 调用的是全局函数,要多指定一个数据库连接资源的参数。
另外这两者除了连接数据库的方法外,其他功能的函数名是对应的,差别在于面向对象方式的成员函数没有“mysqli_”前缀。
如面向对象方法使用db-gtselect_dbstring dbname来指定数据库,而面向过程方法使用mysqli_select_db mysqli link string dbname来指定数据库(注意,粗体部分标出了二者的区别)。
面向过程方法的函数中的参数 mysqli link 通过 mysqli_connect函数调用来获得,该函数的参数与 mysqli 的构造函数的参数完全相同;不同的是, mysqli_connect成功时返回连接资源,失败时返回布尔值 FALSE。
使用面向过程的方法连接数据库的例子参见第 1 章的 1.3.3 节。
注意:
PHP5 之前的版本只支持面向过程的数据库操作方法。
如果用同样的参数第二次调用 mysqli_connect,将不会建立新连接,而是返回已经打开的连接标识。
2.3.3 将用户信息记录到数据库上一节已经建立了一个操作数据库的程序框架,本节具体介绍如何把数据添加到数据库中。
这涉及
PHP 中MySQL 数据库编程最重要也是使用最频繁的一个函数:query。
其原型是:mixed query string query int resultmode 该函数向当前活动数据库发送一条查询语句。
参数 query 指定要执行的查询语句。
参数 resultmode 有两个可能值: MYSQLI_USE_RESULT 和 MYSQLI_STORE_RESULT,默认为 MYSQLI_STORE_RESULT。
如果指定了 MYSQLI_USE_RESULT,则在执行下一条查询前必须调用 mysqli_result 类的 free或 close函数释放查询结果对象, 否则查询将失败。
一般在执行的会返回大量数据的查询语句时指定MYSQLI_USE_RESULT,其他情况都应使用 MYSQLI_STORE_RESULT。
如果执行的是 SELECT,SHOW,DESCRIBE 或 EXPLAIN 语句,query函数执行成功将返回一个结果对象; 如 如果执行的是其他查 询语句, INSERT,DELETE,UPDATE 等,query函数执行成功则返回 TRUE。
无论执行什么查询语句,query函数失败时都 将返回布尔值 false。
下面就使用 query函数把前面用自动全局变量_POST 获取到的用户信息添加到数据库中去,代码如下:sql quotINSERT INTO t_user f_username f_password f_name f_email VALUESquotsql . quotusername pwd name emailquotecho sqlrs db-gtquerysqlvar_dumprsif rs db-gtclose // 关闭数据库连接 echo 数据记录插入失败 exit到此为止,已经制作好 HTML 注册表单,也能够获取到提交给
PHP 的用户信息,而且建立好了数据库连接并将这些用户信息记录到数据库。
现在来整理一下代码,register.
php 文件的内容应当如下所示:ltphpusername _POSTusernamepwd _POSTpwdrepeat_pwd _POSTrepeat_pwdname _POSTnameemail _POSTemailif emptyusername // 用户填写了数据才执行数据库操作 // 调用 mysqli 的构造函数建立连接,同时选择使用数据库test db new mysqliquot127.0.0.1quot quotdeveloperquot quot123456quot quottestquot // 检查数据库连接 if mysqli_connect_errno echo quot数据库连接失败ltbrgtnquot echo mysqli_connect_error exit // 退出程序,后面的所有语句将不再执行 // 将用户信息插入数据库的 t_user 表 sql quotINSERT INTO t_user f_username f_password f_name f_email VALUESquot sql . quotusername pwd name emailquot rs db-gtquerysql if rs db-gtclose // 关闭数据库连接 echo 数据记录插入失败 exit echo quotltfont colorred size5gt恭喜您注册成功lt/fontgtltbrgtnquot // 关闭数据库连接 db-gtclosegtlthtmlgtltheadgtltmeta http-equivquotContent-Typequot contentquottext/html charsetgb2312quotgtlttitlegtRegistering formlt/titlegtlt/headgtltbodygtltphpif emptyusername echo quot您填写的信息是:ltbrgtnquot echo quot用户名: username ltbrgtnquot echo quot密码: pwd ltbrgtnquot echo quot重复密码: repeat_pwd ltbrgtnquot echo quot姓名: name ltbrgtnquot echo quotEmail: email ltbrgtnquotgtltform namequotfrmRegisterquot methodquotpostquot actionquotregister.phpquotgtlttable widthquot330quot borderquot0quot alignquotcenterquot cellpaddingquot5quot bgcolor quoteeeeeequotgtlttrgt lttd widthquot40quotgt用户名:lt/tdgt lttdgtltinput namequotusernamequot typequottextquot idquotusernamequotgt lt/tdgtlt/trgtlttrgt lttdgt密码:lt/tdgt lttdgtltinput namequotpwdquot typequotpasswordquot idquotpwdquotgtlt/tdgtlt/trgtlttrgt lttdgt重复密码:lt/tdgt lttdgtltinput namequotrepeat_pwdquot typequotpasswordquot idquotrepeat_pwdquotgtlt/tdgtlt/trgtlttrgt lttdgtlttdgtltinput namequotnamequot typequottextquot idquotnamequotgtlt/tdgtlt/trgtlttrgt lttdgtEmail:lt/tdgt lttdgtltinput namequotemailquot typequottextquot idquotemailquotgtlt/tdgtlt/trgtlttrgt lttd colspanquot2quot alignquotcenterquotgt ltinput typequotsubmitquot namequotSubmitquot valuequot提交quotgt ltinput typequotresetquot namequotresetquot valuequot重置quotgtlt/tdgtlt/trgtlt/tablegtlt/formgtlt/bodygtlt/htmlgt需要说明的是,在上面的代码中,使用了 if emptyusername来确保当有数据提交上来时才执行数据库操作。
这样做的原因是,在进行
PHP 网络编程时,HTML 表单内填写的数据 往往是提交给表单所在的
PHP文件本身来处理的。
而第一次运行该
PHP 文件时服务器上是获取不到任何数据的,只有当用户填写完表单并提交之后第二次运行该
PHP 文件时,才能获取到用户填写的数据。
最后,运行程序。
在浏览器中打开 register.
php,然后在表单中输入适当的数据,如图 2-3 所示。
单击“提交”按钮,结果如图 2-4 所示。
图 2-3 填写好的注册表单 图 2-4 注册成功的页面如上述程序清单所示,整个程序是比较短小整洁的。
在此回想一下代码的编写步骤和程序运行流程,将会有更大收获。
细心的读者可能已经发现,HTML 注册表单上“重复密码”输入框的值在以上代码中一直没派上用场,而且Email 随便输入都可以注册,这显然是不合理的。
下一节的数据有效性验证的内容就是为解决这个问题的。
为了使得整个
PHP 文件整洁、易读,所有服务器端的代码,除了输出语句(如 echo 语句)外,都应当放在所有的 HTML 代码的前面,即文件的开始 处。
这样做还有另外一个原因,有些
PHP 语句必须在任何输出语句之前执行,否则就会出错,而每一条 HTML 代码都相当于一条
PHP 的输出语句.2.4 客户端的数据有效性验证数据有效性验证既可以放在客户端进行也可以放在服务器端进行,或者在两边同时进行。
一般来说,为了系统的安全,服务器端的有效性验证是必须的,而客户端的 验证则可有可无。
但是,在客户端进行有效性验证有很大好处,因为它在将数据提交给服务器之前就可以排除很多的输入错误,从而减少网络流量,减轻了服务器的 负担,也加快了验证的速度,提升了系统的性能。
2.4.1 指点迷津——JavaScript 编程在客户端进行数据有效性验证需要使用客户端的脚本语言进行编程,通常有 VBScript,JavaScript 和 JScript可以选用,在功能上 JavaScript 基本是 JScript 的一个子集,选择何者视开发人员的习惯。
但需要注意的是,因为 VBScript 和 JScript 只有 IE 浏览器 支持,如果希望其他浏览器也能支持客户端脚本,最好选用JavaScript。
注意:JavaScript 是区分大、小写字母的。
回顾一下,在第 1 章的“第一个
PHP 程序中”有一段 JavaScript 脚本,在此单独摘录,如下代码中粗体部分所示。
ltheadgtltMETA HTTP-EQUIVquotContent-Typequot CONTENTquottext/html charsetgb2312quot /gtlttitlegt第一个
PHP 程序lt/titlegtlt—-以.