wns9778.com_威尼斯wns.9778官网

热门关键词: wns9778.com,威尼斯wns.9778官网
wns9778.com > 计算机教程 > 轻松自学ThinkPHP3.0第一天·上午

原标题:轻松自学ThinkPHP3.0第一天·上午

浏览次数:79 时间:2019-07-14

1.0框架概念

     有人解释为,框架是别人写好的一堆类,库,按一定的规则来使用。这种解释是不准确的。

     框架,framework。

     框架是半成品

框架能组装你的代码(与库不同,与工具类不同)

     成熟的框架往往包含了大量的常用库(图片,SESSION,上传等等)

     4:ThinkPHP框架执行流程深入分析(从TP框架源码的角度分析TP框架的执行流程)

2.0为什么要使用框架

     统一了环境(如,PHP4,5的函数不用考虑,由框架处理);

     简化了大量重复操作,直接上手写与业务相关的代码(如,连接数据库);

     成熟的框架有大量的库文件,调用方便;

     语法相对规范(函数名,类命名等),方便团队协作;

     作为一个程序员,当你连续两次编写同一种业务逻辑的代码时,你就应该考虑将这段代码封装成一个函数或者一个工具类来使用。

开发上的好处

     1)屏蔽了平台,版本的区别

Linux与win的区别:权限问题,大小写敏感问题。

当我们将win下写好的代码发布到Linux中时就常会遇到大小写敏感问题。如,index.php和Index.php在win下是同一个文件,在Linux下却表示不同的两个文件。当我们发布项目网站时就可能存在因为文件名的大小写敏感而导致运行出错。使用think php框架时它就会帮我们处理这一点,屏蔽了平台间的差异性。

     具体例子:ThinkPHP框架屏蔽了PHP版本的差异,如,mkdir函数。

     mkdir()函数在php5.0以前是不能递归创建目录的,在5.0及以后可以递归创建目录。框架的mk_dir()函数已经考虑了版本的区别,无论是在php 5.0前后版本都可以递归创建目录,可以放心调用。

     2)不用写大量的重复代码

数据验证功能等,数据库类,分页类等,都可以直接在框架的库文件中调用。

     3)提供很多成熟的工具(库)

分页类,数据库类,文件上传类,图片处理类等等.便于调用。

    4)方便团队合作

框架有自身的命名及代码规范,便于团队之间合作。

     疑问:

2.1为什么不用框架

     1)效率低

     PHP是每次HTTP请求过来以后,初始化全部资源(例如,创建数据库连接、加载系统类库,创建缓存等),处理完毕,释放全部资源。

     2)应用门槛上升,学习成本也相对较高

     这对于原本只是定位中小应用的PHP变得尤为尴尬,和PHP的“快、糙、猛”的特点相悖。

     3)大型框架考虑的因素过多,开发人员在开发应用时还需要额外关注代码以外的细节过多

     如:非标准约定、冗长的手册、琐碎的配置、复杂的文件目录结构、难以限制的合理约束、千姿百态的类库等等,使大多数程序员开发过程屡遭困惑。提高开发效率也成了一句空话。

     具体分析:

     ①框架代码多,降低了运行效率

     通过Zend Framework 框架输出一个”hello,world“,框架在运行时前后需要引入上百个文件;TP(ThinkPHP)也需要引入将近10个文件。

     PHP作为脚本语言,不能常驻内存,每次执行结束后内存中关于PHP文件的相关的资源都会被清空,这就会在每次HTTP请求发送过来时,都要初始化整个框架(将框架载入内存),开销很大,影响效率。

     对比Java程序,Java程序可以常驻内存,首次执行Java程序时,可以将Java框架载入内存,以后执行时可以不用再次载入内存,不影响效率。

     附:脚本语言都有不能常驻内存的特点?

     ②在web应用的开发语言中,PHP具有”快、糙、猛“的特点

     用了框架后,代码”转弯“多,与本身的特点相悖。

     ③框架本身也是有学习成本的

     使用一件工具本身是为了降低成本,但是付出的学习成本却比能够降低的成本高。

     有一些框架,命名规范非常复杂,继承关系复杂,导致开发效率降低

     我们已经知道,通过在URL中输入http://localhost/tp/02.php/Index/index和http://localhost/tp/02.php/User/test就能分别去调用IndexAction类中的index方法和UserAction类中的test方法,为什么这样输入URL的方式就可以调用相应的Action类中的方法呢?

