项目开发常见流程介绍
需求调研
项目经理------>需求说明书
软件设计书
项目经理------>详细设计说明书——通常这就是开发过程中的主要参考技术文档。
界面设计
UI------>设计效果图
前端和后端
前端和后端工程师------>项目主体
测试
测试工程师------>产品是否符合需求,bug处理
上线运营
运维工程师------>发现问题,提出新需求,提出改进建议等等
MVC框架思想原理
MVC 全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC 被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
Model(模型)表示应用程序核心(比如数据库记录列表)。
View(视图)显示数据(数据库记录)。
Controller(控制器)处理输入(写入数据库记录)。
控制器(controller)
Controller,是一个PHP文件,由浏览器直接请求(访问);
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
它需要做2件最核心的工作:
1,(根据请求),决定需要什么数据,并去调用模型文件(类),去获取该数据;
2,(根据请求),决定需要将数据显示在哪个视图文件中。
模型(model)
Model,是一个PHP文件,不能直接请求,只能“被载入”而发挥作用。
它的核心工作只有一个:
(根据控制器的要求)去生产数据;
视图(view)
View,是一个“伪html文件”(因为其中有极简单的php代码),它也不应由浏览器直接请求;
它的作用是:
结合html和css代码,显示相应的变量(数据)。
模型层(Model)的典型实现
模型层的主要作用:用于处理数据的存储操作,比如表的增删改查;
通常是根据控制器的要求,返回合适的数据。
有时候控制器还会 传递过来 相应的数据,比如post ,get, 根据传递过来的数据才能取得对应结果的数据,比如 获取 id 为1的用户的数据,此时控制器就会传递数据 1 过来;
模型层的典型代码模式
class 模型类名{
function 方法1(){ }
function 方法2(){ }
function 方法3(){ }
}
说明:1 每个方法都是为了获取 某种数据;
2 有的方法需要一些参数;
3 这些方法通常跟数据库打交道,就需要require mysqldb工具类来处理;
控制器中调用模型层获取数据的典型做法
require ‘模型层类文件’;
$obj = new模型对象();
$data = $obj->某个方法();
include ‘需要的视图文件来展示’;
基础模型类
所有模型类,都需要跟数据库打交道,也就是进行数据库的操作,则我们将所有模型类的共同部分——mysqldb工具类(的实例)——放如一个共同的父类中,这就是基础模型类;
项目中都要运用到的工具类,其他类可以继承该基础模型类,不用在自己的类中重复书写,增加代码的冗余,比如连接数据库就可以当做基础模型类,其他类可以继承他。
实现模型类的单例——单例工厂
设计出这样一个“单例工厂类”,通过该单例工厂类,去“获取”模型类的对象(实例);
控制器的典型实现
控制器的作用:获取请求的数据;根据请求的信息,来决定,调用哪个模型以获取什么数据;根据请求信息,载入哪个视图以显示该数据。
步骤
1,用于获取用户的请求数据,
2,获取模型数据,
3,显示到视图中——或也可能直接输出;
控制器中的“动作”
一个控制器,就是一个类;
一个控制器中,就只包含了一些方法,那么,这些方法,被称为“动作”—— 因为每个方法,一定就对应了网页界面上用户所在的某个“操作”(动作,请求);
<a href="?act = del & id =2">XXXXX</a>
对应控制其中的若干个方法。
习惯上,所有的动作(方法),都以“Action”这个词为结尾。
这些动作(方法名),将会对应网页上的连接(或跳转或提交)动作中的“act”参数的值!
基础控制器
每个控制器都有各自的一些功能,但有时候都会做一些相同的事情,为了减少代码的冗余,可以写在基础控制器类里,这样就可以继承该基础类,实现共用相同的功能。
视图层的典型做法
视图层的作用:展示页面的静态内容,以及相关的变量数据。
数据分为:
普通标量数据:echo $v1;
数组数据:foreach($arr as $key => $value){....}
或单独输出:echo $arr[‘id’]; echo $arr[‘age’]; .....
对象数据: echo $obj->p1; echo $obj->p2;
其他MVC的做法(前端控制器(请求分发器))
作用
1,根据传过来的c请求数据,决定使用哪个控制器;——有默认值,目前为User
2,根据传过来的a请求数据,决定使用哪个动作(方法);——有默认值,目前为Index
视图层的做法
<a href="? c= User & a = XX方法">内容</a>
<a href="? c = 其他控制器 & a = XX方法> 内容</a>
MVC项目目录 (加入平台 的划分)
平台 (platform ),在实际开发的目录结构中常用 Application(应用)命名。通常一个网站分为:前台,后台。
这些平台也都需要公用一些基础的类。因此,这个MVC项目的目录可以划分为一下形式:
MVC项目/
index.php
/Framework/ 共用的类
BaseController.class.php
BaseModel.class.php
ModelFactory.class.php
MySQLDB.class.php .....
/App/ 所有平台总目录
/front/ 前台
/Controllers/
XX1Controller.class.php .....
/Models/
XX3Model.class.php .....
/Views/
page1.htm.........
/back/ 后台
/Controllers/
XX1Controller.class.php .....
/Models/
XX3Model.class.php .....
/Views/
page1.htm.........
PDO
PDO是别人写的“数据库操作工具类”! 类似于上面的 MySQLDB.class.php
$pdo = new PDO(连接信息);
$sql = “select * from .....”;
$result = $pdo->query($sql); //返回一个“pdo结果集”;
$sql = “delete / update / insert ........ ”;
$result2 = $pdo->exec($sql); //返回一个真假值;
PDO引擎在 php.ini的配置文件中打开 extenSion= php_pdo_mysql.dll
使用pdo连接数据库
$DSN = "mysql:host=服务器地址/名称;port=端口号;dbname=数据库名";
$Opt = array(PDO::MYSQL_ATTR_INIT_COMMAND=>’set names 连接编码’);
$pdo = new pdo($DSN, "用户名", "密码", $Opt);
pdo对象的使用方法
① $result = $pdo->query(‘返回结果集的sql语句’);
原生语句: mysql_query(‘select.....’)
结果:返回布尔类型 ; 成功->返回pdo结果集;失败->false
② $result = $pdo->exec(‘增删改的sql语句’);
结果:返回布尔类型 ; 成功->true;失败->false
③ $pdo = null; 销毁该对象
④ $pdo->lastInsertId(); 获取最后添加的id值;
⑤ $pdo->beginTransaction(); 开启一个事务
⑥ $pdo->commit(); 提交一个事务
⑦ $pdo->rollBack(); 回滚一个事务
⑧ $pdo->inTransaction(); 判断当前行是否在事务中,返回true/false
⑨ $pdo->setAttribute(属性名,属性值); 设置pdo对象的属性值;
比如:$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
pdo的错误处理
静默模式
默认情况下,pdo采用“静默模式”处理错误:
就是发生了错误后,并不提示,而只是返回false。我们需要在程序中去判断返回是否为false,然后,如果是false,再去“主动”获取错误信息。——跟mysql一样!
比如 select 语句出错的时候会返回false 要调用 mysql_error()
异常模式
pdo结果集
$stmt = $pdo->query(“select .....”); 执行成功, 则$stmt 就是pdo的结果集对象;
pdo结果集对象的常用方法
$stmt = $pdo->query(“select.....”); //获得结果集
$stmt -> rowCount(); //获得结果集的行数
$stmt->columnCount() ; //得到结果集的列数
$stmt->fetch( [返回类型] ); //从结果集中取出“一行”数据;取出的结果,由其中的“返回类型”来决定,常用的有:
PDO::FETCH_ASSOC:表示关联数组
PDO::FETCH_NUM:表示索引数组
PDO::FETCH_BOTH:表示前二者皆有,这是默认值
PDO::FETCH_OBJ:表示对象
$stmt->fetchAll([返回类型]);一次性获取结果集中的所有数据,返回的是一个二维数组
$stmt->fetchColumn( [$i] );获取结果集中的“下一行”数据的第$i个字段的值,结果是一个“标量数据”,相当于我们自己的写的:GetOneData()
$stmt->fetchObject();
$stmt->errorCode();:pdo结果集的错误代号
$stmt->errorInfo(); pdo结果集的错误信息(是一个数组)
$stmt->closeCursor();关闭结果集(相当于mysql_close() )
pdo中的预处理语法
就是,为了“重复执行”多条结构类似的sql语句,而将该sql语句的形式“进行预先处理”(编译);
该sql语句的“形式”中,含有“未给定的数据项”。
然后,到正式执行的时候,只要给定相应的形式上的“数据项”,就可以更快速方便执行。
预处理语句的好处: 查询仅需解析(或预处理)一次,但可以用相同或不同的参数执行多次。
语法1
$sql = “select * from tab where id = ? “; //这里这个“?”就是未给定的数据项;这里通常叫做“占位符”;
语法2
$sql = “select * from tab where id = :v1 and name = :v2 “; //这里这个“:v1”和 “:v2”就是未给定的数据项;通常这里叫做“命名参数”;
使用
1,对含预处理语法的sql语句进行“预处理”:
$stmt = $pdo->prepare( $sql ); //
2, 对上述预处理的结果对象($stmt)的未赋值数据,进行赋值:
$stmt->bindValue(数据项1, 值1);
$stmt->bindValue(数据项2, 值2);
。。。。。。
3, 执行执行:
$stmt->execute();
语法1 占位符的处理形式
语法2 命名参数的处理形式
会话技术
在同一台浏览器的多次请求周期内,持久性存储数据一种技术。
基础:HTTP的无状态性。
B/S 架构基于HTTP协议进行数据交互。
HTTP请求/响应,是独立的,每次请求响应周期都是完全独立的。
会话:想办法,将数据可以在多次请求周期内,传递存储下来。
两种实现:cookie 和 session
cookie
允许服务器端程序(PHP)在浏览器上存储数据的一种技术。内容有服务器端写入,存入浏览器后,在下一次浏览器向服务器发出请求时,会携带该服务器所存储的数据。
形式:setcookie(键,值);
服务器端获取:使用超全局变量 $_COOKIE
cookie的属性
①有效期(重要) 第三个参数
默认:浏览器关闭(会话周期结束)时,COOKIE失效。也叫做会话COOKIE(临时COOKIE);浏览器来判断cookie的过期时间。
设置:setcookie的第三个参数是有效期
setcookie(‘键’,‘值’,‘有效期’);
默认值:0,表示临时 cookie;
PHP_INT_MAX常量值:PHP所能表示的最大整型;
time()-1:删除cookie的通用做法,强制设置为过期。PHP的setcookie支持将第二个参数设置为空字符串的方式,也表示删除。
②有效路径 第四个参数
cookie在当前目录及其后代目录有效,即后代目录可以访问到当前和父级的cookie ,而父级目录中访问不到子代的cookie信息。
语法使用空字符串表示默认值!
通过setcookie函数的第四个参数,进行设置。通常如果需要设置,就是将COOKIE设置为 / 根目录下有效,表示整站有效。
setcookie(‘键’,‘值’,0,‘/’);
③有效域名(使用频率较高) 第五个参数
默认的:某个域名下设置的COOKIE,仅仅可以在当前域名下所使用。但是现在稍大点的网站,都会使用子域名(二级域名)的方式划分业务逻辑,比如:News.baidu.com. music.baidu.com,就是baidu.com下的子域名(二级域名)。
COOKIE,支持在一级域名内(所有的二级域名之间)进行COOKIE数据共享。
setcookie(‘键’,‘值’,0,‘/’,‘.baidu.com’);//所有baidu.com下的子域名都有效
④是否仅安全连接(https)传输 第六个参数
告知浏览器,我们所设置的cookie,是否仅仅在https这个协议下,才会被发送到浏览器端。
默认值false,表示http 和 https 都可以
setcookie(‘键’,‘值’,0,‘’,‘’,false);都可以
setcookie(‘键’,‘值’,0,‘’,‘’,true); 仅仅安全传输
⑤HTTPONLY 第七个参数
所设置好的COOKIE,是否仅仅在http请求时所使用。
COOKIE还可以通过浏览器端的脚本(javascript)获取到。
默认值false
总结:Setcookie(键,值,有效期=0,有效路径=‘’,有效域名=‘’,是否仅安全连接传输=false,是否HTTPonly=false)
其他说明
COOKIE仅仅支持字符串类型数据
$_COOKIE,仅仅用来存储浏览器请求时携带的COOKIE数据
COOKIE中存储了可以认定当前浏览器处于登陆状态的信息才可以完成!
通常保证存储的信息具有以下特点:
可验证性。
保密性(安全性)。
通常可以采取,存储 加密处理后的管理员ID 和密码的组合!
session
session 和 cookie 对比
cookie的劣势:存储在浏览器端,就带来了 安全性问题 和 请求数据的大小限制问题;
session技术优化了这些问题: session 是以文本文件形式存储在服务器端的,所以不怕客户端修改 Session 内容,也没有文件大小的限制。
实现方式如下:
在服务器端,建立很多的会话数据区(session数据区),默认,每个session会话数据区,就是一个独立的文件。存储于服务器所在操作系统的临时目录中。
为每个session会话数据区分配唯一标识
将该唯一标识,分配给对应会话浏览器,也可以说session 基于cookie。
形式:开启session session_start()
每次使用session 都必须先开启。PHP支持自动开启,在php.ini里面设置
session.auto_start = 0; 默认值
不建议自动开启
session不能重复开启,一旦重复开启,后面的开启会被忽略,并有一个notice级别的错误,通常我们在开启时,增加@来屏蔽错误。@seeion_start();
开启后,所有关于session机制(生成session_id,)都由session机制(PHP提供的session相关功能)完成。
使用全局变量 $_SESSION 来操作session
$_SESSION【键】 = 值;
浏览器端存储session-ID
服务器端session会话数据区
默认,每个session会话数据区,就是一个独立的文件。存储于服务器所在操作系统的临时目录中。
session支持储存多类型(数据在session会话数据区,采用序列化的方式进行存储。)
Session属性
有效期:默认关闭浏览器!
有效路径:/ 默认整站有效
有效域名:默认仅在当前域名下有效!
是否仅安全连接传输:默认为非
是否HTTPONLY:默认为非;
session 属性的修改
设置COOKIE中session-ID这个COOKIE变量属性即可!
方案① 在 php.ini 中设置 默认值为
session.cookie_lifetime = 0;
session.cookie_path = /;
session.cookie_domain = ;
session.cookie_secrue = ;
session.cookie_httponly = ;
方案② 在脚本中,session 开启之前进行配置
ini_set(配置项,值);
或者
Session_set_cookie_params(有效期,有效路径,有效域,是否仅安全连接传输,是否HTTPONLY);
在实际项目中 很少修改 session 的有效期。经常改有效域名。
session 数据区操作
Session数据区默认以文件的形式存储与服务器操作系统临时目录中!
当session数据区过多时,文件形式的存储,操作速度变慢。磁盘的读写(IO,input/output)开销是很大的。
实际项目中,都会采用其他的方式更快地存储session数据。典型的办法:数据库,内存。
重写session的存储机制
创建session表,该session中,每条记录,就是一个session数据区,相当于原来的一个session文件。
1 设置自定义的session存储机制
session_set_save_handler(
开始函数,结束函数,读函数,写函数,删除函数,GC函数
);
2 读操作:sessRead($sess_id) 形参是session_id;
在PHP的session机制调用该函数时,会将当前的session-ID作为参数传递到函数中:因此,需要定一个形参,接受传递的session-ID 参数:
需要返回 读取到的session数据字符串。就是sess_content字段的内容。如果没有读到,则返回空字符串即可,表示没有session数据。
3 写操作:sessWrite($sess_id,$sess_content); 两个形参一个是session_id ,一个是需要写入的内容sess_content
4 删除操作:sessDelete($sess_id)
销毁session时,执行了PHP函数:Session_destroy();
可以销毁session,删除对应的session数据区,同时关闭session机制!
5 垃圾回收操作:sessGC($maxlifetime); 一个形参,最大有效时间
垃圾:服务器上过时的session数据区。
如何判断session 过时
如果一个session数据区已经超过多久没有使用(最后一次写操作)了,就是被视为垃圾数据。
默认1440s。在 php.in 中 session.gc_maxlifetime = 1440; 进行修改
根据 最后写入时间,就可以断定是否为垃圾。
判断条件:Last_write < 当前时间-1440 即为过期。
在session_start()过程中,开启session机制过程中:有几率地执行垃圾回收操作。一旦执行,就会删除所有的过期的垃圾数据区。
默认的概率为1/1000。
可以设置该几率: php.ini 中 session.gc_probabliity = 1;
基数 session.gc_divisor = 1000;
6 开始操作sessBegin()
初始化工作,可保证在第一个执行。将初始代码,在sessBegin完成。
7 结尾操作sessEnd():
收尾性工作 一般没什么运用。直接Return true;
说明
1 session的重写存储机制要在session_start()之前,所以不建议开启session自动开启机制;
2 在php.ini中 默认的 session存储机制为文件机制
session.save_handler = files ;
改为 用户自定义
session.save_handler = user;
session_set_save_handler(
‘sessBegin’,‘sessEnd’,‘sessRead’,‘sessWrite’,‘sessDelete’,‘sessGC’
);
ini_set(‘session.save_handler’,'user');
会话技术总结
session 和 cookie 的区别和联系
联系:两者均为会话技术,session 基于 cookie ,session_id存储于cookie中。
区别: Cookie session
存储位置 浏览器端 服务器端
安全性 低 高
大小限制 有 没有
数据类型 字符串 全部
有效期使用 长时间存储 几乎不做持久化
session 的持久化【理论】
Session-ID要持久化:session_set_cookie_params(3600);
服务器session数据区有效期修改:ini_set(‘session.gc_maxlifetime’, 3600);
浏览器禁用cookie,session 是否可用【理论】
通过URL,或者POST数据数据向服务器端,每次传输session-ID;
php.ini Session是否仅仅是用COOKIE完成传输session-ID
默认情况下
session.use_only_cookies = 1
session.use_trans_sid = 0;
修改之后常规使用即可,不推荐。
PHP绘图技术:图像处理技术-验证码
验证码技术:生成图片技术;验证时:将码值存储与session中。
PHP绘图技术:图像处理技术 ,使用GD库完成。
首先加载扩展 php.ini中 extension = php_gd2.dll;
创建画布资源
创建新的画布
画布资源 = Imagecreate(宽,高);创建基于调色板画布(支持的颜色少);
画布资源 = Imagecreatetruecolor(宽,高);创建正彩色(支持的颜色多);
基于已有的图像创建画布
画布资源 = Imagecreatefromjpeg(图片地址);
画布资源 = Imagecreatefrompng(图片地址);
画布资源 = Imagecreatefromgif(图片地址);
操作画布
分配颜色:为某张画布分配某种颜色;颜色的表达形式用RGB表示。
颜色标识 = Imagecolorallocate(画布,颜色R,颜色G,颜色B);
填充颜色:使用某个颜色,在画布的某个位置进行填充。
imagefill (画布,位置X坐标,位置Y坐标,颜色标识);
导出
imagepng(画布,图片地址); 导出png格式的地址
imagegif(画布,图片地址);
imagejpeg(画布,图片地址);
如果第二个参数不使用,表示直接输出到浏览器。
需要,告知浏览器,所输出的为图片,否则浏览器会将所有的响应内容当作html代码字符串处理!
header(‘Content-type:image/png’);
销毁资源
imagedestory(图片);
补充
图片宽高:
宽= Imagesx(画布);
高= Imagesy(画布);
内置字体的宽高:
imagefontWidth(字体);
imagefontHeight(字体);
图片程序的错误处理
图片程序很多时候不会报错,解决方法:
① 直接请求生成图的url,看是否有图片生成,或者看它的url的地址跳转情况;
② 如果出现一段文字报错,例如:图像‘http://............’因存在错误而无法显示。将header(‘Content-Type: image/jpeg’)注释上!
会出现详细的报错信息。
③ 编码不规范,导致存在额外的输出
建议(要求):写PHP程序,所有的程序文件,保证PHP标记要开头!而且同时不要写结束标记!
④ BOM,取消掉UTF-8文件的签名。
文件上传
当浏览器需要文件上传时,要在表单 form 元素中增加属性,
Enctype = 'multipart/form-data' 编码类型= 多部分/表单-数据
服务器脚本PHP将接收到的文件,存储在上传临时目录中。默认为服务器所在操作系统的临时目录。该临时文件有效期为脚本周期,所以需要将该文件移动到 固定的上传目录中去。
方法: Move_uploaded_file(临时文件地址,目标文件地址);
通过 超全局变量$_FILES 获得所有的上传文件的信息。
错误类型【error】
0:没有错误
1:文件超过了PHP中对上传文件大小的设置
2:文件过大,超过表单中元素
3:文件没有上传完
4:没有上传文件
5:上传的文件大小为0,上传的为空文件(PHP 没有定义这个错误!)
6:临时上传目录未找到
7:临时文件写入失败(磁盘空间不足,权限不允许)
相关设置
php.ini中设置
上传文件数量:max_file_uploads = 20;(默认);
POST数据大小:post_max_size = 8M;(默认);文件仅能用post方式提交
实际开发中典型的上传实现
先 判断 文件是否存在错误,类型,大小是否符合要求........
然后 满足条件的文件 再移动。
① 判断是否错误
② 判断文件类型
两种方式:① 后缀名 ;② MIME类型。
后缀名:在原始文件名中截取;
MIME类型:在$_FILES['type'] 中获取。
③ 判断大小
④ 设计目标文件位置并移动
函数:uniqid(), 生成唯一字符串!
分子目录存储上传文件
分类方式
为了减少一个目录中文件过多,划分成不同的子目录,划分形式:
① 按照业务逻辑:商品图片,用户logo。指定不同的upload_path即可。
② 文件数量:每个目录存储2000个文件,数量达到,则创建新子目录。
③ 时间划分:每个规定时间(比如每个月)使用一个新的子目录。
以时间划分为例:
获取当前应该使用的子目录:date();
判断需要的目录是否存在:is_dir(文件路径)是否为一个目录
创建需要的目录:mkdir(文件路径)创建目录
文件上传的安全性
$_FILES中的type的信息,不是PHP检测出来的,而是浏览器提供的。
因此,出于安全性的考虑,PHP也要对上传的文件类型作出检查,不能完全相信浏览器的数据。
PHP检测MINE类型,需要用到扩展库 fileinfo 来完成;
开启fileinfo扩展 extension = php_fileinfo.dll;
返回的是MINE类型
Is_uploaded_file();
判断临时文件,是否为真实的上传文件!
多文件上传
① 表单元素的 name 值不同
需要处理那个,就使用哪个数组即可!
②表单元素的 name 值相同
目录操作
创建
Mkdir(目录地址, 权限, 是否递归创建)
默认不支持递归创建
权限参数在windows下没有作用,在linux下有用。
删除
Rmdir(目录地址);返回布尔值
不允许删除非空目录!
重命名(移动)
Rename(原始地址, 目标地址);
针对文件和目录
获取目录内容
句柄= Opendir(目录地址);
句柄:PHP程序与文件系统数据流通道。
文件名= Readdir(句柄); 返回文件名
通过句柄,从目录中读取一个文件(包括文件和子目录),一次读取一个文件,并向下移动文件指针!(文件指针和数组的指针类似)
注意,每个目录下都存在 ., .. 虚拟目录。表示当前目录,和上级目录。
循环获取文件目录下的所有文件
但是无法在进入文件夹读取文件夹里的内容,要使用递归去获取目录下的说有文件。
Closedir($handle); 关闭句柄
实例:递归获取目录内容
将某个目录内包括其后代目录内全部内容读取到。
实例:递归删除目录
Rmdir()只能删除空目录!
当删除一个目录时,将目录内容删除掉之后,再删除目录本身。
删除文件:unlink(文件地址)
文件操作
读写基本操作
写操作:将文件内容写入文件中
写入长度(字节)= File_put_contents(文件地址,内容);
默认为清空写,将原来文件的内容清空,然后再写;
使用第三个参数FILE_APPEND 表示添加写
File_put_contents(文件地址,内容,FILE_APPEND);
读操作:将内容从文件中读取
文件内容= File_get_contents(文件地址);
函数:nl2br(文件内容); 读取文件内容,将换行符转换为br,在浏览器上就可以显示换行;
删除文件:Unlink(文件地址)
文件移动(重命名):Rename()
文件大小:大小int =Filesize(文件地址)
文件是否存在:布尔= File_exists(文件地址);
文件的最后修改时间: 时间戳= Filemtime(文件地址)
文件句柄读写操作
基本单位是字节;大多说的文件读写都是file_put_contents,file_get_contents完成,但是当文件过大时,只能一部分一部分操作。
①打开文件句柄
Fopen( 文件地址,打开模式); 打开文件句柄,PHP程序与文件间数据通路。
打开模式:R: read, 读模式;W: write, 写操作,清空写(打开文件时,完成了清空的操作);A: append,写操作,追加写。
② 读 fread(),fgetc(),fgets(),feof();
一个字节数据= fgetc(句柄);
每当读取到一个字节,将文件指针向前移动一个字节!
字符串= fgets(句柄,长度); (重点,常用)
从文件指针位置,读取指定长度的字符串内容!如果在读取时,先读到了换行符,也会终止。所以也叫读行函数。一般我们将长度设为1024。
配合函数 feof() 【end of file】来判断是否到达文件末位。
字符串 = Fread(handle,长度);
依据长度读取内容,不受换行符的限制。
③ 写 fwrite();
写入长度= Fwrite(句柄,内容);
根据打开文件句柄的模式,运用 追加写 还是 清空写。
④ 关闭 fclose(句柄); 关闭句柄
指针操作函数
fseek(句柄,位置):定位指针,默认从0开始,递增;
Ftell(句柄): 返回句柄位置
打开模式
基本模式:R: read, 读模式;W: write, 写操作,清空写(打开文件时,完成了清空的操作);A: append,写操作,追加写。X :新建写,只能新建文件进行操作,就是写操作,与w类似。
扩展模式:扩展的操作,都可以完成读写操作,差异与基本模式一致。
R+ 读写,打开任意文件(无论是存在还是不存在),文件内容不会被清空,依据指针位置,完成读,写操作。其中,写,会替换原有指针位置字节。
W+ 读写,打开时,同时清空内容,之后指针在哪里,就在哪里完成读写!与R+唯一的差异,就是会清空文件内容!
A+ 读写,打开任意文件,不会清空内容,指针仅仅影响读操作。不影响写操作,仅仅可以在末尾写!
X+ 读写,新建才能打开,依据文件指针位置,进行读写操作!
文件并发操作(文件锁)
默认的,PHP的文件操作函数,不是阻塞状态。自由操作状态。
当需要,一个脚本操作而需要阻塞另外的脚本操作时,需要用到文件锁。
锁操作流程:先加锁,检测锁是否加成功,如果成功再使用.
锁类型
读锁: s-Lock(share-lock)共享锁,读操作前,期望增加的锁定。导致,允许并发读,阻塞额外的写操作。
写锁: x-lock(exclusive-lock)排他锁,独占锁,写操作前,尝试添加的锁定类型。导致,其他脚本不能读也不能写。
意向锁:所有的操作资源的脚本都遵循一个约定来使用文件锁(约定)。
函数:Flock(句柄,类型);函数用于添加PHP 的文件锁定。(添加意向锁。)
类型:LOCK_SH 读锁;LOCK_EX 写锁
LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。通常与LOCK_SH或LOCK_EX 做OR(|)组合。
$lock_result = flock($handle,LOCK_EX | LOCK_NB);
解锁
Flock($handle, LOCK_UN)来强制解锁;
Fclose()自动解锁。
HTTP
http是一种协议,约定,规范,语法。
http:超文件传输协议,应用层协议。规范 浏览器 与 服务器 间数据交互格式。
规范:请求数据格式 和 响应数据格式。
请求数据格式
以上就是典型的get请求的数据,
浏览器(请求代理端)需要,将数据整理成以上的格式,向服务器端发送才可以。
以上数据共2个部分:
请求行request-line,请求头request-header
还有上面的数据没有展示的部分:
请求主体request-content。
请求行
请求数据的第一行,请求的摘要信息。
表示:请求方法请求的资源地址使用的协议版本
请求头
浏览器向服务器传输的请求属性信息。浏览器需要服务器知道的浏览器的状态。
例如:
User-Agent: 用户代理,谁(什么)发出的这个请求。
Accept-Language:请求代理端(浏览器)可以接受的语言类型。
Accept:请求代理端(浏览器)可以接受的,内容类型。
Accept-Encoding: 请求代理端(浏览器)可以接受的编码类型,指的压缩相关。
Host: 请求的主机名。
Connection:连接类型。http/1.1 新标准。响应结束是否立即断开TCP连接。
值:keep-alive,短时间内保持连接。Close:立即关闭。
Cookie:携带的COOKIE!
语法上:
每行表示一个头。
行结束采用的是:回车+换行。 \r\n , 称之为CRLF
头由标识和内容组成,由冒号分隔!冒号要紧跟着标识。
头以空行结束。
请求主体
请求的主体数据。
通常在使用POST方式发出请求时,POST数据就在请求主体中传输!
操作请求
在服务器端接受到浏览器请求后,利用相应的请求信息完成操作
①返回来源页
利用请求头当中的来源完成的:
Referer表示请求来源!
实际项目中,比如登录后,可以知道登录之前的页面是什么,登录之后会跳转到请求来源的页面中。
响应数据格式
典型的响应数据,分成三部分:
响应行:响应的第一行
协议版本响应状态码状态消息
状态码:响应结果。与状态消息一一对应的。
告知浏览器(请求代理端),当前响应的结果。
常用的状态码:
200 ok 成功
404 Not Found 请求资源不存在
403 Forbidden 请求被拒绝
302 Found 重定向
500 Server Internal Error 服务器内部错误,web服务器出了问题。
系列:
1xx:信息;2xx:成功;3xx:重定向; 4xx:客户端错误;5xx:服务器错误
响应头:服务器需要浏览器知道一些信息。
服务器需要浏览器知道的信息
Date:响应时间
Connection:连接类型
Keep-Alive:保持连接的实效
Content-Type:主体类型
Content-Length: 主体的长度(字节)
Set-Cookie:设置COOKIE的
语法与请求头一致:
CRLF行结尾
空行表示头结束
响应主体:主体数据,用于展示
任何的输出都为响应主体。
浏览器源代码中查看的内容,就是响应主体。
操作响应
Header()函数 操作响应头的。
比如:header(‘Set-Cookie:name = 123’);
控制浏览器缓存
Expires控制响应的有效期的
表示方式,特定格式的GMT时间:
Tue,24 Apr 2018 03:12:02 GMT
Date()将一个时间戳,格式化成本地时间!
Gmdate()将一个时间戳,格式化成GMT时间。
告知浏览器不要缓存
通常,验证码,程序,就需要告知浏览器,不要缓存验证码的图片。
文件下载
http下载:告知浏览器,将浏览器接受到的响应主体,以附件的形式进行存储!