ThinkPHP作为国内具有代表性的PHP框架,经过多年的发展,受到越来越多公司与开发者的青睐。我也在忙里偷闲中抽出部分时间,来学习这个优秀的框架。在开始学习这个框架时,最好通过实例来学习,更容易结合实际的生产情况,促进学习的效果;这里我就选择由ThinkPHP团队开发的基于ThinkPHP3.2的内容管理框架OneThink来学习,从了解它的执行流程→熟悉流程中各个细节→了解模版标签→自己实际去使用标签→再了解它的实际执行过程……通过这样一个流程来熟悉如何基于ThinkPHP开发出一套CMS系统。
此为学习笔记开篇:(一)熟悉执行流程,跟着OneThink的首页内容生成的流程走,分析用户在访问一个URL之后,该程序是如何处理的,为后续的深入细节分析做铺垫。
本地搭建OneThink环境,第一次访问先安装,成功后先简单的浏览一下该CMS的功能;前台(首页、列表页、文章页),后台(系统信息、内容发布审核、用户权限行为管理、系统设置、栏目管理、数据库备份、插件管理),都是些内容管理系统所具有的常规功能。
访问网站首页index.php,跟着执行流程走一遍,细节不深究,碰到不太明白的变量,直接var_dump()输出看看:
1. index.php——首页入口页面,版本判定、是否开启调试、引入ThinkPHP框架
路径:'./index.php'
判断PHP版本需是5.3.0以上:version_compare(PHP_VERSION,'5.3.0','<');
系统调试设置:define('APP_DEBUG', true );
应用目录设置:define ( 'APP_PATH', './Application/' );
缓存目录设置:define ( 'RUNTIME_PATH', './Runtime/' );
引入ThinkPHP:require './ThinkPHP/ThinkPHP.php';
2. ThinkPHP.php——ThinkPHP框架的入口文件,定义各种常量、判断系统环境,初始化应用
路径:'./ThinkPHP/ThinkPHP.php'
定义常量:版本号THINK_VERSION、URL模式定义(4种模式)、类文件后缀EXT、是否为SAE环境、常用的系统路径常量(如Think类库目录、应用公共目录、缓存目录、配置目录等);
引入核心类Think.class.php:require CORE_PATH.'Think'.EXT;
应用初始化:Think\Think::start(); //命名空间\类名::方法(); //这里用到了命名空间
3. Think.class.php——框架的核心类,初始化应用程序,加载配置、类库,错误和异常处理,实例化对象
路径:'./ThinkPHP/Library/Think/Think.class.php' 声明:Think\Think
start()方法:加载需用的类、配置、语言包,是否需要缓存,运行应用
①设定方法:spl_autoload_register('Think\Think::autoload'); 自动加载类的方法,以及一些错误异常处理方法;
②分布式存储类初始化,用于读取、写入、删除文件;Storage::connect(STORAGE_TYPE);
③开发模式不缓存加载的核心类文件$runtimefile,用户模式将所有需引用的类并到同一个文件中缓存,加快后续访问速度。
④加载应用的配置文件、需要的函数和类文件、行文扩展等文件路径的数组$mode;include './ThinkPHP/Mode/common.php'
⑤循环加载处理$mode数组中的各路径的文件;
⑥检查应用目录结构是否存在,不存在则会默认生成目录结构;(这个针对ThinkPHP新建一个应用,首次访问时使用)
⑦开始运行应用 App::run(); 即:'./ThinkPHP/Library/Think/App.class.php'
4. App.class.php——加载公共文件配置、URL解析、调用对应的控制器方法
路径:'./ThinkPHP/Library/Think/App.class.php' 声明:Think\App
run()方法:
①App::init();
load_ext_file加载应用的公共文件(./Application/Common/Common/)配置(./Application/Common/Conf)
Think\Dispatcher::dispatch(); URL解析,获取控制器index、方法index
②App::exec(); 执行应用程序,及新建控制器HomeConstroller的实例,即对象;
创建控制器实例:$module = controller(CONTROLLER_NAME,CONTROLLER_PATH); 即=new IndexController();
利用php反射机制获取action方法对象,$method = new \ReflectionMethod($module, $action);
执行这个方法:$method->invoke($module); //无参数时执行,访问首页默认执行这个
$method->invokeArgs($module,$args); //有参数时执行;
以上即执行了控制器 ./Application/Home/Controller/IndexController.class.php 中的index方法
5. IndexController.class.php——应用Home中默认首页index的控制器
路径:./Application/Home/Controller/IndexController.class.php
index()方法:
$category = D('Category')->getTree(); //调用Category模块(./Application/Home/Model/CategoryModel.class.php)中的getTree()方法,获取到站点栏目的数据;其中Category对应的是数据表名;
$lists = D('Document')->lists(null); //和上面一样 调用DocumentModel.class.php中的lists()方法;
$this->assign('category',$category);// 将栏目数组数据分配给 category标签
$this->display(); //解析模版,输出;模版(./Application/Home/View/default/Index/index.html)
这里利用了“模板继承”,请查看:
http://document.onethink.cn/manual_1_0.html#onethink_3_8
到此,访问该站点首页的流程就结束,其中后台admin.php和安装install.php的执行流程与之类似,这里就不做叙述了。其中用到一些直接调用的单个大写字母方法,都在这个公共函数文件中(./ThinkPHP/Common/functions.php)。
最后提醒自己,学习是一个循序渐进的过程,需要一个时间积累,不可能一看就会;需要顺着这个流程多走几遍,再熟悉流程中的各个细节实现;加以大量的实际编码练习,才能真正的掌握!
继续努力前进!