2.2到底用不用框架?

     我们在02.php仅仅只是引入了ThinkPHP目录中的ThinkPHP.php文件,输入http://localhost/02.php后就能看到IndexAction类中的index方法输出的内容,原因到底是因为什么呢?

     1:用不用框架?

      用!

     分析:

     1)硬件效率的发展速度远超软件效率

     大内存,大硬盘,高带宽,已不必把程序效率放在首位考虑,而是把开发效率放在首位。

     2)PHP已经走向大企业应用,不再是草根语言

     如,百度贴吧、facebook等。(facebook考虑到PHP不能常驻内存,自行写了一个hihop,可以将PHP代码转化成C 代码)

     在网站开发中,PHP已经占有了70%的市场份额。

     3)开发中的个人英雄时代已经成为历史,大家都要适应团队合作

     在项目开发的过程中,如果不使用框架,很难去规范不同程序员的编码习惯,这就让团队很难进行合作开发,影响开发的效率。使用框架,能够使程序之间达成一种统一的约束,共同遵守框架的规范,有利于团队的合作。

     1)我们从最开始编写的02.php(位于C:AppServwwwTP目录下)文件开始,一步一步地进行分析

     2:学不学框架?

     学!

     你学的框架本身(比如ThinkPHP,ZendFramework,cakePHP),未必能在工作中用上(有的公司可能会自己内部编写一个小型框架来使用),但是框架的思想,肯定会用上。

     框架的种类有很多种,学习框架的目的在于掌握框架的思想,在之后遇到其他类型的框架类型时也可以很快的上手。

<?php  // 引入框架  include('./ThinkPHP/ThinkPHP.php'); ?> 

3.0主流框架介绍

     Zend Framework,CakePHP,Yii,Think PHP,CI...

      2)02.php文件中引入了/ThinkPHP目录下的ThinkPHP.php文件:ThinkPHP.php,位于C:AppServwwwTPThinkPHP目录中

3.1Zend framework

     Zend framework(简写ZF)是由Zend公司支持开发的完全基于PHP5的开源PHP开发框架:

     代码完全采用PHP5面向对象编写;

     良好的Ajax支持;

     模块化的结构设计,易于扩展;

     完善的文档资料;

     使用MVC模式来提高程序的可维护性;

     缺点:笨重,学习成本高。

<?php // ThinkPHP 入口文件  //记录开始运行时间 $GLOBALS['_beginTime'] = microtime(TRUE); // 记录内存初始使用 define('MEMORY_LIMIT_ON',function_exists('memory_get_usage')); if(MEMORY_LIMIT_ON) $GLOBALS['_startUseMems'] = memory_get_usage(); defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); defined('RUNTIME_PATH') or define('RUNTIME_PATH',APP_PATH.'Runtime/'); defined('APP_DEBUG') or define('APP_DEBUG',false); // 是否调试模式 $runtime = defined('MODE_NAME')?'~'.strtolower(MODE_NAME).'_runtime.php':'~runtime.php'; defined('RUNTIME_FILE') or define('RUNTIME_FILE',RUNTIME_PATH.$runtime);   if(!APP_DEBUG && is_file(RUNTIME_FILE)) {     // 部署模式直接载入运行缓存     require RUNTIME_FILE; }else{     // 系统目录定义     defined('THINK_PATH') or define('THINK_PATH', dirname(__FILE__).'/');     // 加载运行时文件     require THINK_PATH.'Common/runtime.php'; }

3.2CakePHP

     CakePHP是一个基于PHP,免费且开源的迅速发展起来的框架,最开始是从Ruby On Rails框架里得到灵感(就是照抄的)。

     特点:

     CakePHP是类似于ROR的框架,包括设计方式,数据库操作的Active Record方式;

     设计层面很优雅,没有自带多余的library,所有的功能都是纯粹的框架,执行效率还不错;

     数据库层hasOne,hasMany功能很强大,对于复杂业务处理比较合适;

     路由功能,配置功能还不错;

     适合中型应用;

     基本实现了MVC的每一层;

     具有自动操作命令行脚本功能。

     文档比较齐全,在国内推广的比较成功,学习成本中等。

      ThinkPHP.php文件中定义了一些变量,...wns9778.com 1,引入了Common目录中的runtime.php文件。

