ThinkPHP 架构


支持MVC模式及MVVM(Model-View-ViewModel)模式的应用开发,URL的规范是统一的

URL访问受路由决定 没有定义或匹配路由的情况下(且没有开启强制路由模式的话)基于

http://serverName/index.php(或其它入口文件)/模块/控制器/操作/参数/值…

入口文件

用户请求PHP文件 负责处理请求(不一定是URL请求)的生命周期 入口文件就是index.php
某些特殊的需求而增加新的入口文件 如给后台模块单独设置的个入口文件admin.php
命令行程序入口 thin k都属于入口文件

应用

管理系统架构及生命周期的对象 由系统的 thinkApp类完成 应用通常在入口文件中被调用和执行 具有相同的应用目录的应用 认为是同个应用 应用可能存在多个入口文件(绑定不同的模块或使用不同的配置)。

应用具有自己独立的配置文件、公共(函数)文件和路由定义文件

路由

用于规划(同时简化)请求的访问地址 在访问地址和实际操作方法之间建立个路由规则 => 路由地址的映射关系

ThinkPHP不强制使用路由 没有定义路由 可直接使用“模块/控制器/操作”的方式  定义了路由 则该路由对应的路由地址就被不能直接访问了。一旦开启强制路由参数 则必须为每个请求定义路由(包括首页)

路由有性能损失 但更加安全 每个路由都有自己的生效条件 不满足条件的请求被过滤 远比在控制器的操作中进行各种判断要实用的多

路由的作用非URL规范这么简单 还实现验证、权限、参数绑定及响应设置等功能

模块

典型的应用是由多个模块组成的 模块是应用目录下面的个子目录 每个模块都有自己独立的配置文件、公共文件和类库文件

支持单一模块架构设计 如果应用下面只有个模块 那么通过配置这个模块的子目录可以省略(同时应用类库的命名空间也随之简化)

控制器

模块有独立的类库及配置文件 模块有多个控制器响应请求 每个控制器是个独立的控制器类。

控制器负责请求的接收 调用相关的模型处理 最终通过视图输出。控制器不应该过多的介入业务逻辑处理

控制器可被跳过,通过路由直接把请求调度到某个模型

控制器类灵活 无需继承任何基础类库,典型的Index控制器类

namespace appindexcontroller;class Index {public function index(){return 'hello,thinkphp!';
    }
}

继承系统控制器thinkController的话 使用内置的功能 享受更多的便利

操作

控制器包含多个操作(方法) 操作方法是URL访问的最小单元

Index控制器的操作方法定义 包含了两个操作方法:

namespace appindexcontroller;class Index {public function index(){return 'index';
    }    public function hello($name){return 'Hello,'.$name;
    }
}

操作方法可不用参数 定义了非可选参数 则该参数必须通过用户请求传入 如果是URL请求 则通常是通过当前的请求传入

模型

模型类完成实际的业务逻辑和数据封装 并返回和格式无关的数据

模型类并不一定要访问数据库 只有进行实际的数据库查询操作的时候 才会进行数据库的连接 是真正的惰性连接

模型层支持多层设计 可对模型层细化的设计和分工 如把模型层分为逻辑层/服务层/事件层等

视图

控制器调用模型类后 返回的数据通过视图组装成不同格式的输出。视图根据不同的需求 决定调用模板引擎进行内容解析后输出还是直接输出

视图有系列的模板文件对应不同的控制器和操作方法 支持动态设置模板目录

模板引擎

模板文件可用特殊的模板标签 标签的解析由模板引擎负责实现

内置基于XML解析的编译型模板引擎 方便的实现模板输出和控制

也支持第三方的模板引擎扩展

驱动

系统组件采用驱动式设计 灵活扩展 驱动类的位置 默认放入核心类库目录下面 可重新定义驱动类库的命名空间而改变驱动的文件位置

行为

行为(Behavior)是在预先定义好的个应用钩子(Hook)位置执行的一些操作
类似于AOP编程中的“切面”的概念 给某个钩子绑定相关行为就成了一种类AOP编程的思想

行为和某个Hook位置相关 行为的执行时间取决于行为绑定位置

要执行行为 首先要在应用程序中进行行为侦听

// 在app_init位置侦听行为thinkfacadeHook::listen('app_init');

然后对某个位置进行行为绑定

// 绑定行为到app_init位置thinkfacadeHook::add('app_init','appindexbehaviorTest');

绑定了多个行为的 按照绑定的顺序依次执行 除非遇到中断

中间件

中间件主要用于HTTP请求的拦截处理

事件

事件指数据库操作和模型操作在完成数据写入之后的回调机制

数据库操作的回调也称为查询事件 是针对数据库的CURD操作而设计的回调方法

事件描述
before_selectselect查询前回调
before_findfind查询前回调
after_insertinsert操作成功后回调
after_updateupdate操作成功后回调
after_deletedelete操作成功后回调

模型事件可以看成是模型层的钩子和行为 只不过钩子的位置主要针对模型数据的写入操作

钩子对应操作快捷注册方法
before_insert新增前beforeInsert
after_insert新增后afterInsert
before_update更新前beforeUpdate
after_update更新后afterUpdate
before_write写入前beforeWrite
after_write写入后afterWrite
before_delete删除前beforeDelete
after_delete删除后afterDelete

before_writeafter_write表示无论是新增还是更新都会执行的钩子。

助手函数

常用操作提供助手函数支持
但核心框架本身并不依赖任何助手函数
使用助手函数和性能并无直接影响
只是某些时候无法享受IDE自动提醒的便利
但是否使用助手函数看项目自身规范
在应用的公共函数文件中也可以对系统提供的助手函数进行重写