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_select | select 查询前回调 |
before_find | find 查询前回调 |
after_insert | insert 操作成功后回调 |
after_update | update 操作成功后回调 |
after_delete | delete 操作成功后回调 |
模型事件可以看成是模型层的钩子和行为 只不过钩子的位置主要针对模型数据的写入操作
钩子 | 对应操作 | 快捷注册方法 |
---|---|---|
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_write
和after_write
表示无论是新增还是更新都会执行的钩子。
助手函数
常用操作提供助手函数支持
但核心框架本身并不依赖任何助手函数
使用助手函数和性能并无直接影响
只是某些时候无法享受IDE自动提醒的便利
但是否使用助手函数看项目自身规范
在应用的公共函数文件中也可以对系统提供的助手函数进行重写
尊贵的董事大人
英文标题不为空时 视为本栏投稿
需要关键字 描述 英文标题