3.3Yii

     Yii是一个纯OOP的通用Web编程框架,和大多数PHP框架一样,Yii是一个MVC框架。

     Yii在设计时借鉴和完成了其他著名web编程框架和应用的思想和工作:

     Prado:这是Yii的思想的注意来源。Yii采用了它的基于部件和事件驱动的编程范式,数据库抽象层,模块应用框架,国际化和本地化以及其他一些东西;

     Ruby on Rails:Yii继承了它的易于配置的特点,还参考了他的活动记录设计模式的实现;

     Jquery:作为javascript框架的基础集成到Yii中;

     Symfony:Yii参考了它的过滤器设计以及插件框架;

     Joom la:Yii参考了它的模块设计以及消息传递体系。

      3)runtime.php,位于C:AppServwwwTPThinkPHPCommon目录中

3.4ThinkPHP

     ThinkPHP的思想很大程度上受Java的Struts影响,同时也借鉴了国外很多优秀的框架和模式,使面向对象的开发结构和MVC模式,融合了Struts的思想和TagLib(标签库)、RoR的ORM映射和ActiveRocord模式,封装了CURD和一些常用操作,单一入口模式等。

     在模版引擎、缓存机制、认证机制和扩展性方面均有独特的表现,已经越来越多的受到国内PHP开发人员的认可。

     ThinkPHP在国产框架中位于使用量第一位。

      runtime.php中包含了一些方法:

4.0ThinkPHP3.0(简称TP3.0)的特点

     MVC模式 单入口;

     核心文件编译执行;

     CBD架构:核心Core 行为Behavior 驱动Driver;

     面向切面:AOP,Aspect-oriented Programming;

     比2.0版有架构上的变化。

      build_app_dir(),我们在运行02.php后再次进入到包含02.php的文件目录下,可以看到自动生成了一些目录,就是runtime.php 中的build_app_dir()方法创建生成的。
      load_runtime_file(),加载运行时所需的文件,并负责自动目录生成。“require THINK_PATH.’Common/common.php’”,加载系统基础函数库。

5.0框架的学习思路

与所有的MVC框架类似,一般来说,都有3个部分。(一般)单一入口,想访问控制器需要从index.php来中转。Model,Controller都有自己独特的命名规范。

学习框架的思路:

如何引入并配置框架,Controller的命名规范和书写规范,Model的命名规范和书写规范,View的书写规范,操作数据库的方式,扩展包/工具包/库的功能。

     1)学习TP的用法
     2)研究TP的源码,了解框架的运转机制
     3)总结MVC框架的共性,方便快速学习其他框架

      load_runtime_file()具体代码:

5.1单入口解释

     1:TP框架的引入

     下载ThinkPHP_3.0_Core.zip核心版解压得到ThinkPHP目录,复制到wns9778.com,Apache的www目录或htdocs目录下的TP目录中。(C:AppServwwwTP)

     1)输出”helo,world“

     ①普通PHP程序输出”hello,world“

<?php  echo "hello,world"; ?>

     ②使用ThinkPHP框架输出“hello,world”: C:AppServwwwTP\02.php

<?php  // 引入并配置框架  include('./ThinkPHP/ThinkPHP.php'); ?>

     运行效果:

     wns9778.com 2

     在运行02.php后打开02.php所在的目录,发现多出了很多的文件,如下图所示:

     wns9778.com 3

     2)通过ThinkPHP框架输出hello,world

     打开在运行02.php之后产生的Lib目录下的Action目录中的IndexAction.class.php文件:C:AppServwwwTPLibAction IndexAction.class.php,可以看到文件内如下,这其实就是在引入ThinkPHP框架后默认显示的效果页面。

<?php // 本类由系统自动生成,仅供测试用途 class IndexAction extends Action {     public function index(){         header("Content-Type:text/html; charset=utf-8");         echo '<div style="font-weight:normal;color:blue;float:left;width:345px;text-align:center;border:1px solid silver;background:#E8EFFF;padding:8px;font-size:14px;font-family:Tahoma">^_^ Hello,欢迎使用ThinkPHP</div>';     } } 

     修改成:

