[TOC]

PHP 基础教程

入门

输出 echo

1
2
3
<?php
echo "Hello World!";
?>

注释

1
2
3
4
5
6
7
<?php
// 这是单行注释

/*这是多行注释块*
*它横跨了多行*/

?>

在 PHP 中,所有用户定义的函数、类和关键词(例如 if、else、echo 等等)都对大小写不敏感。
在 PHP 中,所有变量都对大小写敏感。

支持中文

1
header("Content-type: text/plain");

库文件、或者一些class文件等只有纯php代码的文件不推荐加结束标签

但是如果和 HTML 结合,不加结束标签的话会报错(PHP无法执行HTML代码)。

变量

以 $ 符号开头,其余规则同C语言
PHP 没有创建变量的命令,变量会在首次为其赋值时被创建

函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问,函数内不能访问
函数内部声明的变量拥有 LOCAL 作用域,只能在函数内部进行访问。
global 关键词用于访问函数内的全局变量,在(函数内部)变量前面使用 global 关键词:

1
2
3
4
5
6
7
8
9
10
<?php
$x=5;
$y=10;
function myTest() {
global $x,$y;
$y=$x+$y;
}
myTest();
echo $y; // 输出 15
?>

全局变量

PHP 同时在名为 $GLOBALS[index] 的数组中存储了所有的全局变量。下标存有变量名。这个数组在函数内也可以访问,并能够用于直接更新全局变量。
上面的例子也可以这样写:

1
2
3
function myTest() {
$GLOBALS['y']=$GLOBALS['x']+$GLOBALS['y'];
}

echo - 能够输出一个以上的字符串

print - 只能输出一个字符串,并始终返回 1

echo 是一个语言结构,有无括号均可使用:echo 或 echo()

1
2
3
4
5
$cars=array("Volvo","BMW","SAAB");

echo "<h1>My car ", "is a {$cars[0]}</h1>";

print "Hello world!<br>";

宏定义 define

1
define("username", "OK");

数据类型

同C系语言(但是不用声明类型,直接使用)
三种格式规定整数:十进制、十六进制(前缀是 0x)或八进制(前缀是 0)
浮点数是有小数点或指数形式的数字。
其余:略

