PHP中MVC 开发

项目开发常见流程介绍

    需求调研

     项目经理------>需求说明书

    软件设计书

     项目经理------>详细设计说明书——通常这就是开发过程中的主要参考技术文档。

    界面设计

     UI------>设计效果图

    前端和后端

    前端和后端工程师------>项目主体

    测试

    测试工程师------>产品是否符合需求,bug处理

    上线运营

    运维工程师------>发现问题,提出新需求,提出改进建议等等


MVC框架思想原理

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-ID
浏览器请求头

                    

                    服务器端session会话数据区

                    默认,每个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数据。

sessRead($sess_id)

                    3 写操作:sessWrite($sess_id,$sess_content);  两个形参一个是session_id ,一个是需要写入的内容sess_content

sessWrite($sess_id,$sess_content)

                    4 删除操作:sessDelete($sess_id)

                    销毁session时,执行了PHP函数:Session_destroy();

                    可以销毁session,删除对应的session数据区,同时关闭session机制!

sessDelete($sess_id)

                    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;

sessGC($maxlifetime)

                    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 获得所有的上传文件的信息。

$_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;

 fileinfo 

                        返回的是MINE类型

                    Is_uploaded_file();

                    判断临时文件,是否为真实的上传文件!

   Is_uploaded_file()

                    多文件上传

                ① 表单元素的 name 值不同

name不同
$_FILES详情

                        需要处理那个,就使用哪个数组即可!

                    ②表单元素的 name 值相同

name相同
$_FILES详情
多图上传

            目录操作

                    创建

                    Mkdir(目录地址, 权限, 是否递归创建)

                    默认不支持递归创建

                    权限参数在windows下没有作用,在linux下有用。

mkdir

                    删除

                    Rmdir(目录地址);返回布尔值

                    不允许删除非空目录!

                    重命名(移动

                    Rename(原始地址, 目标地址);

                    针对文件和目录

                    获取目录内容

                    句柄= Opendir(目录地址);

                    句柄:PHP程序与文件系统数据流通道。

Opendir

                    文件名= Readdir(句柄);   返回文件名

                    通过句柄,从目录中读取一个文件(包括文件和子目录),一次读取一个文件,并向下移动文件指针!(文件指针和数组的指针类似)

                    注意,每个目录下都存在 ., ..  虚拟目录。表示当前目录,和上级目录。

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】来判断是否到达文件末位。

fgets

                    字符串 = 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 写锁

Flock

                    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表示请求来源!

                    实际项目中,比如登录后,可以知道登录之前的页面是什么,登录之后会跳转到请求来源的页面中。

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

expires

                Date()将一个时间戳,格式化成本地时间!

                Gmdate()将一个时间戳,格式化成GMT时间。

                告知浏览器不要缓存

不要缓存

                通常,验证码,程序,就需要告知浏览器,不要缓存验证码的图片。

                文件下载

                http下载:告知浏览器,将浏览器接受到的响应主体,以附件的形式进行存储!

文件下载
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容