<?php class IndexAction extends Action {     public function index(){         header("Content-Type:text/html; charset=utf-8");         echo 'hello,world';     } } 

     再次运行02.php文件就会在页面输出hello,world。可以判断,输出的hello,world是调用了IndexAction.class.php中的index方法得到的结果。

wns9778.com 4

     2:疑问:

     我们在地址栏中输入的是02.php在服务器下的地址,并没有输入IndexAction.class.php,那么IndexAction.class.php中的index方法是怎样被调用执行的呢?

     我们在IndexAction.class.php中自定义一个test方法,怎样才能调用这个test方法呢?

     修改IndexAction.class.php,如下:

<?php // 本类由系统自动生成,仅供测试用途 class IndexAction extends Action {     public function index(){         header("Content-Type:text/html; charset=utf-8");         echo "hello,world";     }  public function test(){  header("Content-Type:text/html; charset=utf-8");      echo "测试!";     } } 

     在浏览器地址栏中输入:http://localhost/tp/02.php/Index/test,可以看到运行效果如下:

wns9778.com 5

     也就是说,我们自定义的test方法通过这种方式成功地被调用了!

     类比的,我们输入http://localhost/tp/02.php/Index/index,来调用IndexAction.class.php中的index方法。

     (调用IndexAction.class.php中的index方法时可以省略地后面的/Index/index,在运行02.php时会默认调用IndexAction.class.php中的index方法。也就是说,输入http://localhost/tp/02.php/Index/index和输入http://localhost/tp/02.php的运行结果是一样的,对比上面的运行效果也证实了这一点)

wns9778.com 6

     小结:

     Ⅰ.我们从上面的运行结果初步可以得出,http://localhost/tp/02.php/Index/index中的“/Index”表是IndexAction(也就是IndexAction.class.php),而“/index”则表示IndexAction中的index方法。

     Ⅱ.地址栏中,输入的页面访问地址后紧跟着的两个参数,第一个参数对应Lib目录下的Action中的XXAction.class.php,第二个参数对应XXAction.class.php中的XXX方法。

    我们总结的是否是正确的呢?

     验证:

     我们在C:AppServwwwTPLibAction中仿照IndexAction.class.php创建一个UserAction.class.php,在该文件中编写一个test方法,测试是否能够通过输入http://localhost/tp/02.php/User/test成功调用UserAction.class.php中的test方法。

     ①创建UserAction.class.php文件:

     wns9778.com 7

     ②在UserAction.class.php中编写一个test方法:

     UserAction.class.php(位于C:AppServwwwTPLibAction目录下)

<?php class UserAction extends Action {     public function test(){      echo "测试2!";     } } 

     ③浏览器地址栏输入:http://localhost/tp/02.php/User/test

wns9778.com 8

     从运行结果可以看出成功调用了UserAction.class.php中的test方法。

     3:规律总结

     URL与方法调用的规律(从运行规律的角度分析ThinkPHP的执行流程):

     xx.php/XXAction类名/方法名,通过这种地址栏url的输入方式,可以去调用XXAction.class.php中的相应方法。

     在使用ThinkPHP之前,以完成用户注册功能为例,我们可能会编写2个文件reg.php和regOk.php,其中reg.php用于接收POST方式提交过来的用户注册信息,regOk.php用户返回注册成功后返回给用户的提示信息。而在ThinkPHP框架中,reg.php中的业务逻辑写入UserAction.class.php中的reg方法下,regOk.php中的业务逻辑,写入到UserAction.class.php中的regOk方法下。

     这两个方法,再通过URL中的参数来调用.这样,URL中始终只看到一个PHP文件.而不是分别去运行多个PHP文件。这个PHP文件,就是入口文件.这种设计方式---叫做单入口模式。

     如:http://localhost/reg.php,http://localhost/regOk.php,就只需通过http://localhost/tp/02.php/User/reg、http://localhost/tp/02.php/User/regOk,分为2次来调用。

     附:ThinkPHP框架中的Action就相当于MVC模式中的controller控制器。

     4:controller层(Action类)如何去编写

     1)Action类文件所放位置

     Controller层的PHP文件存放在项目目录中的Lib/Action目录下。

     2)controller的命名规范

     以UserAction为例:

     文件名,大驼峰写法,UserAction.class.php;
     类名,大驼峰写法,和文件名保持一致,class UserAction;
     继承关系:最终应该继承自Action类,class UserAction extends Action{};

     说明:

     注意,这里的“最终”,并不需要直接继承Action类,也可以是间接地继承于Action类。如,class BaseAction extends Action,这时,编写一个UserAction继承于BaseAction也是允许的。即,class UserAction extends BaseAction。

     3)controller的源码分析——Action类的源码的初步分析

     以UserAction为例, UserAction类继承于Action类,那么这个Action类(Action.class.php)究竟在哪呢?

     我们进入到C:AppServwwwTPThinkPHPLib目录(ThinkPHP是解压ThinkPHP源码包得到的)下,并没有看到运行02.php后生成的Lib目录中类似的Action目录,而是在Core目录中找到了Action.class.php。

     ①ThinkPHPLib目录下的文件

     wns9778.com 9

    

      ②ThinkPHPLibCore目录下的文件

     wns9778.com 10

     UserAction类继承于Action类,自然就有Action类的一些属性和方法。UserAction类继承Action类会有那些方法可以使用呢?

     Action.class.php(位于C:AppServwwwTPThinkPHPLibCore 目录下),部分代码如下:

