PHP中MVC 开发

作者: _1633_ | 来源:发表于2018-04-24 15:00 被阅读179次

    项目开发常见流程介绍

        需求调研

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

        软件设计书

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

        界面设计

         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下载:告知浏览器,将浏览器接受到的响应主体,以附件的形式进行存储!

    文件下载

    相关文章

      网友评论

        本文标题:PHP中MVC 开发

        本文链接:https://www.haomeiwen.com/subject/qhwmcftx.html