PHP对象:class(类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
class Car
{
var $color;
function Car($color="green")
{
$this->color = $color;
}

function what_color()
{
return $this->color;
}
}
?>

可以通过把值设置为 NULL,将变量清空。

字符串

strlen

1
echo strlen("Hello world!"); //12 字符串长度

strpos

1
echo strpos("Hello world!","world"); //6 字符串检索,位置从0开始,没找到则返回false

字符串参考手册:http://www.w3school.com.cn/php/php_ref_string.asp

stripos 不区分大小写寻找

:由于strpos查找开头字符返回值为 0,且 false 的值也是 0,所以判断是否失败要用 ===

1
if (strpos("Hello", "h") === false) echo "查找失败";

str_replace

1
$s = str_replace("原字符", "新字符", $str);

正则表达式

正则替换
1
$s = preg_replace("/原文本/", "新文本", $str);
正则匹配
1
2
3
$pat = "/待匹配文本/iU"; // i 忽略大小写, U 禁止贪婪匹配
if (preg_match($pat, 待匹配文本, $ans))
$result = format_sql(trim($ans[1]));

字符串中变量

用单引号括住的输出,并没有解析字符串变量,而使用双引号括住的输出,则解析了变量了,输出变量的值。

效率问题

普遍认为,在不需要变量解析的字符串输出,用单引号速度可能会快一些。

字符串中的表达式

用花括号括起来 ${$row[0]}

常量

设置常量,使用 define() 函数。
三个参数:变量名,值,大小写不敏感(默认false,即区分大小写)

1
2
3
4
<?php
define("GREETING", "Welcome to W3School!");
echo GREETING;
?>
1
var_dump(x)  // 输出类型以及数值

rand() 随机数

1
rand(min, max);

如果没有确定 min 和 max ,rand() 将返回 0 到 RAND_MAX 之间的随机数

编码

ord() 函数:字符转ASCII

chr() 函数:ASCII转字符

PHP 运算符:同C系

  • 包括==、=+-*/%、+=、>=、++自增 等
    === 完全相等,包括键值对的顺序相同类型相同
    !== 不全等
    !=和<>不等于
    . 串接: $txt1 = “Hello” $txt2 = $txt1 . “ world!” 现在 $txt2 包含 “Hello world!”
    .= 串接赋值: $txt1 = “Hello” $txt1 .= “ world!” 现在 $txt1 包含 “Hello world!”

  • and && 与
    or || 或
    xor 异或
    ! 非

  • if…else… 同C系语言
    switch()…同C系语言(同样有case、break、default等),但是支持字符串
    while(), do…while, for(;;)… 同C系语言

1
2
3
4
<?php 
for ($x=0; $x<=10; $x++) {
echo "数字是:$x <br>"; }
?>

foreach语句

1
2
3
foreach ($array as $value) {
…$value…
}

函数(函数名对大小写不敏感)

1
function 函数名($参数) { 代码; }

可选参数

1
2
function 函数名($参数=默认值) { return 返回值; }
function format_input($s, $blank = 0) { }

可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function seize()
{
$args = func_get_args(); // 取参数列表
if (func_num_args() == 1) // 取参数数量
if (isset($_REQUEST[$args[0]])) // 第一个参数:$args[0]
return format_input($_REQUEST[$args[0]], 1);
else
return NULL;
else // 多个参数
{
$num = func_num_args();
for ($i = 0; $i < $num; $i++)
if (!isset($_REQUEST[$args[$i]])) // 有一个参数不存在与表单中
return NULL;
return 1;
}
}

数组

三种数组类型

  1. 索引数组 - 带有数字索引的数组
  2. 关联数组 - 带有指定键的数组
  3. 多维数组 - 包含一个或多个数组的数组
1
$cars=array("Volvo","BMW","SAAB");
1
count(数组名)  数组长度
1
2
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");  // 关联数组
$age['Peter']="35";

foreach 遍历

1
2
3
foreach($age as $x=>$x_value) {
echo "Key=" . $x . ", Value=" . $x_value, "<br>";
}

数组排序函数

  • sort() - 以升序对数组排序
  • rsort() - 以降序对数组排序
  • asort() - 根据值,以升序对关联数组进行排序
  • ksort() - 根据键,以升序对关联数组进行排序
  • arsort() - 根据值,以降序对关联数组进行排序
  • krsort() - 根据键,以降序对关联数组进行排序

超全局变量

$GLOBALS

  • $GLOBALS
  • $_SERVER
  • $_REQUEST
  • $_POST
  • $_GET
  • $_FILES
  • $_ENV
  • $_COOKIE
  • $_SESSION

PHP 在名为 $GLOBALS[index] 的数组中存储了所有全局变量。
变量的名字就是数组的键。

1
2
3
4
5
6
7
8
9
<?php 
$x = 75;
$y = 25;
function addition() {
$GLOBALS['z'] = $GLOBALS['x'] + $GLOBALS['y'];
}
addition();
echo $z; // 100
?>

$_SERVER

保存关于报头、路径和脚本位置的信息。

1
2
3
4
<?php
echo $_SERVER['PHP_SELF'];
echo "<br>";
?>

元素/代码 描述

  • $_SERVER[‘PHP_SELF’] 返回当前执行脚本的文件名。
    • $_SERVER[‘GATEWAY_INTERFACE’]返回服务器使用的 CGI 规范的版本。
    • $_SERVER[‘SERVER_ADDR’]返回当前运行脚本所在的服务器的 IP 地址。
    • $_SERVER[‘SERVER_NAME’]返回当前运行脚本所在的服务器的主机名(比如 www.w3school.com.cn)。
    • $_SERVER[‘SERVER_SOFTWARE’]返回服务器标识字符串(比如 Apache/2.2.24)。
    • $_SERVER[‘SERVER_PROTOCOL’]返回请求页面时通信协议的名称和版本(例如,“HTTP/1.0”)。
    • $_SERVER[‘REQUEST_METHOD’]返回访问页面使用的请求方法(例如 POST)。
    • $_SERVER[‘REQUEST_TIME’]返回请求开始时的时间戳(例如 1577687494)。
    • $_SERVER[‘QUERY_STRING’]返回查询字符串,如果是通过查询字符串访问此页面。
    • $_SERVER[‘HTTP_ACCEPT’]返回来自当前请求的请求头。
    • $_SERVER[‘HTTP_ACCEPT_CHARSET’]返回来自当前请求的 Accept_Charset 头( 例如 utf-8,ISO-8859-1)
    • $_SERVER[‘HTTP_HOST’]返回来自当前请求的 Host 头。
    • $_SERVER[‘HTTP_REFERER’]返回当前页面的完整 URL(不可靠,因为不是所有用户代理都支持)。
    • $_SERVER[‘HTTPS’]是否通过安全 HTTP 协议查询脚本。
    • $_SERVER[‘REMOTE_ADDR’]返回浏览当前页面的用户的 IP 地址。
    • $_SERVER[‘REMOTE_HOST’]返回浏览当前页面的用户的主机名。
    • $_SERVER[‘REMOTE_PORT’]返回用户机器上连接到 Web 服务器所使用的端口号。
    • $_SERVER[‘SCRIPT_FILENAME’]返回当前执行脚本的绝对路径。
    • $_SERVER[‘SERVER_ADMIN’]该值指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。
    • $_SERVER[‘SERVER_PORT’]Web 服务器使用的端口。默认值为 “80”。
    • $_SERVER[‘SERVER_SIGNATURE’]返回服务器版本和虚拟主机名。
    • $_SERVER[‘PATH_TRANSLATED’]当前脚本所在文件系统(非文档根目录)的基本路径。
    • $_SERVER[‘SCRIPT_NAME’]返回当前脚本的路径。
    • $_SERVER[‘SCRIPT_URI’]返回当前页面的 URI。

$_REQUEST

用于收集 HTML 表单提交的数据。

例:输入name,点提交,下方出现输入的name

1
2
3
4
5
6
7
8
9
10
11
12
<html> <body>
<form method="post"
action="<?php echo $_SERVER['PHP_SELF'];?>" >
Name: <input type="text" name="fname">
<input type="submit">
</form>
<?php
$name = $_REQUEST['fname'];
//$name = $_POST['fname']; //$_POST,等效
echo $name;
?>
</body> </html>

使用isset()函数判断表单是否提交

1
if(isset($_post['submit'])

$_POST

广泛用于收集提交 method=”post” 的 HTML 表单后的表单数据。
也常用于传递变量。
实例见上。

  • $_GET 也可用于收集提交 HTML 表单 (method=”get”) 之后的表单数据。
  • $_GET 也可以收集 URL 中的发送的数据。
1
2
3
4
5
6
7
8
9
10
<html><body>
<a href="test_get.php?subject=PHP&web=W3school.com.cn">
测试 $GET</a>
</body></html>

<html><body>
<?php
echo "Study " . $_GET['subject'] . " at " . $_GET['web'];
?>
</body></html>

常用数组函数

  • 取数组长度:count(array)
  • 增加一个元素到结尾:array_push(array, val)
  • 是否存在某个元素:in_array(val, array)

PHP 高级教程

PHP 多维数组

两维数组

1
2
3
4
5
6
$cars = array (
array("Volvo",22,18),
array("BMW",15,13),
array("Saab",5,2),
array("Land Rover",17,15)
);

这是一个 4 行 3 列 的数组 $cars[3][2]
用法:$cars[1][2] = 13

1
echo $cars[0][0].": 库存:".$cars[0][1].", 销量:".$cars[0][2].".<br>";

打印两维数组表格

1
2
3
4
5
6
7
8
9
10
11
<?php
for ($row = 0; $row < 4; $row++) {
echo "<p><b>Row number $row</b></p>";
echo "<ul>";
for ($col = 0; $col < 3; $col++)
{
echo "<li>".$cars[$row][$col]."</li>";
}
echo "</ul>";
}
?>

PHP 日期

date() 函数

用于对日期或时间进行格式化

1
date(format,timestamp)

format 必需,规定时间戳的格式,见下面。
timestamp可选,规定时间戳,默认当前时间日期。

时间戳是一种字符序列,它表示具体事件发生的日期和事件。

  • d - 表示月里的某天(01-31)
  • m - 表示月(01-12)
  • Y - 表示年(四位数)
  • 1 - 表示周里的某天
  • h - 带有首位零的 12 小时小时格式
  • i - 带有首位零的分钟
  • s - 带有首位零的秒(00 -59)
  • a - 小写的午前和午后(am 或 pm)
1
2
3
echo "今天是 " . date("Y-m-d") . "<br>";
echo "今天是 " . date("l"); // 这是小写的字母L
echo "当前时间是 " . date("h:i:sa");

自动版权年份

1
© 2010-<?php echo date("Y")?>

请注意:date() 会返回服务器的当前日期/时间!

获得时区

默认是服务器所在地点

1
date_default_timezone_set("Asia/Shanghai");

mktime() 函数

返回日期的 Unix 时间戳。Unix 时间戳包含 Unix 纪元(1970 年 1 月 1 日 00:00:00 GMT)与指定时间之间的【秒数】,不考虑闰秒

mktime(hour,minute,second,month,day,year)

1
2
3
4
5
6
<?php

$d=mktime(9, 12, 31, 6, 10, 2015);
echo "创建日期是 " . date("Y-m-d h:i:sa", $d);

?>

strtotime() 函数

用于把人类可读的字符串转换为 Unix 时间。

1
strtotime(time,now)

time:转化格式
now:对比的时候(当前时间可省略)

1
2
3
4
<?php
$d=strtotime("10:38pm April 15 2015");
echo "创建日期是 " . date("Y-m-d h:i:sa", $d);
?>

PHP 在将字符串转换为日期这方面非常聪明,所以您能够使用各种值(strtotime() 并不完美):

1
2
3
$d=strtotime("tomorrow");
$d=strtotime("next Saturday");
$d=strtotime("+3 Months");

输出七月四日之前的天数:

1
2
3
4
5
<?php
$d1=strtotime("December 31");
$d2=ceil(($d1-time())/60/60/24);
echo "距离十二月三十一日还有:" . $d2 ." 天。";
?>

PHP Include

include (或 require)语句会获取指定文件中存在的所有文本/代码/标记,并【复制】到使用 include 语句的文件中。

include 和 require 是相同的,除了错误处理方面:

  • require 会生成致命错误(E_COMPILE_ERROR)并停止脚本(必需文件)
  • include 只生成警告(E_WARNING),并且脚本会继续(不必需文件)

用法:

1
<?php include 'footer.php';?>

可以直接使用引用文件的变量(尽量使用安全的require,否则文件及其变量可能不存在)

PHP 文件

读取文件

1
echo readfile("a.txt");

fopen() 的第一个参数包含被打开的文件名,第二个参数规定打开文件的模式。

如果 fopen() 函数未能打开指定的文件,下面的例子会生成一段消息:

1
2
3
4
5
<?php
$myfile = fopen("a.txt", "r") or die("Unable!");
echo fread($myfile,filesize("a.txt"));
fclose($myfile);
?>

文件会以如下模式之一打开:

  • r 只读。文件指针在文件的开头开始。
    • w 只写。删除文件的内容或创建一个新的文件,如果它不存在。文件指针在文件的开头开始。
    • a只写。文件中的现有数据会被保留。文件指针在文件结尾开始。创建新的文件,如果文件不存在。
    • x创建新文件为只写。返回 FALSE 和错误,如果文件已存在。
    • r+读/写、文件指针在文件开头开始。
    • w+ 读/写。删除文件内容或创建新文件,如果它不存在。文件指针在文件开头开始。
    • a+读/写。文件中已有的数据会被保留。文件指针在文件结尾开始。创建新文件,如果它不存在。
    • x+读/写。返回 FALSE 和错误,如果文件已存在。

fread() 的第一个参数包含待读取文件的文件名,第二个参数规定待读取的最大字节数。

读取单行文件 - fgets()

1
echo fgets($myfile);

调用 fgets() 函数之后,文件指针会移动到下一行。

检查 End-Of-File - feof()

1
2
3
4
5
6
7
8
<?php
$myfile = fopen("a.txt", "r") or die("Unable!");
// 输出单行直到 end-of-file
while(!feof($myfile)) {
echo fgets($myfile) . "<br>";
}
fclose($myfile);
?>

读取单字符 - fgetc()

用法同fgets()

写入文件 - fwrite()

fwrite() 的第一个参数包含要写入的文件的文件名,第二个参数是被写的字符串。

1
2
3
4
5
6
$myfile = fopen("new.txt", "w") or die("Unable!");
$txt = "Bill Gates\n";
fwrite($myfile, $txt);
$txt = "Steve Jobs\n";
fwrite($myfile, $txt);
fclose($myfile);

写出的文件是这样的:

1
2
Bill Gates
Steve Jobs

PHP 文件上传

文件上传 网页端

1
2
3
4
5
6
7
<html><body>
<form action="upload_file.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> <br />
<input type="submit" name="submit" value="Submit" />
</form>
</body></html>

<form> 标签的 enctype 属性规定了在提交表单时要使用哪种内容类型。在表单需要二进制数据时,比如文件内容,请使用 “multipart/form-data”。

<input> 标签的 type=”file” 属性规定了应该把输入作为文件来处理。

上传脚本 服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if ($_FILES["file"]["error"] > 0)
{
echo "Error: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Stored in: " . $_FILES["file"]["tmp_name"];
}
?>

使用 PHP 的全局数组 $_FILES,第二个下标可以是 “name“, “type“, “size“, “tmp_name“ 或 “error“。

在服务器的 PHP 临时文件夹创建了一个被上传文件的临时副本,会在脚本结束时消失。
拷贝到另外的位置:

1
2
3
4
5
6
7
8
9
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}

PHP Cookies

setcookie() 函数

用于设置 cookie。

注释:setcookie() 函数必须位于 标签之前。

setcookie(name, value, expire, path, domain);

一小时后过期:

1
2
3
setcookie("user", "Alex Porter", time()+3600);
<html><body>
</body></html>

cookie会自动URL编码、解码。
为防止 URL 编码,使用 setrawcookie()

用于取回 cookie 的值。

1
echo $_COOKIE["user"];
1
2
// A way to view all cookies
print_r($_COOKIE);

isset() 函数

确认是否已设置了 cookie

1
2
3
4
5
6
<?php
if (isset($_COOKIE["user"]))
echo "Welcome " . $_COOKIE["user"] . "!<br />";
else
echo "Welcome guest!<br />";
?>

使过期日期变更为过去的时间点。

1
setcookie("user", "", time()-3600);

PHP Sessions

session_start()

在您把用户信息存储到 PHP session 中之前,首先必须启动会话。
注释:session_start() 必须位于 标签之前:

1
2
<?php session_start(); ?>
<html><body></body></html>

上面的代码会向服务器注册用户的会话,以便您可以开始保存用户信息,同时会为用户会话分配一个 UID。

$_SESSION 变量

存储和取回 session 变量

1
2
3
4
session_start();
$_SESSION['views']=1;

echo "Pageviews=". $_SESSION['views'];

isset() 函数

检测是否已设置 session 变量。

1
2
3
4
if(isset($_SESSION['views']))
$_SESSION['views']=$_SESSION['views']+1;
else
$_SESSION['views']=1;

unset() 函数

用于释放指定的 session 变量:

1
2
3
<?php
unset($_SESSION['views']);
?>

session_destroy() 函数

彻底终结 session (清空):

1
2
3
<?php
session_destroy();
?>

PHP E-mail

mail() 发送邮件

1
mail(to,subject,message,headers,parameters)

接收者、主题、消息、[附加的标题]、[参数]

防止 email 注入(使用 PHP 过滤器)

1
2
3
4
5
6
7
8
9
10
11
12
function spamcheck($field)
{
$field=filter_var($field, FILTER_SANITIZE_EMAIL);

if(filter_var($field, FILTER_VALIDATE_EMAIL))
return TRUE;
else
return FALSE;
}

if (spamcheck($_REQUEST['email'])==FALSE)
echo "Invalid input";

PHP Error

die() 函数:基本的错误处理

1
die("Error<br>");
1
die();

set_error_handler():修改错误处理程序:

1
set_error_handler("customError");
1
set_error_handler("customError",E_USER_WARNING);  // 加上错误级别
1
2
3
4
5
6
7
8
9
10
<?php
function customError($errno, $errstr)
{
echo "<b>Error:</b> [$errno] $errstr";
}

set_error_handler("customError");

echo($test);
?>

如果异常没有被捕获,而且又没用使用 set_exception_handler() 作相应的处理的话,那么将发生一个严重的错误(致命错误),并且输出 “Uncaught Exception” (未捕获异常)的错误消息。

  • Try - 使用异常的函数应该位于 “try” 代码块内。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常。

  • Throw - 这里规定如何触发异常。每一个 “throw” 必须对应至少一个 “catch”

  • Catch - “catch” 代码块会捕获异常,并创建一个包含异常信息的对象

创建一个自定义的 Exception 类

可以使用 exception 类的方法,比如 getLine() 、 getFile() 以及 getMessage()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class customException extends Exception
{
public function errorMessage()
{
$errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile().': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
return $errorMsg;
}
}

$email = "someone@example...com";

try
{
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
throw new customException($email);
}

catch (customException $e)
echo $e->errorMessage();
?>

设置顶层异常处理器 (Top Level Exception Handler)

set_exception_handler() 函数可设置处理所有未捕获异常的用户定义函数。

1
2
3
4
5
6
7
8
9
10
<?php
function myException($exception)
{
echo "<b>Exception:</b> " , $exception->getMessage();
}

set_exception_handler('myException');

throw new Exception('Uncaught Exception occurred');
?>

PHP Exception 过滤器

函数和过滤器

  • filter_var() - 通过一个指定的过滤器来过滤单一的变量
  • filter_var_array() - 通过相同的或不同的过滤器来过滤多个变量
  • filter_input - 获取一个输入变量,并对它进行过滤
  • filter_input_array - 获取多个输入变量,并通过相同的或不同的过滤器对它们进行过滤

验证整数

1
filter_var($int, FILTER_VALIDATE_INT)

Validating 过滤器

用于验证用户输入
严格的格式规则(比如 URL 或 E-Mail 验证)
如果成功则返回预期的类型,如果失败则返回 FALSE

Sanitizing 过滤器

用于允许或禁止字符串中指定的字符
无数据格式规则
始终返回字符串

选项和标志用于向指定的过滤器添加额外的过滤选项。
不同的过滤器有不同的选项和标志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$var=300;

$int_options = array(
"options"=>array
( "min_range"=>0,
"max_range"=>256 )
);

if(!filter_var($var, FILTER_VALIDATE_INT, $int_options))
echo("Integer is not valid"); // 300,输出
else
echo("Integer is valid");
?>

验证表单

1
2
if (!filter_input(INPUT_GET, "email", FILTER_VALIDATE_EMAIL)) 
{ echo "E-Mail is not valid"; } // Email不可用

通过 “GET” 方法传送的输入变量,
1、检测是否存在 “GET” 类型的 “email” 输入变量
2、如果存在,检测它是否是有效的邮件地址

净化输入

1
2
3
4
if(!filter_has_var(INPUT_POST, "url"))
{ echo("Input type does not exist"); }
else
{ $url = filter_input(INPUT_POST, "url", FILTER_SANITIZE_URL); }

通过 “POST” 方法传送的输入变量 (url),
1、检测是否存在 “POST” 类型的 “url” 输入变量
2、如果存在此输入变量,对其进行净化(删除非法字符),并将其存储在 $url 变量中

输入变量:”http://www.W3非o法ol.com.c字符n/“,则净化后的 $url 变量:
http://www.W3School.com.cn/

过滤多个输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
$filters = array
(
"name" => array
( "filter"=>FILTER_SANITIZE_STRING ),
"age" => array
(
"filter"=>FILTER_VALIDATE_INT,
"options"=>array
( "min_range"=>1,
"max_range"=>120
)
),
"email"=> FILTER_VALIDATE_EMAIL,
);

$result = filter_input_array(INPUT_GET, $filters);

if (!$result["age"])
{ echo("Age must be a number between 1 and 120.<br />"); }
elseif(!$result["email"])
{ echo("E-Mail is not valid.<br />"); }
else
{ echo("User input is valid"); }
?>

自定义数据过滤函数

1
2
3
4
5
6
7
8
<?php
function convertSpace($string)
{ return str_replace("_", " ", $string); }

$string = "Peter_is_a_great_guy!";

echo filter_var($string, FILTER_CALLBACK, array("options"=>"convertSpace"));
?>

PHP 表单

注意:在处理 PHP 表单时请关注安全!

表单是否存在

1
2
3
4
if (isset($_REQUEST[$s])) { }
if (isset($_COOKIE[$s])) { }
if (isset($_POST[$s])) { }
if (isset($_GET[$s])) { }

GET 和 POST

者都创建数组(例如,array( key => value, key2 => value2, …))。此数组包含键/值对,其中的键是表单控件的名称,而值是来自用户的输入数据。

1
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

作用:$_SERVER[“PHP_SELF”] 返回当前执行脚本的文件名,将表单数据发送到页面本身

htmlspecialchars() 函数

把特殊字符转换为 HTML 实体。
这意味着 < 和 > 之类的 HTML 字符会被替换为 < 和 > 。这样可防止攻击者通过在表单中注入 HTML 或 JavaScript 代码(跨站点脚本攻击)对代码进行利用。

$_SERVER[“PHP_SELF”] 变量能够被黑客利用!

假设我们的一张名为 “test_form.php” 的页面中有如下表单:

1
<form method="post" action="<?php echo $_SERVER["PHP_SELF"];?>">

URL:”http://www.example.com/test_form.php"

上面的代码会转换为:

1
<form method="post" action="test_form.php">

如果输入URL:
http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E

在这种情况下,上面的代码会转换为:

1
<form method="post" action="test_form.php"/><script>alert('hacked')</script>

这段代码加入了一段脚本和一个提示命令。并且当此页面加载后,就会执行 JavaScript 代码(用户会看到一个提示框)。
<script> 标签内能够添加任何 JavaScript 代码!

使用 htmlspecialchars() 函数能够避免 $_SERVER[“PHP_SELF”] 被利用。

表单代码是这样的:

1
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

htmlspecialchars() 函数把特殊字符转换为 HTML 实体。
现在,如果用户试图利用 PHP_SELF 变量,会导致如下输出:

1
<form method="post" action="test_form.php/"><script>alert('hacked')</script>">

无法利用,没有危害!

htmlspecialchars() 函数可以使提交的代码字段不会被执行,因为会被保存为转义代码,当作普通的文本,就像这样:

1
<script>location.href('http://www.hacked.com')</script>

转义后的:

1
&lt;script&gt;location.href('http://www.hacked.com')&lt;/script&gt;

现在这条代码显示在页面上或 e-mail 中是安全的。

检查函数

在用户提交该表单时,我们还要做两件事:
1.(通过 PHP trim() 函数)去除用户输入数据中不必要的字符(多余的空格、制表符、换行)
2.(通过 PHP stripslashes() 函数)删除用户输入数据中的反斜杠(\)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

// 定义变量并设置为空值
$name = $email = $gender = $comment = $website = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") { // 提交类型是否POST或未提交
$name = test_input($_POST["name"]);
$email = test_input($_POST["email"]);
$website = test_input($_POST["website"]);
$comment = test_input($_POST["comment"]);
$gender = test_input($_POST["gender"]);
}
function test_input($data) {
$data = trim($data); // 去空格
$data = stripslashes($data); // 去转义
$data = htmlspecialchars($data); // 防注入
return $data;
}