abstract class Action {     // 视图实例对象     protected $view   =  null;     // 当前Action名称     private $name =  '';      public function __construct() {         tag('action_begin');         //实例化视图类         $this->view       = Think::instance('View');         //控制器初始化         if(method_exists($this,'_initialize'))             $this->_initialize(); }   … }

     可以看出,Action类的构造函数中会去判断_initialize()方法是否存在,如果存在的话便调用。

     UserAction类继承于Action类,能否调用_initialize()方法呢?

     验证:

     ①修改C:AppServwwwTPLibAction中的UserAction.class.php,如下:

<?php class UserAction extends Action {     public function test(){      echo "测试2!";     }      protected function _initialize(){      echo "我是控制器,我被调用了!<br>";     } } 

     ②测试:浏览器地址栏输入http://localhost/tp/02.php/User/test

wns9778.com 11

     说明:

     Ⅰ._initialize()方法在父类Action类的构造函数中被调用,所以会先显示“我是控制器,我被调用了!”;

     Ⅱ.controller(XXAction类)在实例化时,会首先试图调用自身的_initialize()方法。这是很有用的一个处理方式。

     Ⅲ.举例:

     通过在UserAction类中添加_initialize()方法,在用户进行其他操作之前,在_initialize()方法中增加一个session或cookie检验。这样就可以在用户进行每一个操作之前都对用户的身份进行自动检验。

     用户进行的相关操作,自然是通过/User/reg、/User/login、/User/buy等方式来实例化UserAction类,即:http://localhost/tp/02.php/User/xx。然后再调用UserAction类中的相应的方法,而每一次实例化UserAction类都会自动地去调用_initialize()方法。

版权声明:本文为博主原创文章,未经博主允许不得转载。


// 加载运行时所需要的文件 并负责自动目录生成 function load_runtime_file() {     // 加载系统基础函数库     require THINK_PATH.'Common/common.php';     // 读取核心编译文件列表     $list = array(         CORE_PATH.'Core/Think.class.php',         CORE_PATH.'Core/ThinkException.class.php',  // 异常处理类         CORE_PATH.'Core/Behavior.class.php',     );     // 加载模式文件列表     foreach ($list as $key=>$file){         if(is_file($file))  require_cache($file);     }     // 加载系统类库别名定义     alias_import(include THINK_PATH.'Conf/alias.php');      // 检查项目目录结构 如果不存在则自动创建     if(!is_dir(LIB_PATH)) {         // 创建项目目录结构         build_app_dir();     }elseif(!is_dir(CACHE_PATH)){         // 检查缓存目录         check_runtime();     }elseif(APP_DEBUG){         // 调试模式切换删除编译缓存         if(is_file(RUNTIME_FILE))   unlink(RUNTIME_FILE);     } }

