PHP内容梳理
2014-08-31
背景
最近要快速搭建一个网站,用途:实现团队内容的对外展现,第一反应就是用wordpress框架实现,号称5分钟建站,够快了。问题来了:网站要实现一些特定的效果,这个就需要定制一下了,wordpress后端是PHP写的处理逻辑,OK,熟悉一下PHP。(实际上,半年前在baidu的时候,用过一段时间PHP,只不过没有整理,后来没继续使用,也忘得差不多了,就剩下学习方法和感觉了)
学习路线
自己之前接触过1个多月的PHP,当时的内容就是搭建web站点;针对一门不熟悉的语言,只需要掌握其基本知识即可开始工作,包括:
- 定义变量;
- 不同数据结构对应的变量;(链表、集合)
- 多个文件之间的组织结构;
- 调试程序;
变量
变量,就是存储数据的容器,对变量进行操作就是处理数据;
定义变量
变量名,几点:
- 变量名必须以
$
开头; $
之后,第一个字符必须为字母、下划线_
,不能为数字;- 变量名剩余部分,可以包含任意字母、数字、下划线;
- 变量名,区分大小写;
关于变量名,建议:
- 变量名,全部小写字母;
- 变量名,表示其含义,举例:
$first_name
好于$fn
; - 注释变量用途,例:$first_name = ‘Guo’; //the first name
- 保持一致命名模式,如果要大写,就全部大写;举例:预定义变量
$_SERVER
;
变量定义,几点:
- PHP是脚本语言,不要求必须先定义变量或者初始化变量;但为了规范开发、减少出错,建议先定义变量后使用;
- 在定义时,对变量用途进行注释;
- 变量命名风格,有两种:驼峰式(
$FirstName
)和下划线式($first_name
),建议下划线式。
变量类型
这一部分,将介绍3种变量类型:数值型、字符串型和数组;
- 数值
- 整数:1、-1;
- 浮点数:1.0、2.2;
- 注:
1/3
包含/
是错误表示;
- 字符串
- 单引号
'
、双引号“
包含起来的任意符号; - 可以包含变量,例:
'$field_name'
;
- 单引号
- 数组
- 基本单元:key-value;
- key不同,数组分为两类:索引数组(key为数值)、关联数组(key为字符串);
- 数组的key,又称索引;
- 如果数组的value也是数组,则,为多维数组;
- PHP中关联数组,在Perl和Ruby中称为散列;
索引数组如下:
key | value |
---|---|
0 | Don |
1 | Jane |
2 | Roger |
关联数组如下:
key | value |
---|---|
D | Don |
J | Jane |
R | Roger |
变量赋值
- 普通变量(数值、字符串)
- 等号赋值,例: $number = 1;
- 数组
- 使用array()函数,例:$list = array();
使用变量
- 直接输出变量
- echo $number;
- print $number;
- 上下文中输出变量
- echo “number is $number”;
- 注:上述不能使用单引号
‘
,下文会提到;
- 数组
- print_r “$_SERVER”;
- 注:print “$_SERVER”; 结果是:
Array
; - 数组是非标量类型,还有其他输出方式;
特别说明:打印出变量内容,是调试脚本的重要方法。
引号说明
这个比较重要,单拎出来说一下:
单引号
‘
内容,原样输出;双引号”
内容,进行变量带入;
针对引号,几点注意:
- 坚持使用双引号
"
即可解决大部分问题; - 当输出
\n
、\t
时,需要使用双引号"
; - 建议输出所有变量时,都使用双引号
"
;
预定义变量
PHP中已经预先定义了一些变量,这些变量功能强大,需要熟记。
- $_POST,数组,捕获POST方式表单数据;
- 使用键访问数组元素:
print $_POST['name_value']
; - 严格区分大小写,并且以
$_
开头,全部大写; - 双引号内部,不能使用数组的单引号来引用key;
- 使用键访问数组元素:
针对上面 3. 中提到的情况,说明如下:
// 下面输出会出错
print "Thank U : $_POST['name']";
// 可选解决办法(先取出,后使用)
$input_name_value = $_POST['name'];
print "Thank U : $input_name_value";
疑问:能使用双引号,即 $_POST["name"]
样式,来获取数组中内容吗?当然可以,单引号能做,双引号也能。
- $_GET,捕获GET方式表单数据,与$_POST类似;
- $_REQUEST,捕获任意方式提交的数据;(不推荐)
- $_COOKIE,设置和查询当前cookie中信息;
- $_SERVER,服务器和执行环境信息;
- ‘PHP_SELF’:当前执行脚本的文件名,与document root有关,例如:
/test.php/foo.bar
,具体看PHP手册; - ‘REQUEST_METHOD’:访问页面的请求方法,例如:GET、POST、PUT;
- ‘PHP_SELF’:当前执行脚本的文件名,与document root有关,例如:
数组
操作数组:array()函数创建数组:
$list = array ('appales', 'bananas', 'oranges');
默认,数组的索引从0开始;当然有办法从1开始,代码如下:
$list = array(
1 => 'apples',
2 => 'bananas',
3 => 'oranges'
);
//key值也可以为字符串
$list = array(
'Mon' => 'apples',
'Tue' => 'bananas',
'Wed' => 'oranges'
);
//range () 函数创建数组
$evens = range (0, 100, 2);
关于数组的常用操作,小结如下:
- 创建数组
$list = array ()
;evens = array ()
;
- 输出数组
print_r()
函数var_dump()
函数foreach()
- 引用元素
- 只能通过key的引用来获取;
- key区分大小写;
- key是字符串的,通过$list[1]无法访问任何元素;
- 追加元素
- 数值索引时:
$list[] = 'pears'
; - 字符串索引:必须指定key;
- 数值索引时:
- 修改元素
- 数值索引:
$list[2] = 'pears'
; - 字符串索引:
$list['Wed'] = 'pears'
; - 字符串索引时,不能使用数值;
- 数值索引:
- 元素个数
$how_many = count($array)
;
- 删除元素
unset($list[1])
;unset($list['Wed'])
;unset($list)
;//删除整个数组$list = array()
;//等价于删除数组
- 合并数组
array_merge($list1, $list2)
;$list = $list1 + $list2
;
- 数组排序:会单独列张表
sort($array)
、rsort()
;asort()
、arsort()
;ksort()
、krsort()
;shuffle()
:数组元素顺序随机重组;
- 字符串与数组间相互转换
implode()
:数组转换为字符串;explode()
:字符串转换为数组;
- 判断是否为数组
is_array($array)
;
- 额外几个函数
array_key_exists()
array_search()
in_array()
数组使用过程总结如下:
- 如果 $list 不存在,
$list[] = 'value'
,会去创建数组; - 数组中使用单引号
'
来引用 key 和 value,也可以使用双引号"
; sizeof()
函数是count()
的别名,返回数组的元素个数;- 当key为数值、变量、常数时,不用引号引用,即可调用;
特别要说的是foreach遍历数组,举例如下:
//同时,使用key 和value
foreach($array as $key => $value) {
print "<p>Key is $key. Value is $value. </p>";
}
//只使用value
foreach($array as $value){
print "<p>Value is $value.</p>";
}
//对于数值索引数组
for($n = 0; $n < count($array); $n++){
print "<p>Value is $array[$n].</p>";
}
备注:上述$key => $value
,可以替换为$k => $v
等类似形式。
多维数组
$fruits = array (
1 => 'apples',
2 => 'bananas',
3 => 'oranges'
);
$meats =array (
'fruits' => $fruits,
'other' => 'peanuts',
'cash' => 30.00
);
数组排序,常用函数如下:
函数 | 排序依据 | 是否保持key-value对应关系 |
---|---|---|
sort() | Values | No |
rsort() | Values | No |
asort() | Values | Yes |
arsort() | Values | Yes |
ksort() | Keys | Yes |
krsort() | Keys | Yes |
natsort() | Keys,自然顺序 | Yes |
natcasesort() | Keys | Yes |
字符串与数组之间转换,通常如下原因:
- 数组->字符串,为了在URL中传输数组;
- 数组->字符串,方便将数组存储到数据库;
- 字符串->数组,逗号分割的文本,转化为相互独立形式;
数组与字符串间转换实例:
// 将array以','为分割,转换为字符串
$string = implode(',', $array);
//将string以','为分割,转换为数组
$array = explode(',', $string);
将数组中元素分别指定给不同变量,使用 list() 函数:
$date = array('Thursday', 23, 'October');
//为3个变量赋值
list($weekday, $day, $month) = $date;
实践:查看PHP手册中的几个函数,array_key_exists()
、array_search()
、in_array()
。
常量
与变量不同,常量在脚本的执行过程中,一直保持初始值;常量一旦设定就不能更改。
定义常量
使用define()函数
define('CONSTANT_NAME', value);
几点:
- 常量名,以字母、下划线开头,全部大写;
- 常量名,不需要以
$
开头; - 定义常量,define()中常量名,使用引号;
- 输出常量,直接使用常量名即可;
- 引号内部(单引号、双引号)无法输出常量;
- 判断是否定义常量:
defined('CONSTANT_NAME')
; - 常量是全局作用域的;
- 常量的值不能修改,常量本身也不能修改;
预定义常量
- PHP_VERSION:正在运行的PHP版本
- PHP_OS:服务器操作系统
- SID:session ID
运算符
PHP中运算符,参考下表:
运算符 | 用法 | 类型 |
---|---|---|
+ |
加 | 算数 |
- |
减 | 算数 |
* |
乘 | 算数 |
/ |
除 | 算数 |
% |
取模 | 算数 |
++ |
自增 | 算数 |
-- |
自减 | 算数 |
= |
赋值 | 赋值 |
== |
相等 | 比较 |
!= |
不等 | 比较 |
< |
小于 | 比较 |
> |
大于 | 比较 |
<= |
小于等于 | 比较 |
>= |
大于等于 | 比较 |
! |
非 | 逻辑 |
AND |
与 | 逻辑 |
&& |
与 | 逻辑 |
OR |
或 | 逻辑 |
|| |
或 | 逻辑 |
XOR |
异或 | 逻辑 |
. |
连接 | 字符串 |
函数
特别说明:PHP中函数名与()
之间可以有空格,即,如下两种方式都正确:
round(100.2);
round (100.2);
数值格式化
round(),进行数值四舍五入,具体参阅[PHP Manual],举例如下:
<?php
round(3.4); //3
round(4.12, 1); //4.1
round(1221, -2); //1200
?>
类似函数还有:number_format()
、printf()
、sprintf()
;
随机数
rand()
、mt_rand()
,具体不多说,查看操作手册即可;
字符串连接
字符串连接:句点.
,举例:$result = $first_name . $last_name
;
转换HTML格式
- nl2br($string); //将$string内的\n转换为
- htmlsprcialchars(); //将特定的HTML标签转换为实体版本
- htmlentities(); //将所有的HTML标签转换为实体版本
- strip_tags(); //移除所有HTML和PHP标签
- html_entity_decode(); //将HTML实体转换为相应HTML代码
- wordwrap(); //按照指定长度,换行处理字符串
几个问题:
- HTML实体是什么?例如:
<
对应HTML实体为<
;使用HTML实体主要原因:防止输入文本中包含HTML标签,打乱整个页面的布局,更近一步,防止用户提交JS进行跨站点攻击(XSS,Cross-Site Scripting)。补充:XSS 能够做的事情:破环网站风格、功能;盗取浏览用户的session信息。 - 通常先移除所有HTML、PHP标签,再将
\n
等转义符,转换为HTML换行符,即:strip_tags()
之后nl2br()
;
字符串编/解码
背景:通过URL的query向服务器发送参数时,要求参数不能包含空格、特殊字符等;如果一定要使用URL的query向服务器传送数据,可以先对数据进行编码,即可解决此问题。
urlencode()
,专门解决这一问题,将字符串转换为适合最为URL的一部分来传输。几点说明:
- 表单发送出去的数据,会自动进行URL编码,在服务器端,会自动解码,因此,本例中,只需要在页面上通过
urlencode()
编码即可,服务器能够自动解码; urldecode()
,能够进行解码,但不常用,因为服务器能够自动解码;
子字符串
strtok($string, $token)
,按照$token来分割$string,并返回最新的子串;substring($string, 0, 10)
,从$string中索引为0的字符开始(包含在内),累计截取10个字符;substring($string, -3, 3)
,从$string中倒数第3个字符开始(包含在内),累计截取3个字符;strlen($string)
,字符串中字符个数;str_word_count()
,字符串中单词个数;str_ireplace($needle, $replacement, $haystack)
,将$haystack中$needle替换为$replacement;str_replace()
,区分大小写,其余与str_ireplace()类似;trim()
,删除字符串首尾的空格、换行符、制表符;rtrim()
,删除最右端的空白字符;ltrim()
,删除最左端的空白字符;strtoupper()
,字符串转换为大写;strtolower()
,字符串转换为小写;substr_count($string, $substr)
,子字符串出现的次数;
PHP中所有索引的位置都是从0开始的。
- $evens = range (0, 100, 2); 创建等差数列;
日期和时间
说几个函数,有点印象就行,具体用法去查PHP手册:
date()
返回某一日期格式;date()
中第二参数为时间戳(timestamp),是表示从1970年1月1日算起的秒数;time()
返回当前时间戳;mktime()
返回一个给定日期和时间对应的时间戳;date_default_timezone_set()
设置时间默认的时区;date_default_timezone_get()
获取当前时间对应的时区;
额外说明几点:
- PHP是服务器端的技术,函数反映的是服务器上的时间,如果要获取客户端的时间,需要使用JavaScript;
- PHP 5.3中,加入一个创建、操作日期和时间的类:DateTime类;
创建函数
一个典型函数的格式如下:
//设置参数默认值
function function_name($arg1 = 'world', $arg2){
statements;
//函数的返回值(返回多个值:数组)
return $name;
}
说几点:
- 函数名,不区分大小写;
- 函数function_exists(function_name),用于判断一个函数是否存在;
- PHP中不要求:函数在调用之前就定义好,但,推荐在脚本开头就定义好函数;(放在引入文件中)
变量作用域
- 通常,变量作用域:整个脚本的声明周期中;
- 函数中传参数时,传递变量值,而不传递变量本身;
- 函数内部定义的变量,为局部变量;
- global可以将函数内局部变量设置为全局变量;
控制结构
几点注意:
{
、}
的前后,不能出现;
,否则报错;
几个验证函数:
empty()
,除去变量未定义、值为0、空字符串外,返回FALSE;isset()
,仅当变量未定义时,返回False;(能够接受任意个数的变量)is_numeric()
,仅当变量为数值时,返回TRUE;checkdate()
,验证日期是否存在;is_array()
,判断是否数组;
举例如下:
$var1 = 0;
$var2 = "";
$var3 = "HELLO!"
empty($var); //TRUE,没有定义的变量
empty($var1); //TRUE,空值
empty($var2); //TRUE,空值
empty($var3); //FALSE,非空(这个是这样吗?)
isset($var); //FALSE,变量未定义
isset($var1); //TRUE
isset($var2); //TRUE
if条件语句
if (condition1) {
statement(s);
} elseif (condition2) {
statement(s);
} else {
statements(s);
}
switch条件语句
switch($var),变量$var,可以为字符串、数值,在case后的value,如果是数值,则不需要加引号。
switch ($var) {
case value1:
statements1;
break;
case value2:
statements2;
break;
default:
statements3;
break;
}
循环语句
主要是for、while,以及foreach,不多说,给个示例:
while(condition) {
statement(s);
}
do {
statement(s);
} while (condition);
for (init_exp; condition ; closing_exp){
statement(s);
}
调试程序
调试程序有2种方式:
- 输出变量和错误信息;
- 用IDE,打断点,debug;
- 查看程序运行日志,特别是出错日志;
输出变量
- echo “$var”;
- print “$var”;
- print_r “$_SERVER”;
输出错误信息
安装PHP之后,默认安全配置下,是不允许向Web端输出任何出错信息的,即,display_errors
出于关闭状态;为了方便调试,有两种方法:
- 开启
display_errors
设置; - 为某些脚本单独开启
display_errors
设置;
当前首选第一个选项,但是只有root用户才有如此权限;普通用户,可以在php页面中添加代码:ini_set('display_errors', 1);
实现为某些脚本开启 display_errors
。说明:这种方式进行的设置,只在当前php脚本执行期间有效,脚本结束后恢复原始设置;display_errors
只能控制是否向浏览器发送错误信息,而不会控制错误的发生。
输出错误信息级别
通过设置display_errors可以实现输出错误信息,但是要输出哪一类的错误信息呢?警告信息要不要输出?
PHP中错误的类型,见下表:
类型 | 描述 | 示例 |
---|---|---|
通知 | 非致命性错误,程序不一定有问题 | 引用一个没有值的变量 |
警告 | 非致命错误,程序有问题 | 函数误用 |
解析错误 | 致命错误,语法错误 | 缺少分好、引号、圆括号、花括号 |
错误 | 致命错误,一般错误 | 内存分配问题 |
错误报告常量(不完整,完整版查看[PHP Manual]),见下表:
名称 | 描述 |
---|---|
E_NOTICE | 通知 |
E_WARRING | 警告 |
E_PARSE | 解析错误 |
E_ERROR | 错误 |
E_ALL | 所有错误(E_STRICT除外) |
E_STRICT | PHP代码修改建议 |
注:上面的常量,是二进制位掩码,可以使用按位运算符来对其进行组合,例如,php.ini中,|
、~
、&
;
两种方式可以设置错误提示级别:
- 全局设置:PHP配置文件php.ini中,调整error_reporting()级别;
- 局部设置:php脚本中,使用error_reporting()函数;
举例说明如下:
//不报告任何错误
error_reporting(0);
//报告所有错误
error_reporting(E_ALL);
//报告除通知之外的所有错误
error_reporting(E_ALL & ~E_NOTICE);
//所有错误以及代码修改建议
error_reporting(E_ALL | E_STRICT);
Web开发基本过程
Web开发的基本过程:
- 创建模版HTML文件;
- 从模版中抽取:页头文件、页脚文件;
- 将页头、页脚文件导入php主文件中;
include('file.php');
若include()函数失败,发出警告;require('file.php');
若require()函数失败,终止脚本;
- 通常两个php脚本来处理表单:一个显示表单,一个接收和处理表单数据;
- 让同一个脚本来完成整个流程更好;
- 检查变量是否设置:
isset($_POST['something']);
- 检查表单提交的方法:
$_SERVER['REQUEST_METHOD'] == 'POST'
;
- 表单粘性:若表单提交后出错,则,重新提交表单,希望能够记录初次填写的表单数值;
- <input … value=”<?php print $_POST[‘name’]; ?>” />
- 不要引用不存在的变量;在引用之前,判断是否存在isset()
- 用户提交的内容,直接显示在表单中有样式问题,可以使用htmlspecialchars();
- 发送Email
- 服务器上Email应用程序发送Email;
- 具体:调用函数
mail(to, subject, body)
; substr_count($_POST['eamil'], '@') == 1
,邮件验证;
- 输出缓冲,只能在服务器发出响应之前进行调用:
- header():
- setcookie():
- session_start():
- ob_start();开启输出缓存,output buffering;
- ob_end_flush();输出缓冲数据;
- ob_end_clean();删除缓冲数据,不进行传输;
- php.ini中可设置输出缓冲区的大写;
- ob_get_length();当前输出缓冲区的大小;
- ob_get_contents();获取缓冲区内容;
- ob_flush();输出当前缓冲区内容,以方便继续缓冲新内容;
- ob_clean();清空缓冲区内容,但后续仍会继续缓冲;
- HTTP头,header()函数
- 重定向:header(‘Location: index.php’);
- 重定向,接着使用函数,exit();
- 开启输出缓存:ob_start();
- 如果浏览器已经收到HTTP头,则headers_sent()函数返回TRUE;
cookie和session
cookie、session的作用:跟踪用户,记录用户信息。
什么是cookie
客户端保存用户信息的一种方式,服务器通过此信息识别用户身份;将从几点来介绍cookie:
- 建立cookie;
- 从cookie中检索信息;
- 删除cookie;
- 限制cookie的可选参数;
- 如何调试与cookie相关的问题;
- 如何传输和接收cookie;
cookie的访问时间和方式:用户输入URL后,浏览器会将cookie信息包含至HTTP请求内发送给服务器。额外几点说明:
- 服务器端的PHP和浏览器端的JavaScript都能发送、读取、删除cookie,这是两种脚本重叠的功能之一;
- cookie必须在服务器发送任何信息之前,从服务器发送到客户端;
- setcookie(name, value)函数,向浏览器发送cookie;
- 发送cookie,应位于整个HTML页面标签之前(<!DOCTYPE html … >);
- 若使用输出缓存机制(output buffering),则setcookie()可以位于PHP脚本中任意位置;
- cookie的总数,限制在4KB;
- headers_sent()函数可用与测试HTTP头部是否发送出去;
- cookie的值在发送时,将自动编码,接收时会自动解码;对于PHP表单发送的值也是如此;
- setcookie()函数在不同的浏览器中,有兼容性问题;
读取cookie
预定义的数组$_COOKIE中存储了所有cookie数据,按照key值,从数组$_COOKIE中读取即可。
向cookie中添加参数
函数setcookie(),具体用法如下:
//expiration:过期时间点,单位秒(s);默认关闭浏览器之前有效;
//domain:设置一个子域的cookie;
//secure:为1时,表示只能通过https传送;
//httponly:设置防止JS读取cookie,但不是所有浏览器都支持;
setcookie(name, value, expiration, path, domain, secure, httponly);
setcookie(name, value, time() + 3600);
setcookie(name, value, time() + 3600, '/subfolder/');
setcookie(name, value, time() + 3600, '', 'forum.example.com');
几点注意:
- cookie过期时间的选择:
- cookie持续时间如果同用户浏览网站的时间一样长,则,不需要设置过期时间;
- 如果需要cookie在关闭、重启浏览器之后继续存在,可将过期时间设置为数个月;
- 若cookie可能引发安全隐患,则可将过期时间设置为小于1h;
- 出于安全考虑,可以设定cookie过期时间为5min~10min,同时,让用户每访问一个新页面时,重新发送一次cookie;
删除cookie
删除cookie,本质就是设置一个空值,同时可以设置一个过去的过期时间:
//重设值,同时设置过去的过期时间
setcookie('username', FALSE, time() - 600);
特别提醒:删除cookie时,一定要使用与设置cookie一致的参数(除去值和过期时间)。
setcookie('user', 'larry', time() + 3600, '', 'forums.example.com');
setcookie('user', '', time() - 600, '', 'forums.example.com');
什么是session
session的数据保存在服务器端,cookie数据保存在客户端;由此,session比cookie拥有更多的优势:
- session通常更安全,因为数据不会在客户端、浏览器之间重复传输;
- session存储比cookie更多的信息;
- session能够在禁止cookie的浏览器上,继续工作;
几点说明:
- 开启一个session时,PHP会自动创建一个随机的session ID;
- 每个用户都拥有一个自己的Session ID,这也是服务器上存储该用户session数据的文件名称;
cookie相对于session的优势有:
- cookie相对容易创建和使用;
- cookie耗费服务端的资源少;
- 如果希望长期保存用户身份信息,则应采用cookie;
结论:
- 当保存数据较少,同时安全性要求不高时,推荐首选cookie;
- 保存数据较多或者敏感,同时安全性要求较高时,首选session;
创建session
session_start()函数用于创建一个session,并且在session首次启动时发送一个cookie,因此,必须在所有HTML响应发送回浏览器之前,创建session。 第一次开启session时,随机产生一个session ID,并向Web浏览器发送一个名为PHPSESSID(session的名称)的cookie。
一旦启用session,就可以通过向数组赋值的方式来存储数据:
$_SESSION['first_name'] = 'Sam';
$_SESSION['age'] = 14;
每次向session中添加数据时,PHP将向服务器上一个临时文件中添加一些数据:
//session数据在服务器文件中的存储方式
email|s:14:"me@example.com"; loggedin|i:1292;
关于session几点信息:
- php.ini中可以配置session信息;
- ini_set()函数可以设置session信息;
- session_name()函数可以修改session名称(默认名称PHPSESSID),注意:必须在调用session_start()之前使用;
- session_set_cookie_params()函数,用户修改session cookie的设置(过期时间、路径、域);
- 常量SID用格式name=ID的方式保存一个字符串;
- session中可以保存任意类型数据,甚至对象;
- 在session中,数据都会以纯文本的形式保存在一个开放可读的文本文件中;永远不要将真实的敏感信息存在session中,例如信用卡数据;
- 为提高安全性,可以将数据加密后保存到session中,在读取session后再解密(Mcrypt库);
删除session
服务器端session中包含的数据都保存在$_SESSION数组中,可以对数组重新赋值,以达到删除session的效果,但也需要删除服务器上保存session数据的临时文件,具体操作如下:
//重置session
$_SESSION = array();
//删除服务器端session临时文件
session_destroy();
函数unset($var),可用于删除一个变量,也能达到删除$_SESSION的效果;同时,如果浏览器禁用cookie,则可以在URL上添加session ID作为附属参数,以继续使用session,注意:需要在php.ini中启用enable_trans_side。
文件和目录
Web应用程序,不可避免两个问题:数据存储、检索数据。当前数据存储的方法主要有两种:文件(和目录)、数据库。这一部分,主要介绍一下文件的写入、读取和锁定。
疑问:读取、上传的文件,为什么在Web目录之外?
- file_exists(‘somefile.ext’),判断文件是否存在;
- is_readable()测试文件是否可读;
- touch(‘somefile.ext’),创建空白文件;
- chgrp()、chown()、chmod(),修改文件、目录权限;
- file_put_contents($file, $data),向文件写入数据;
- 文件不存在,则,函数主动创建;
- 文件存在,覆盖文件内容;
- file_put_contents($file, $data, FILE_APPEND),追加;
- 如果需要追加的内容独占一行,则需要在内容后,添加换行符,PHP专用常量 PHP_EOL 可以解决这一问题,file_put_contents($file, $data . PHP_EOL, FILE_APPEND)
- file_put_contents($file, $data, LOCK_EX);写文件同时锁定文件;
- 若同时追加文件、锁定文件,则,
LOCK_EX | FILE_APPEND
;
- 若同时追加文件、锁定文件,则,
- file_get_contents($file),一次读取文件所有内容;
- file($file),读取文件内容,并且返回一个数组,每个元素为原文件中的一行;
- 更多文件读取方式:fgets()、fgetcsv();
- filesize($file),返回文件大小(单位Byte);
- filetime($file),返回文件修改时间戳,可使用date()格式化;
- is_writeable()
- is_readable()
- is_dir()
- is_file()
- glob(),搜索名字与模式匹配的文件(*.jpg)
- fileperms(),文件权限;
- fileatime(),文件最后访问时间;
- fileowner(),拥有该文件的用户名称;
- basename()、dirname(),返回文件名、路径名;
- finfo_file(),文件的MIME类型;
- mkdir(‘dir_name’, permissions),创建文件;
- rmdir(),删除现有目录;
- fgets(),返回指定长度的字符串;
- feof(),判断是否达到文件末尾;
补充几点:
读取文件:PHP 4 以及以下版本,不能使用file_put_contents(),需要按照旧方法来写数据:打开文件、写数据、关闭文件;
//文件模式mode,查PHP手册很详细
$file_pointer = fopen($file, mode);
fwrite($file_pointer, $data . PHP_EOL);
fclose($file_pointer);
上传文件:通过表单上传,修改3处:
- form表单添加enctype,即 <form action=… enctype=”multipart/form-data” method=”post” >;必须使用POST方式;
- 添加银行输入框:,用于建议浏览器最大能够上传的文件;
- 使用file元素,创建所需的表单:,file类型允许用户上传一个文件;
PHP脚本中,使用$_FILES变量能够引用上传的文件。$_FILES数组包含5个成员:
- name,用户上传文件的原始名字;
- type,文件MIME类型,例:image/jpg;
- size,文件大小(单位Byte)
- tmp_name,文件存放在服务器上的临时文件名称;
- error,发生错误时,保存的错误代码;(查看PHP手册)
文件上传之后,需要将临时文件移动到最终目标位置:
//将临时文件移动到最终位置
move_uploaded_file($_FILES['pic']['tmp_name'], '/path/filename');
一个php脚本可以同时处理多个文件上传,只要name属性不同即可,此时只需要一个隐含输入框设定MAX_FILE_SIZE。另外,针对移动文件的函数小结:
- move_uplodaded_file(),将上传的临时文件移动到最终位置;
- unlink(),删除文件,不会进行移动或者复制;
- copy(),复制文件;
上传文件时,有几点注意:
- php.ini中,开启file_uploads配置;
- php.ini中,设置upload_tmp_dir,如果没有设置,可能会指定一个隐含值;
- php.ini中,upload_max_filesize和post_max_size用于设定PHP能够处理的文件大小;
- form中隐含input元素中设定的MAX_FILE_SIZE只是在前端浏览器处,进行的约束;
- 当缺失要上传大文件时,除了上述相关的配置,还应设置两个参数:memory_limit、max_execution_time,来给PHP脚本足够的处理时间和空间;
目录相关
浏览目录:
- scandir($dir),返回目录下所有内容,一个数组:包含文件和子目录;
- 旧版本的PHP中,需要使用opendir()、readdir()、closedir();
数据库MySQL
PHP中操作MySQL数据库,基本过程,连接数据库、操作、释放连接,具体几点:
- $dbc = mysql_connect(hostname, username, passwd),获取数据库连接
- mysql_query($query, $dbc)
- mysql_query(‘create database somedb’, $dbc);
- mysql_select_db(‘somedb’, $dbc);
- $result = mysql_query($query, $dbc), 执行$query
- mysql_num_rows($result),返回查询结果的个数,可用于删除、查询之前判断?
- $row = mysql_fetch_array($result),每次返回一行数据,形式:数组;
- mysql_fetch_array($result, MYSQL_ASSOC or MYSQL_NUM),关联数组、索引数组;
- while( $row = mysql_fetch_array($result) ){ … },用于遍历结果;
- mysql_affected_rows(),返回INSERT、DELETE、UPDATE等影响到的行数;
- msyql_close($dbc),释放连接
PHP中对MySQL的支持
PHP操作MySQL,根据扩展不同,分为两类:
- 标准MySQL,支持所有MySQL版本,函数以
mysql_
作为前缀; - 扩展MySQL,MySQLi(Improved MySQL Extension),PHP5之后引入的,支持MySQL4.1以上的版本,能够利用MySQL的一些额外特性,函数以
mysqli_
最为前缀;
MySQL错误处理
常见的错误类型有:
- 连接MySQL失败;
- 选择数据库失败;
- 无法运行查询;
- 查询没有返回结果;
- 数据没有插入到表中;
具体说几点:
- mysql_error(),显示发生错误的详细信息;
- 错误控制符
@
,在函数名之前使用,阻止显示错误信息,但并不能阻止错误的发生,仅当希望自己处理错误时,才使用@
; - 错误控制符
@
,可以用于阻止任何函数的错误、通知、警告,而不仅限于MySQL相关函数;
关于PHP中使用MySQL,具体说几点:
为避免SQL注入攻击,可随意用mysql_real_escape_string()函数,来转义危险字符:
$var = mysql_real_escape_string($var, $dbc);
注意几点:
- 所有文件编码方式需要与HTML中指定的charset一致;
- 如果为UTF-8编码方式,则,必须为UTF-8 without BOM方式;
- 通过include(‘path/file.php’),路径为相对与最终php脚本的位置;
- include_once()、require_once(),表示同一个文件只包含一次;
特别说明
PHP基础教程(第4版)的附录部分,有很多进一步学习的建议。
参考资料
原文地址:https://ningg.top/php-intro/