简单PHP+MySQL数据库动态⽹站制作--摘抄
在这篇⽂章中,我尽量⽤最浅显易懂的语⾔来说明使⽤ PHP, MySQL 制作⼀个动态⽹站的基本技术。阅读本⽂需要简单的 HTML 基础知识和(任⼀编程语⾔的)编程基础知识(例如变量、值、循环、语句块的概念等)。
PHP 基础
概述
PHP 是⼀种解释性语⾔,可⽤于对⽹页进⾏预处理。PHP 脚本在服务器端运⾏,其运⾏结果是⼀个可⽤来显⽰的⽹页。尽管可以完成许多类似⼯作,但是JavaScript 和 PHP 的⼀⼤区别就是,JavaScript 是在浏览器端运⾏的。事实上,浏览器会接收 JavaScript 代码并运⾏它,所以⽤户是可以查看 JavaScript 代码的。⽽ PHP 不会将原始代码交给浏览器,只会将其运⾏的结果交给浏览器,所以⽤ PHP 处理⽤户登陆、⽤户权限等问题是安全可靠的。
PHP 与 HTML
实际编写的时候,通常采⽤的⽅式是建⽴扩展名为 php 的⽂件(⽹页⽂件本质上是⽂本⽂件)。编写 php 代码和编写 html 代码并没有多少区别,⽽最⽅便的地⽅在于,在⼀个 php ⽂件中,两种代码是可
以混编的。
规则:php 代码需要包含在 <?php ... ?> 标签中,就像这样:
<?php
// code goes here
>
提⽰:这是⼀个 php 和 html 混编的较为⽣动的例⼦。
<?php
if ($var == true):
>
<html id="ie6">
<?php
else:
>
<html id="ie8">
<?php
endif;
>
这⾥的意思是,如果 php 中的变量 $var 的值为 true,则放置⼀个标签,否则放置另⼀个标签。PHP 的 if 语句可以像上⾯那样写,也可以写成C/C++风格的:<?php
if ($var == true) {
// do something
} else {
// do other things
}
>
关于 PHP 中的操作符
PHP 采⽤的操作符和 C/C++ 是类似的,例如⽤ = 表⽰赋值,== 表⽰相等性⽐较,以及 < 和 > (⼩于、⼤于)⽐较符、! 取反、&&逻辑与、||逻辑或等。当然,也⽀持 +-*/ 等数学表达式的运算。
关于 PHP 中的变量
PHP 中变量的命名⼀律以符号 $ 开头,可以使⽤下划线,例如 $is_logged_in 就是⼀个表意清晰的变量名。和⼤多数编程语⾔不同,PHP 中变量没有类型的概念,⽽且不⽤声明就可以直接使⽤。虽然很爽,但是变量多了的时候也容易混乱,这⼀点需要特别注意。
关于 PHP 中的语句
这⼀点 PHP 和许多其他常见的编程语⾔很类似,也可以⽤ if...else 选择语句(之前已经见过了),PHP 还包括 while 循环、foreach 循环等,以后遇到了会详细介绍。
MySQL 基础
使⽤ MySQL 数据库是存储数据的⼀种⽅法,MySQL 需要和 PHP 配合来完成对数据库的查询(这⾥术语“查询”包括写⼊、更新、读取等)操作。利⽤MySQL,你可以创建许多数据库(database),每个数据库可以包含多个表(table),⽽每个表包含若⼲字段。为了⾼效,⼀般会采取分类维护多个表的⽅式,⽽不是把所有数据都储存在同⼀个表中。
MySQL 需要服务器⽀持。使⽤的第⼀步是建⽴⼀个数据库,可以⽤相应的图形化⼯具(例如 phpMyAdmin)来建⽴数据库,也可以在终端直接使⽤下列 SQL 语句来创建⼀个名为 database_name 的数据库:
CREATE DATABASE database_name;
创建好数据库之后,需要创建表。可以通过下列 SQL 语句来创建⼀个名为 table_name 的表:
USE database_name;
CREATE TABLE table_name (
first_name varchar(30),
last_name varchar(30),
);
第⼀句说明在哪个数据库中添加表,第⼆个说明添加的表的详情。这⾥我们在表中添加了两个字段,分别叫做 first_name 和 last_name,它们的类型
是 varchar(30)。其中 varchar 是⼀种可变长字符类型,⽽ 30 代表了最⼤长度。
其他常见的数据类型如下:
VARCHAR(100) --可变字符
CHARACTER(1) --定长
INTEGER--整数
DECIMAL(10, 2) --⼩数(⼩数点前后的位数)
TIMESTAMP--⽇期和时间
DATE --⽇期
你可能已经看出来了,MySQL 的注释符为 --。你可能觉得没太⼤⽤,但是它却是⼀种稍后要提到的攻击的关键之处。此外,⼀般字符串都应该使⽤变长
的VARCHAR类型,⽽⾮定长的CHARACTER类型,因为后者会占据更多的空间,⽽这是不必要的。
使 PHP 和 MySQL 协作
第⼀种⽅式
现在你已经创建好了 SQL 数据表,并对 PHP 语⾔有了⼀个概览。下⾯我们直奔主题,学习如何对数据表进⾏查询。
为了使 PHP 和 MySQL 进⾏交互,需要为 PHP 提供你的数据库⽤户名、密码、数据库名和数据表名。当然,最重要的,查询操作的 SQL 语句。我们⼀⼀来观察是如何实现的。
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'renfei');
define('DB_PASS', 'root');
define('DB_NAME', 'database_name');
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$query = "INSERT INTO table_name (column1, column2) VALUES ('value1', 'value2')";
mysqli_query($dbc, $query);
>
下⾯来解释⼀下这⼀坨代码的⼯作原理。
⾸先 3~6 ⾏为 PHP 中的 define 语句,作⽤很明显,把 DB_HOST 定义为localhost,下⾯的代码中就可以使⽤ DB_HOST 来代替 localhost。这样做的好处在于,如果mysqli_connect函数在代码中出现多次,修改参数的时候则只需修改 define语句,⾮常⽅便。
然后是⼀个叫做 mysqli_connect() 的函数,它需要四个变量,分别是主机名、⽤户名、密码、数据库名。这个函数执⾏后的返回值传递给变量 $dbc,$dbc 包含了⼀次数据库连接。注意,这个变量名是任意的,并不强制要求叫做$dbc。
然后,我们把要对数据库执⾏的操作对应的 SQL 语句以字符串的形式赋给变量 $query。这个变量名也是任意的。应该注意到,这⾥的 SQL 语句是不以分号结尾的。
最后,我们执⾏ mysqli_query(); 函数,该函数有两个参数,分别是⼀个数据库连接,和⼀个 SQL 查询操作。执⾏该函数后,相应的查询操作被执⾏。
如果把这些代码保存成⼀个⽹页,当⽤户打开⽹页的时候,如果各项参数正确,它就会完整地运⾏下去。
这⾥的 SQL 语句的含义是向叫做 table_name 的表中插⼊⼀⾏,其中把 colume# 字段的值相应地设置为 value#。这⾥只设定了两个字段的数值(表中还可以有其他字段;没有显式说明的字段则留空或者使⽤数据表指定的默认值)。该语句的通⽤形式为:
INSERT INTO table_name (column1, column2, ...) VALUES ('value1', 'value2', ...)
如果你要做的仅仅是执⾏⼀个 SQL 语句,那么使⽤这种模式就可以完成。提醒⼀下,$dbc 变量往往是重复使⽤的。
另⼀个常⽤的 SQL 语句就是修改某⼀⾏。它的形式为:
UPDATE table_name SET
column1 ='preferred_value1',
php远程连接mysql数据库column2 ='preferred_value2',
...,
WHERE id ='$id'
当然,这个语句应该是写到⼀⾏的,不过为了清晰我分开来写。它的含义是,修改名为 table_name 的表中字段 id 的值是变量 $id 的值的所有⾏,
把 column1 字段的值设为 preferred_value1,把 column2 字段的值设为 preferred_value2,依此类推。这⾥我们还看到,值既可以⽤常量表⽰,也可以⽤变量表⽰。
注意:会修改所有符合 WHERE ⼦句限定的条件的⾏(如果省略 WHERE ⼦句,就会修改所有⾏)。WHERE ⼦句可以设定多个条件,也可以使⽤⽐较运算符。例如:
WHERE age >20AND gender ='male'
WHERE is_admin ='true'OR id ='$id'
(如果你想问 AND 和 OR 为什么不是符号 && 和 || 的话,我想提⽰你,不要把 PHP 语⾔和 SQL 语⾔搞混了。这是 SQL 语⾔,⽽我只说过 PHP 语⾔和
C/C++ 有些类似)。
下⾯介绍其他 SQL 语句。
-删除table_name表中的所有⾏
DELETE FROM table_name
--删除table_name表中email字段为david@example的所有⾏
DELETE FROM table_name WHERE email ='david@example'
--删除table_name表
DROP TABLE table_name
--删除table_name表中的score字段
ALTER TABLE table_name DROP COLUMN score
--给table_name表添加⼀个叫age的字段,类型为 INTEGER
ALTER TABLE table_name ADD COLUMN age INTEGER
可见,第⼀种⽅式的本质就是编写⼀条 SQL 语句,然后通过 PHP 来执⾏它。下⾯,我们来看第⼆种⽅式。
第⼆种⽅式
有时,我们不满⾜于让服务器去执⾏⼀条 SQL 语句。我们会需要从数据库中查询信息,然后把得到的信息储存起来(其实就是储存在变量中)。这样,我们需要⼀些额外的⼯作。先看⼀坨代码:
<?php
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$query = "SELECT * FROM table_name WHERE problem_id='$id'";
$result = mysqli_query($dbc, $query);
$row = mysqli_fetch_array($result);
$problem_title = $row['problem_title'];
>
这⾥我们省略了 define 语句。
这⼀坨代码和上⼀坨的主要区别是,我们使⽤了 mysqli_query() 函数的返回值,把它保存到 $result 变量中。这个 $result 变量⾥边保存的即为执⾏ SELECT 语句的返回结果。
解释⼀下 SELECT 语句,它的作⽤是选取 table_name 表中符合 WHERE ⼦句条件的所有⾏。上⾯的语句会选定每⼀⾏的所有字段(通配符说明了这⼀点),并且把这些信息全部储存到变量 $result中。
然后,⽤变量 $row 储存 mysqli_fetch_array() 函数的返回值。$row 这个变量⾮常神奇,$row['column_name'] 这个事⼉包含的内容正是刚才选定的⾏
的 column_name 字段的值(事实上,$row 正是⼀个数组)。这⾥,我们把它赋给了 $problem_title 变量。
到这⾥你应该问⼀个问题:如果满⾜ WHERE ⼦句条件的有不⽌⼀⾏的话怎么办?要解答这个问题,需要稍微细致的讲解⼀下 $row 这个事⼉。如果满⾜条件的只有⼀⾏,那么使⽤ $row = mysqli_fetch_
array($result) ⾃然会把这唯⼀的⼀⾏信息储存到 $row 中。如果有很多⾏,那么第⼀次使⽤ $row =
mysqli_fetch_array($result) 会把第⼀⾏的信息储存到 $row 中,⽽第⼆次使⽤ $row = mysqli_fetch_array($result) 会把第⼆⾏的信息储存到 $row 中。如果这时没有下⼀⾏了,再次调⽤的话 $row 会储存逻辑假(false 或 0)。类似,如果符合 WHERE ⼦句条件的⼀⾏都没有,那么执⾏后 $row 直接存储逻辑假。
最后补充⼀点刚才没有提到的。如果不需要所有字段的数据,可以只选择需要的字段。⽅法是把原来 SQL 语句中的通配符换成字段名称。例如:
SELECT problem_name, problem_type FROM table_name WHERE problem_id='$id'
while 循环在 PHP 中的应⽤举例
如果我们要把⼀个数据库的许多⾏信息都展⽰在⽹页中,那么需要⽤到 while 循环和上⾯的第⼆种⽅式。代码如下:
<?php
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$query = "SELECT user_id FROM database_name ORDER BY user_id ASC";
$result = mysqli_query($dbc, $query);
while ($row = mysqli_fetch_array($result)) {
$user_id = $row['user_id'];
echo "<tr>";
echo "<td>".$user_id."</td>";
echo "</tr>";
}
>
如果有⼀定编程基础的话上⾯的代码很容易看懂。上⾯新出现了三种⽤法,说明如下:
SELECT 语句可以附加⼀个 ORDER BY ⼦句,⽤来控制顺序。例如这⾥是按照字段 user_id 升序排列。下⾯的例⼦会先按照 user_rank 降序排列,user_rank 相同时按照 user_id 升序排列:
SELECT user_id, user_rank FROM table_name ORDER BY user_rank DESC, user_id ASC
关于 PHP 中的 echo 语句,它可以⽤来⽣成⽂本,类似于 C 中的 printf() 函数。这⾥利⽤它直接⽣成 HTML 代码。它的⽤法参考例⼦就可以了。
关于符号 . 的⽤法,它的作⽤是连接字符串(和变量),往往和 echo 配合使⽤,⽤法参考⽰例。
从表单获取信息
概述
这⼀部分我们演⽰如何构建⼀个表单,使⽤户填写这个表单并把内容储存到数据库。这⼀技术是⽤户注册系统和⽤户互动的基础。
要实现这个功能,需要 HTML 和 PHP 配合完成。HTML 负责表单,⽽ PHP 负责获取信息并使⽤ SQL 查询储存信息。⾸先来看 HTML 部分(就是普通的表单):
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<label for="username">⽤户名:</label>
<input type="text" id="username" name="username"/><br/>
<label for="info">信息:</label>
<input type="text" id="info" name="info"/><br/>
<input type="submit" value="Submit" name="submit"/>
</form>
属于 HTML 部分的不再解释了,说⼀说新鲜的。这⾥的 action 属性后⾯的 $_SERVER['PHP_SELF'](严格地说,$_SERVER),是 PHP 的⼀个超级全局变量,内容是当前页⾯的相对路径,例如 signup.php。这个 action 属性的含义是指定⽤户填写的信息在哪⾥被处理,这⾥是在当前页⾯处理。⼀般的做法都是将负责处理这部分信息的 PHP 代码和 HTML 代码放在同⼀页⾯内。
下⾯来看⼀下相应的 PHP 处理部分的代码:
<?php
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if (isset($_POST['submit'])) {
$user = $_POST['username'];
$info = $_POST['info'];
$query = "INSERT INTO table_name (tb_user, tb_info) VALUES ('$user', '$info')";
mysqli_query($dbc, $query);
echo "<p>提交成功</p>";
}
mysqli_close($dbc);
>
⾸先仍然是建⽴数据库连接。当⽤户点击 sumbit 按钮后,表单的内容会被储存在 PHP 中 $_POST 超级全局变量内,这个超级全局变量仍然是⼀个数
组。isset() 函数⽤来检查变量是否被设置,只有⽤户点击 submit 后 isset($_POST['submit']) 才返回真,所以不⽤担⼼,⾸次加载表单(那时⽤户还没有填写任何内容)是不会执⾏这部分 PHP 代码的,只有⽤户提交之后才会执⾏。⽤户填写的具体内容可以⽤ $_POST['name'] 来获取。这⾥的 name 对应的是 HTML
中 name 属性的内容。这⼀段程序把⽤户填写的内容赋给变量,然后执⾏插⼊到数据库的操作。
这⾥新出现了⼀个内容,就是 mysqli_close() 函数,它的作⽤是关闭数据库连接。当我们不再需要这个连接的时候,及时关闭是⼀个好主意。
需要注意的是,这仅仅是最简单的代码,⽽且实际上是不完善的。如果要真正投⼊使⽤,我们需要使它更健壮⼀些。下⾯逐⼀讨论这些内容。
检查⽤户输⼊是否合法
如果⽤户根本没有填写表单,就直接点击提交按钮,会发⽣什么?在上⾯的实例中,PHP 依然会乖乖地把空内容插⼊,⽽这显然是垃圾信息,不是我们需要的。所以,需要在插⼊前检查被插⼊的变量是否为空。例如:
<?php
if (!empty($user) && !empty($info)) {
// 插⼊操作
}
>
这⾥出现了 empty() 函数,⽤于检查内容是否为空。注意这⾥使⽤ isset() 是⽆效的,因为 isset() 检查的是是否“被设置”,⽽被设置为空也属于被设置。
错误提⽰
⽤户输⼊有误时,上⾯的改进除了不执⾏SQL查询,并没有多少直观上的变化。⽤户不会收到任何信息表明他们的填写是不合适的。所以我们要在这时产⽣⼀些提⽰,引导⽤户正确填写表单。
<?php
if (!empty($user) && !empty($info)) {
// 插⼊操作
} else {
echo "请填写全部内容后再提交";
}
>
防范 SQL 注⼊攻击
我们执⾏的 SQL语句中包含变量,执⾏的时候会直接把变量内容替换进去。⽽如果攻击者在输⼊框中输⼊⼀些危险的字符(通常包含 SQL 注释符 --,以及其他
预先精⼼设置的内容),就可能导致该次 SQL 查询完全被改写成攻击者需要的意思。为了防范这种攻击,我们需要对可能存在的危险字符进⾏过滤和转义,较为便捷的⽅法是使⽤两个函数。改进后的部分如下:
<?php
$user = mysqli_real_escape_string($dbc, trim($_POST['username']));
$info = mysqli_real_escape_string($dbc, trim($_POST['info']));
>
粘性表单
如果⽤户第⼀次填写失败,他们希望能保留已经填写好的内容,只做些修改就好了。这需要使⽤粘性表单技术。要实现,只需要稍稍改动 HTML 表单部分的代码:
<label for="username">⽤户名:</label>
<input type="text" id="username" name="user" value="<?php if (!empty($user)) echo $user; ?>" >
显⽽易见,如果⽤户填写后因为某些原因没有提交⽽是回到了这个表单,并且之前填写了 user 字段的内容,那么此时 $user 变量已经被赋值了。那么就会在HTML 表单显⽰这些内容,避免⽤户再次输⼊。
构造⼀个注册页⾯
虽然上⾯说了很多,但是仅仅满⾜了我们最基本的输⼊要求。许多时候我们需要更为复杂的功能。举例来说,要写⼀个注册页⾯,必须检查⽤户名是否重复,还要对密码采取某种技术加密以保证安全。
检查⽤户是否重复
基本原理就是,根据需要判重的字段(例如⽤户名)去数据库搜索。如果发现结果则⽤户名重复,如果没有到则允许注册。需要⼀个新函
数 mysqli_num_rows(),返回 SELECT 语句得到的⾏数,根据其是否等于 0 进⾏判断。
<?php
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$query = "SELECT * FROM table_name WHERE user_name = '$user'";
$data = mysqli_query($dbc, $query);
if (mysqli_num_rows($data) == 0) {
// 把内容插⼊数据库
echo "注册成功";
mysqli_close($dbc);
exit();
} else {
echo "⽤户名已被占⽤,请重新选择⽤户名";
$user = "";
}
>
把 $user 清空是为了配合粘性表单。
需要说明的是 exit(); 函数,它会⽴刻终⽌ PHP 的运⾏。因为⽤户已经注册成功,没有必要执⾏后⾯的任何代码,所以使⽤这个函数。写⾃⼰的程序的时候可以亲⾃试验是否需要这⼀⾏、PHP 和 HTML 在 php 中的顺序不同有何影响。我通常的做法是把 PHP 代码放在前⾯,HTML 代码放在后⾯。
对密码进⾏加密存储
明⽂存储密码是对⽤户很不负责的,不仅数据库管理员可以看到密码,⼀旦数据库泄漏,密码就会被
公开。所以,我们应该加密存储⽤户密码。在 PHP 中,可以使⽤ sha1() 函数进⾏加密(sha 即 secure hash algorithm 的⾸字母缩写),它是⼀种不可逆的加密,加密后会⽣成定长的⼀段字符串,并且是⽆法由这段字符串还原原密码的。
加密的原理是,⽤户输⼊密码后,利⽤ PHP 把 hash 过的密码储存在数据库中。⽤户登陆的时候,把⽤户输⼊的密码进⾏ hash 运算,之后和数据库中的进⾏⽐对。
使⽤⽅法如下:
sha1($password)
识别⽤户登录:Cookie
只注册没有⽤,必须添加登录功能。登录功能可以使⽤ Cookie 来实现。这⾥假定你已经了解 Cookie 的基础知识,只说如何实现。
设置 Cookie
<?php
setcookie('user_type', $user_type, time() + (60 * 60 * 24 * 30));
>
上⾯的代码⽤来设置 Cookie,其中函数的第⼀个参数为 Cookie 名称,第⼆个参数为数值(这⾥⽤⼀个变量传递),第三个参数为过期时间,单位秒。⽰例为⼀个⽉。
可以⽤设置多个 Cookie 来存储许多内容,例如⽤户 ID、⽤户组(管理员还是普通⽤户)等。
验证 Cookie
⽤户登陆后,我们可以设置⼀个 Cookie 来存储登录信息(即哪个⽤户登陆的),然后通过检查这个 Cookie 来设定相应功能。
<?php
if (isset($_COOKIE['user_type'])) {
$user_type = $_COOKIE['user_type'];
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。