      在load_runtime_file()方法中,引入了common.php、Think.class.php、ThinkException.class.php、Behavior.class.php、alias.php多个文件。其中,common.php是ThinkPHP框架的基础函数库,ThinkException.class.php是TP框架自定义的异常处理类,Think.class.php是ThinkPHP框架的核心类文件。
      4)Think.class.php,位于C:AppServwwwTPThinkPHPLibCore目录下

class Think {      private static $_instance = array();      /**       ----------------------------------------------------------      * 应用程序初始化       ----------------------------------------------------------      * @access public       ----------------------------------------------------------      * @return void       ----------------------------------------------------------      */     static public function Start() {         // 设定错误和异常处理         set_error_handler(array('Think','appError'));         set_exception_handler(array('Think','appException'));         // 注册AUTOLOAD方法         spl_autoload_register(array('Think', 'autoload'));         //[RUNTIME]         Think::buildApp();         // 预编译项目         //[/RUNTIME]         // 运行应用         App::run();         return ;     }

     说明:
     Ⅰ.Think类中的静态方法Start()中”set_error_handler(array('Think','appError'));set_exception_handler(array('Think','appException'));“设定了TP框架处理错误和异常的方式,不使用PHP程序默认的错误和异常处理方式。TP框架中对于错误和异常的处理,分别使用appError()方法和appException()。
     Ⅱ. ”spl_autoload_register(array('Think', 'autoload'));“,注册autoload方法。public static function autoload($class) ,系统自动加载ThinkPHP类库,并且支持配置自动加载路径。
     Ⅲ. “Think::buildApp();”,调用Think类(Think.class.php)的静态方法buildapp。static private function buildApp() ,读取配置信息 编译项目。
     Ⅳ. ”App::run();“,调用App类(App.class.php)的静态方法run。