?>

输入提示(必填项未输入/格式错误等)

1
2
3
4
Name: <input type="text" name="name" value="<?php echo $name;?>">
<span class="error">
<?php echo $Msg;?>
</span>

格式验证(正则表达式)

名字是否包含空格

1
2
3
$name = test_input($_POST["name"]);
if (!preg_match("/^[a-zA-Z ]*$/",$name))
{ $nameErr = "只允许字母和空格!"; }

邮箱

1
preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email)

URL(允许斜杠 /,需转义)

1
preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/% =~_|]/i",$website)

PHP 数据库

连接数据库

1
mysql_connect(servername,username,password);

servername 默认是 “localhost:3306”
username 默认值是拥有服务器进程的用户的名称
password 默认为””

创建数据库

1
CREATE DATABASE database_name

选择数据库

1
mysql_select_db("database_name", $con);

建表、添加、选取等之前必须选择数据库

创建表

1
2
3
4
5
6
7
CREATE TABLE table_name
(
column_name1 data_type,
column_name2 data_type,
column_name3 data_type,
.......
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
// 连接数据库
$con = mysql_connect("localhost","peter","123");
if (!$con)
{ die('Could not connect: ' . mysql_error()); }

// 创建数据库
if (mysql_query("CREATE DATABASE my_db",$con))
{ echo "Database created"; }
else
{ echo "Error creating: " . mysql_error(); }

// 选择数据库后才能建表
mysql_select_db("my_db", $con);

// 创建栏位
$sql = "CREATE TABLE Persons
(
// 主键 personID,不为空,自增
personID int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(personID),
FirstName varchar(15),
LastName varchar(15),
Age int
)";

// 选择数据库后创建表
mysql_query($sql,$con);

mysql_close($con);
?>

修改表名

1
mysql_query("ALTER TABLE `$old_tablename` RENAME TO `$tablename`"); // 注意:是 ` ` 而不是 单引号

删除表

1
mysql_query("DROP TABLE `$tablename`");

插入数据(不分大小写):INSERT INTO

1
mysql_query("INSERT INTO Persons (FirstName, LastName, Age) VALUES ('Glenn', 'Quagmire', '33')");

注意values里面的单引号,必须要加上去。

表单数据到数据库

1
2
$sql="INSERT INTO Persons (FirstName, LastName, Age) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";
mysql_query($sql,$con);

选取数据:SELECT

1
$result = mysql_query("SELECT * FROM Persons");

按行读取选取的数据

1
mysql_fetch_array(data,array_type);

mysql_fetch_array() 是 mysql_fetch_row() 的扩展,不会慢很多。

array_type 规定返回哪种结果。可能的值:

  • MYSQL_ASSOC - 关联数组
  • MYSQL_NUM - 数字数组
  • MYSQL_BOTH - 默认。同时产生关联和数字数组
1
2
3
4
5
while($row = mysql_fetch_array($result))
{
echo $row['FirstName'] . " " . $row['LastName'];
echo "<br />";
}

匹配指定条件:WHERE

运算符: = != < > <= >=

  • BETWEEN 介于一个包含范围内
  • LIKE 搜索匹配的模式
1
$result = mysql_query("SELECT * FROM Persons WHERE FirstName='Peter'");

###排序

  • 排序:ORDER BY
    SELECT * FROM Persons ORDER BY age
  • 默认升序,DESC 关键词降序。
    ORDER BY column_name DESC
  • 多列排序时,只有第一列相同时才使用第二列:
    ORDER BY column_name1, column_name2

修改数据:UPDATE

1
mysql_query("UPDATE Persons SET Age = '36' WHERE FirstName = 'Peter' AND LastName = 'Griffin'");

删除数据:DELETE FROM

1
mysql_query("DELETE FROM Persons WHERE LastName='Griffin'");

ODBC

不多说,直接看下面的实例吧!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<body>

<?php
// 名为 northwind 的 DSN 的连接,无帐号、密码
$conn=odbc_connect('northwind','','');
if (!$conn)
{exit("Connection Failed: " . $conn);}

$sql="SELECT * FROM customers";
$rs=odbc_exec($conn,$sql); // 查询
if (!$rs)
{exit("Error in SQL");}

echo "<table><tr>";
echo "<th>Companyname</th>";
echo "<th>Contactname</th></tr>";

while (odbc_fetch_row($rs)) // 取出
{
$compname=odbc_result($rs,"CompanyName");
$conname=odbc_result($rs,"ContactName");
echo "<tr><td>$compname</td>";
echo "<td>$conname</td></tr>";
}
odbc_close($conn); // 关闭
echo "</table>";
?>

</body>
</html>

AJAX

创建 XMLHttpRequest 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function GetXmlHttpObject()
{
var xmlHttp=null;

try {
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
} catch (e) {
// Internet Explorer
try {
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}

实时搜索

前端 HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
<script src="clienthint.js"></script>
</head>

<body>

<form>
First Name:
<input type="text" id="txt1"
onkeyup="showHint(this.value)">
</form>

<p>Suggestions: <span id="txtHint"></span></p>

</body>
</html>

后端 JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var xmlHttp

// 每当在输入域中输入一个字符,该函数就会被执行一次
function showHint(str)
{
if (str.length==0)
{
document.getElementById("txtHint").innerHTML=""
return
}
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
{
alert ("Browser does not support HTTP Request")
return
}
var url="gethint.php"
url=url+"?q="+str
url=url+"&sid="+Math.random()
xmlHttp.onreadystatechange=stateChanged
xmlHttp.open("GET",url,true)
xmlHttp.send(null)
}

// 每当 XMLHTTP 对象的状态发生改变,则执行该函数
function stateChanged()
{
// 在状态变成 4 (或 "complete")时,用响应文本填充 txtHint 占位符 txtHint 的内容
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{
document.getElementById("txtHint").innerHTML=xmlHttp.responseText
}
}

// 为不同浏览器创建不同 XMLHTTP 对象的问题
function GetXmlHttpObject()
{
var xmlHttp=null;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e)
{
// Internet Explorer
try
{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}

其他

取网页源码

1
2
3
4
5
6
$ret = file_get_contents("http://acm.hdu.edu.cn/showproblem.php?pid=1000"); // 取网页源码
$ret = iconv("gb2312", "utf-8//IGNORE",$ret); // 避免乱码

$pat = "/<h1 style='color:#1A5CC8'>(.+)<\/h1>/"; // 后缀:i 忽略大小写, U 禁止贪婪匹配
if (preg_match($pat, $ret, $ans))
$title = format_sql(trim($ans[1]));

网址重定向

1
header("Location:" . $_SERVER['PHP_SELF']); // 默认页面

获取 IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function getIP() // 获取真实的IP
{
$ip = "";
if (getenv('HTTP_CLIENT_IP'))
{
$ip = getenv('HTTP_CLIENT_IP');
}
elseif (getenv('HTTP_X_FORWARDED_FOR'))
{
$ip = getenv('HTTP_X_FORWARDED_FOR');
}
elseif (getenv('HTTP_X_FORWARDED'))
{
$ip = getenv('HTTP_X_FORWARDED');
}
elseif (getenv('HTTP_FORWARDED_FOR'))
{
$ip = getenv('HTTP_FORWARDED_FOR');
}
elseif (getenv('HTTP_FORWARDED'))
{
$ip = getenv('HTTP_FORWARDED');
}
else
{
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}

获取时间文本

时间戳:time()

1
2
3
4
5
6
function gettime() // 获取当前时间文本
{
date_default_timezone_set('PRC'); // 临时设置成中国时区
$time = date("y-m-d h:i:s", time());
return $time;
}

自制数据库模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
define("MySQL_servername", "localhost");
define("MySQL_username", "root");
define("MySQL_password", "root");
define("MySQL_detabase", "数据库名");
$con = NULL;
$is_connected = 0;

function connect_sql() // 连接数据库
{
global $con, $is_connected;
if ($is_connected) // 避免多次连接
{ return NULL; }

$con = mysql_connect(MySQL_servername, MySQL_username, MySQL_password);
if (!$con)
{ die("数据库连接失败"); }

$is_connected = 1;

mysql_select_db(MySQL_database, $con);

return $con;
}

function query_sql($sql) // 查询语句
{
global $con, $is_connected;
if (!$is_connected)
{
connect_sql();
$is_connected = 1;
}

$result = mysql_query($sql, $con);
return $result;
}

function row_sql($sql) // 查询一行,数据是否存在
{
global $con, $is_connected;
if (!$is_connected)
{
connect_sql();
$is_connected = 1;
}

if ($result = mysql_query($sql))
{
$row = mysql_fetch_array($result);
return $row;
}
else
{
return NULL;
}
}

自制表单操作模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
function seize() // 函数重载吧……
{
$args = func_get_args();
if (func_num_args() == 1) // 一个,直接取值(可为空字符串)
if (isset($_REQUEST[$args[0]]))
return format_input($_REQUEST[$args[0]], 1);
else
return NULL;
else // 多个,仅判断存不存在
{
$num = func_num_args();
for ($i = 0; $i < $num; $i++)
if (!isset($_REQUEST[$args[$i]])) // 有一个没有值
return NULL;
return 1;
}
}

function seizeor() // 多个表单有一个就行了
{
$args = func_get_args();
if (func_num_args() == 1) // 一个,存在并返回值
if (isset($_REQUEST[$args[0]]))
return format_input($_REQUEST[$args[0]], 1);
else
return NULL;
else // 多个,仅判断存不存在
{
$num = func_num_args();
for ($i = 0; $i < $num; $i++)
if (isset($_REQUEST[$s])) // 有一个没有值
{
return format_input($_REQUEST[$args[$i]], 1);
}
return NULL;
}
}

function seize0($s, $blank = 0) // 获取必须存在且非空的表单,如果没有则强制退出
{
if (isset($_REQUEST[$s]) && $_REQUEST[$s] != "")
return format_input($_REQUEST[$s], $blank);
else
die ;
}

function seize1($s, $blank = 0) // 获取一个表单
{
if (isset($_REQUEST[$s]))
return format_input($_REQUEST[$s], $blank);
else
return NULL;
}

function seize2($s, &$a, $blank = 0) // 获取表单并引用赋值
{
if (isset($_REQUEST[$s]))
return ($a = format_input($_REQUEST[$s], $blank));
/*else if (isset($_COOKIE[$s]))
return ($a = $s);*/
else
return ($a = NULL);
}

function seizeval($s, $blank = 0) // 获取一个非空表单,否则为NULL
{
if (isset($_REQUEST[$s]) && $_REQUEST[$s] != "")
return format_input($_REQUEST[$s], $blank);
/*else if (isset($_COOKIE[$s]))
return $s;*/
else
return NULL;
}

function format_input($s, $blank = 0) // 格式化输入内容
{
if (!$blank)
$s = trim($s); // 去空格
$s = stripslashes($s); // 去转义
$s - htmlspecialchars($s); // 防注入
return $s;
}

END

恭喜您,看完了整篇文章!