     5)App.class.php ,位于C:AppServwwwTPThinkPHPLibCore目录下

static public function run() {         // 项目初始化标签         tag('app_init');         App::init();         // 项目开始标签         tag('app_begin');         // Session初始化         session(C('SESSION_OPTIONS'));         // 记录应用初始化时间         G('initTime');         App::exec();         // 项目结束标签         tag('app_end');         // 保存日志记录         if(C('LOG_RECORD')) Log::save();         return ;     }

     说明:
     Ⅰ. ”App::init();”,调用App类中的init方法;
     部分代码如下:

class App {      /**      * 应用程序初始化      */     static public function init() {          // 设置系统时区         date_default_timezone_set(C('DEFAULT_TIMEZONE'));         // 加载动态项目公共文件和配置         load_ext_file();         // URL调度         Dispatcher::dispatch();         //...         return ;     }

      init方法,对应用程序进行初始化操作,如设置系统时区,加载公共文件等。与此同时,更为重要的一个操作是调用了Dispatcher类(Dispatcher.class.php)中的dispatch方法。
     dispatch方法就是用于分析地址栏中输入的参数,根据地址栏中的参数分析出类名和方法名。如,http://localhost/tp/02.php/User/test,dispatch方法就会分析得到User类名和test方法。

     Ⅱ."App::exec();",调用App类中的exec方法,exec,即executive,执行。
     部分代码:

/**      * 执行应用程序      */     static public function exec() {         // 安全检测         if(!preg_match('/^[A-Za-z_0-9] $/',MODULE_NAME)){             $module =  false;         }else{             //创建Action控制器实例             $group =  defined('GROUP_NAME') ? GROUP_NAME.'/' : '';             $module  =  A($group.MODULE_NAME);         }          if(!$module) {        //...         }         //获取当前操作名         $action = ACTION_NAME;         // 获取操作方法名标签         tag('action_name',$action);         if (method_exists($module,'_before_'.$action)) {             // 执行前置操作             call_user_func(array(&$module,'_before_'.$action));         }         //执行当前操作         call_user_func(array(&$module,$action));         if (method_exists($module,'_after_'.$action)) {             //  执行后缀操作             call_user_func(array(&$module,'_after_'.$action));         }         return ;     }

     说明:
     Ⅰ.“A($group.MODULE_NAME);”,dispatch方法执行后得到的MODULE_NAME中部包含非法字符时,便根据MODULE_NAME去创建Action控制器实例。A()方法是common.php中的基础函数,用于根据传入地参数实例化Action类。此时的$module已经是根据类名返回的对象。
     Ⅱ."if(!$module)",传入的$module出现错误时的处理。
     Ⅲ.假如当前的需要引入的类名为UserAction,需要调用的方法为test。$module就是UserAction类的实例,$action就是test。
     在调用UserAction类中的test方法前,先判断在UserAction类中是否存在_before_test方法,有的话便调用;前置操作;
     调用UserAction类中的test方法,“call_user_func(array(&$module,$action));”根据变量$module和$action的不同值来动态地调用不同的实例中的不同方法,也可以写成“$module->$action;”。$module和$action都是由Dispatcher.class.php中的dispatch方法分析URL得到的。
     在调用UserAction类中的test方法后,会去判断在UserAction类中是否存在_after_test方法,存在即调用;后置操作。

      关于“前置操作”和“后置操作”我们可以通过案例进行简单地验证:

     ①修改UserAction.class.php(位于C:AppServwwwTPLibAction目录中)如下,

<?php class UserAction extends Action {     public function test(){      echo "测试2!";     }      public function _before_test(){      echo "我会在test方法执行之前,被自动地调用执行<br />";     }      public function _after_test(){      echo "我会在test方法执行之后,被自动地调用执行<br />";     }     protected function _initialize(){      echo "我是控制器,我被调用了!<br>";     } }

      ②测试:输入http://localhost/tp/02.php/User/test

wns9778.com 12

     从运行结果可以看出,执行顺序确实是分析的那样:_before_test()、test()、_after_test()。

     我们在深入地分析ThinkPHP框架的执行流程时,可以看到在很多框架的源文件中都有定义的常量的操作。这种操作的目的是为了不同方法(函数)间使用同一个数据的方便。不同方法间需要使用到同一个数据,要么是传参数,要么是定义成全局变量,还可以是定义成常量。定义成常量的方式使用起来更加的方便。

      5:图解简易说明TP框架执行流程

wns9778.com 13

     说明:
     在ThinkPHP框架(简称TP框架)中,http://localhost/tp/02.php/User/test传入参数“User”和“test”的方式,与“http://localhost/tp/02.php?m=User&a=test”的方式是等价的,TP框架都有相应的处理。其中,m就表示$module,a就表示$action。第二种方式在此之前我们使用得较多。
     简单验证:浏览器地址栏输入http://localhost/tp/02.php?m=User&a=test

wns9778.com 14

    6: ~runtime.php文件说明

     在运行02.php的时候(浏览器地址栏中输入:http://localhost/tp/02.php),会自动生成多个目录和文件,其中在Runtime目录中有一个~runtime.php文件,它是一个编译缓存文件。分析TP框架程序的执行流程时,我们发现程序在运行的过程(各种初始化操作)中不断地引入了多个PHP文件,引入文件是一个从硬盘读取文件内容的过程,每一次的读取必然都会消耗一定的资源,如果程序重复运行多次时耗费的资源会更大!
     ThinkPHP框架为了节省资源的采取的措施是:将所有需要引入的文件全部包含到一个文件(~runtime)中,当程序重复运行时就只需去读取编译好的缓存文件~runtime.php就可以了,就不再去读取多个PHP文件,只读取~runtime.php文件就可以了。从而节省开销,减少I/O操作。
     TP框架采取的这种措施节省了I/O操作的开销,但也带来了另一个问题:测试/调试时,修改程序代码后,运行程序时发现运行结果并没有受到影响。这是因为缓存文件~runtime.php文件所造成的,运行程序生成了~runtime.php文件后,再次运行程序时便不会再去重新读取其他需要引入的配置文件了,不会重新地初始化应用程序,这就给调试带来了麻烦。
     既然运行程序就会自动地生成~runtime.php文件,我们在调试的过程中可以手动删除~runtime.php文件;也可以“启动调试模式”——启动调试就是定义APP_DEBUG常量为true,APP_DEBUG常量默认为false。定义APP_DEBUG常量为true,启动“调试模式”事实上是通过程序来自动地删除~runtime.php文件。两种方式都可以使用,目的都是删除缓存文件~runtime.php,让程序在执行的时候能够重新初始化。程序能够初始化,重新去加载各个文件,也就是说,修改的代码能够生效。
     1)定义APP_DEBUG常量为true,应用/项目的~runtime.php文件会自动删除的原因:
     程序运行时会加载runtime.php(位于C:AppServwwwTPThinkPHPCommon目录下),执行runtime.php中的load_runtime_file()方法时会对常量APP_DEBUG的值进行判断,值为真的时候会删除编译缓存文件。
    load_runtime_file()部分代码:

// 加载运行时所需要的文件 并负责自动目录生成 function load_runtime_file() {     //...省略一部分代码     // 检查项目目录结构 如果不存在则自动创建     if(!is_dir(LIB_PATH)) {         // 创建项目目录结构         build_app_dir();     }elseif(!is_dir(CACHE_PATH)){         // 检查缓存目录         check_runtime();     }elseif(APP_DEBUG){         // 调试模式切换删除编译缓存         if(is_file(RUNTIME_FILE))   unlink(RUNTIME_FILE);     } }

     其中,“unlink(RUNTIME_FILE);”就是去删除缓存文件。

      2)验证:定义APP_DEBUG常量为true时会自动删除~runtime.php文件,是因为执行了TP框架runtime.php源码中的“unlink(RUNTIME_FILE);”相关部分代码。
     ①修改02.php,启动调试模式

?php  //开启调试模式  define('APP_DEBUG', true);  // 引入框架  include('./ThinkPHP/ThinkPHP.php'); ?>

     注意:定义常量的操作一定要写在include文件操作的前面,不然会没有效果。原因?

     ②在TP框架的runtime.php中的load_runtime_file()方法中添加测试输出代码

// 加载运行时所需要的文件 并负责自动目录生成 function load_runtime_file() {     // 加载系统基础函数库     require THINK_PATH.'Common/common.php';     // 读取核心编译文件列表     $list = array(         CORE_PATH.'Core/Think.class.php',         CORE_PATH.'Core/ThinkException.class.php',  // 异常处理类         CORE_PATH.'Core/Behavior.class.php',     );     // 加载模式文件列表     foreach ($list as $key=>$file){         if(is_file($file))  require_cache($file);     }     // 加载系统类库别名定义     alias_import(include THINK_PATH.'Conf/alias.php');      // 检查项目目录结构 如果不存在则自动创建     if(!is_dir(LIB_PATH)) {         // 创建项目目录结构         build_app_dir();     }elseif(!is_dir(CACHE_PATH)){         // 检查缓存目录         check_runtime();     }elseif(APP_DEBUG){         // 调试模式切换删除编译缓存         echo "这部分代码被执行了!<br/>";         if(is_file(RUNTIME_FILE))   unlink(RUNTIME_FILE);     } }

     ③运行02.php程序测试。运行02.php文件生成的~runtime.php文件被删除,页面输出“这部分代码被执行了!”。

wns9778.com 15

     3)不删除~runtime.php文件(位于C:AppServwwwTPRuntime目录中),修改02.php文件,测试是否修改能够生效

<?php  //开启调试模式  // define('APP_DEBUG', true);  // 引入框架  include('./ThinkPHP/ThinkPHP.php');  echo "<br />huangSir"; ?>

     运行结果:

wns9778.com 16

     测试发现,即使不启用“调试模式”,修改02.php后运行,结果也发生变化了。
     疑问:启用调试模式,禁止生成缓存文件,使修改的代码能够生效,方便调试。可是修改02.php文件后,即使没有启用调试模式,运行结果也发生改变了?是修改什么文件才必须得启动调试模式才能让修改能够生效?核心文件?对ThinkPHP框架源码的修改?配置的修改?

      4)调试模式的启用
     在我们开发项目的过程中通常都是定义APP_DEBUG常量为true,启用调试模式,能够更为简便地调试代码(不需要每次调试都是手动去删除相应的~runtime.php文件)。当项目完成,发布到服务器下时,就需要关闭调试模式(直接注释掉即可),来生成缓存文件,减少I/O操作,提高程序运行效率。

      7:Model层(Model类)的写法

本文由wns9778.com发布于计算机教程,转载请注明出处:轻松自学ThinkPHP3.0第一天&#183;上午

关键词: wns9778.com

上一篇:phpcms v9模板标签使用说明

下一篇:没有了