《细说PHP》第四版 样章 第23章 自定义PHP接口规范 8
23.5.2 架构详解
本例的实现最重要的就是服务层的设计,有两个配置文件config.php和api.php,其中文件config.php是全局的配置文件,用于整个程序全局需要的参数设置。可以根据程序扩展需求,在配置文件中增加新的配置选项。config.php文件的内容如下所示:

本例配置文件采用PHP常量和数组两种格式,直接加载这个文件,常量就可以在任意位置使用,数组也可以作为全局变量直接在程序中使用。这个配置文件中包含了项目根目录“S_ROOT”和程序根目录“DS”两个常量,以及一个多维数组$configs。可以通过改变数组中的元素值,配置数据库的连接信息,以及改变和客户端匹配的“token”字符串。
配置文件api.php一定要根据程序相关的规则,添加路由记录,不能是任意格式的。因为路由主程序会用这个文件中设置好的路由规则匹配当前的URL,来选择控制器去处理请求,给客户端返回响应消息。api.php添加的部分路由规则示例如下:

在WebAPI中,控制器(Controller)是用来操作HTTP请求的,控制器里的“action” 方法对应不同的HTTP请求。当WebAPI收到一个HTTP请求时,路由表就会将请求映射到对应的“action”方法中。路由表的定义需要根据WebAPI的访问需求,一条条自行添加。当WebAPI框架收到HTTP请求时,它会尝试从路由表的模板中匹配一个URL,如果是重复的路由规则,会使用最前面的那一条,如果不匹配将会显示给用户错误响应消息。我们注册的这个模板规则说明如下:
Ø Router 是路由类名,通过我们定义路由类的静态方法实现路由匹配和映射机制。
Ø Router::get()是路由类中定义的用户请求方法,可以是get、post、put、delete和resource中的一个。其中,resource方法默认注册了一系列用户请求的路由规则,如果是一些通用的请求操作,只使用这一个方法注册,通用的操作请求如增、删、改、查等路由策略都可以实现。其他的方法则都是一条记录对应路由的一个请求。
Ø 路由方法中第一个参数是资源名称,需要自定义这个名称,目的是用来设置不同的URL,从而定位到不同的资源。这个名称是一个字符串,例如,"/users"、"/users/{id}"、"/users/create"、"/users/{id}/edit"等,用户请求“GET http://api.itxdl.cn/v1/users/2”时,使用的就是资源"/users/{id}"。
Ø 路由方法中第二个参数是控制器的类名和操作方法。例如,“UserController”就是用户自定义的控制器类名称,如果不是使用Router类中的resource方法,而是使用单个的get或post等方法时,需要在这个参数中,控制器类名的后面使用“@”指定这个控制器中自定义的一个方法名称。这样就可以根据用户请求,映射到指定控制器的方法中了。如果是使用Router类中的resource方法,则不用“@”指定具体的方法,因为在Router类中默认注册了所有通用默认映射方法的匹配规则。
Ø 路由方法中第三个参数是可选参数,指定API的版本号,默认是V1。按RESTful API规范, API的URL都需要有版本号对应。
Ø 路由方法中第四个参数也是一个可选参数,指定一个中间件(自定义类Middleware)的方法名称,用来对用户请求API进行安全验证。这个安全验证的规则,可以通过在Middleware类中自定义方法进行验证,只需要将方法名称字符串传入这个参数即可。在默认情况下,如果不使用该参数,则不需要进行安全验证。
设计WebAPI最主要的操作就是从用户发起请求开始,到接口服务运行后再返给用户结果。请求和响应在框架中分别通过两个类实现,在request.php和response.php两个文件中声明。在request.php中声明的Response类,用来获取用户请求API的URI和参数,根据用户的动作才能通过路由定位到具体的资源位置,并映射到指定的控制器中去处理业务。request.php文件中的代码如下所示:

通过在主入口文件index.php中,直接调用Request类中的init()方法,获取用户请求的全部信息,并应用在路由等类中,使用Request类中的getMethod()方法获取用户的请求动作,通过getUri()方法获取请求的URI信息,还能通过all()方法得到一个数组,获取全部用户请求的信息。
API服务执行后,需要返给用户信息。不管是成功执行,还是在中间某个环节出现了问题,都需要给用户一个明确的响应,而且响应信息按RESTful API的规范,格式需要统一,这样方便用户接到响应信息后能进行规范的处理。response.php文件中的代码如下所示:

在Response类中只提供success()和error()两个对外调用的方法,返回的数据消息格式是相同的,使用JSON格式向用户返回数据。消息中有4个元素,“code”是响应消息的状态码,“message”是提示用户的消息,“time”是当前服务器的时间,通过时间的变化用于区分不同时间相同的两次操作,“data”是以多维数组形式返给用户的数据。当向用户响应成功的消息时,调用本类中的success()方法,主要在控制器的方法中使用。需要两个可选参数,如果调用时没有提供参数,默认返回的状态码为“0”表示成功,并返回空数据,默认提示“success”。第一个参数需要传递一个数组,作为响应给用户的数据。第二个参数可以自定义提示用户的响应消息。 当任何一个环境出现问题时,都可以调用error()方法响应给用户错误消息提示,可以在路由、中间件、控制器、数据访问模型等类中使用,也有两个可选参数,第一个参数是状态码,默认为“E001”。本类也提供了一组常见的返回状态码和对应的错误消息,用于标准的错误消息提示。如果使用的状态码在本类中已经存在,则返给用户这个状态码和这个状态码对应的错误提示消息,如果状态码在本类中不存在,可以返给用户自定义的状态码和自定义的错误消息。
公开的API可以不用进行安全验证,但非公开的API必须通过安全验证才能访问。本例通过middleware.php文件实现一个中间件环节,专门处理用户连接验证。该文件中声明一个类Middleware,在该类中每声明一个方法就是一个验证规则,在api.php文件的路由表的每条记录中,最后一个参数传入Middleware类任意一个方法名,就可以选择使用一种验证规则。本例只在Middleware中提供一个login()验证方法。middleware.php文件中的代码如下所示:

Middleware类中的login()验证方法,用来处理用户连接时的安全验证。算法和前面安全验证章节介绍的一样,通过时间戳参数、token和用户提供的应用参数,进行排序再加密处理,得到一个“key”,再和客户端通过URL传递过来的使用同样算法的“key”进行比对,如果相同则才允许连接。
WebAPI框架最核心的功能就是路由的实现,本例通过在router.php文件中声明的Router类实现了路由的功能。当WebAPI框架收到用户的HTTP请求时,它会尝试从api.php定义的路由表中匹配模板中的每条规则信息,调用中间件进行连接验证,再映射到对应的控制器方法,如果不匹配则会响应错误消息。router.php文件中的代码如下所示:


路由类Router其实只有一个对外公开的run()方法,在主入口文件index.php中,调用完Request类的init()方法,并处理完成用户请求后就可以直接调用。在run()方法中直接加载api.php导入路由表,其实在api.php中的路由表记录,每一条就是完成一次对Router类中一个方法的调用,例如Router::get()、Router::put或Router::resource等,而且这些方法的内部,又都是通过调用本类中addRouter()方法进行路由注册的。在addRouter()方法中,通过正则匹配获取用户的请求动作和资源,再调用中间件进行安全连接验证,最后通过调用本类的toAction()方法,映射到具体的控制器,以及控制器中对应的操作方法,实现整个路由过程。
WebAPI框架的入口是index.php文件,可以将它看作一个中央调度器。程序通过URL重写规则或其他方式,把所有URL导向本文件,由它调度其他代码。index.php文件中的代码如下所示:

因为index.php是整个程序的入口文件,所以会将配置文件,以及程序需要的类文件都直接加载进来,然后调用Request类中的init()方法,获取用户所有的请求参数,再通过调用Router类的run()方法,根据用户的请求完成路由机制的处理。







《细说PHP》第四版 样章 第23章 自定义PHP接口规范 8的更多相关文章
- 《细说PHP》第四版 样章 第二章 PHP的应用与发展 1
		<细说PHP>第四版 样章 第二章 PHP的应用与发展 1 学习任何编程语言之前,先了解一下它的应用与发展是很有必要的.从Web开发的历史看来,PHP.Python和Ruby几乎是同时出现 ... 
- 《java编程思想(第四版)》第一二章学习笔记
		目录 一.Introduction 1.抽象过程 2.面向对象语言(包括Java)的五个基本特性 3.每个对象都提供服务 4.public.private.protected三者的区别 5.Java的 ... 
- 《细说PHP》 第四版 样章 第二章 PHP的应用与发展 5
		2.5 如何学习PHP PHP以其简单易学的特点,以及敏捷开发的优势,从一个几乎不被人知的开源项目,慢慢成长为技术人员首选的动态Web设计工具,与其他语言相比,PHP表现得更好.更快.更简单易学.尽 ... 
- 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 11
		23.6 使用第三方接口服务实例 接供服务的第三方接口平台有很多,现在的项目中也经常用到一些第三方接口,如支付宝.微信.短信.邮件接口等,我们需要借助第三方的能力来实现产品的某些功能.如果自己已经掌 ... 
- 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 9
		23.5.3 WebAPI框架应用 程序框架其实就是一个半成品项目,在应用框架时,核心的服务程序只应用,不需要改动.当然如果有必要,也可以根据项目的需要对框架进行二次开发.本节内容主要基于我们的框架 ... 
- 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 6
		23.4 API的设计原则和规范 API是服务提供方和使用方之间对接的通道,前面我们设计的一些简单API的例子,基本上比较随意,没有使用任何规范.设想一下,每个平台都可能存在大量的API,如果API ... 
- 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 3
		23.2 接口实现的基础 大家都很了解函数在本地应用,通过名称调用函数执行,并通过传递不同参数,函数有不同执行,执行后给调用者返回结果.如果把一个函数做成一个接口远程访问,也需要这几个步骤.使用HT ... 
- 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 1
		如今的项目开发中,接口是很普遍的应用技术.现在好多项目组都单独设有接口开发人员.像腾讯.微博.淘宝等开放平台,其所谓的开放,就是提供一些可调用的接口,用于获取相关的信息.例如,微信用户基本信息.淘宝店 ... 
- 《细说PHP》第四版 样章 第18章 数据库抽象层PDO 12
		18.9 管理表books实例 在Web项目中,几乎所有模块都要和数据表打交道,而对表的管理无非就是增.删.改.查等操作,所以熟练掌握对表进行管理的这些常见操作是十分有必的.本例为了能更好地展示PD ... 
随机推荐
- Spring学习的第二天
			第二天总共学习了以下内容: spring中的ioc常用注解: 案例使用xml方式和注解方式实现单表的CRUD操作(但还是需要xml配置文件,并不是纯注解的配置): 改造基于注解的Ioc案例,使用纯注解 ... 
- jenkins实现git自动拉取代码时替换配置文件
			jenkins实现从git上自动拉取源代码——>自动编译——>发布到测试服务器——>验证测试,这个大家应该都知道,但是关于源代码里的配置文件,可能就会有点头疼了, 一般测试都会自己的 ... 
- MVC(实战一)
			一.创建MVC项目 二.界面分布 Content:是存放css文件等,暂时先不考虑. Controllers:重要, 控制层,控制界面显示和界面逻辑的,其实真正业务逻辑层,建议分层出去. Models ... 
- RTP Payload Format for H264 Video
			基础传输结构 rtp中对于h264数据的存储分为两层,分别是 VCL: video coding layer 视频编码层 这是h264中block, macro block 以及 slice级别的定义 ... 
- 划分为k个相等的子集
			给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等. 示例 1: 输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 ... 
- 【Unity游戏开发】性能优化之在真机上开启DeepProfile与踩坑
			一.引子 最近马三入职了新公司,平时除了负责编辑器开发之外还要做一些游戏性能优化方面的工作.在这里首先给大家安利一下Unity官方的性能测试分析工具URP ,这个工具目前是免费,测试的过程中也不需要接 ... 
- R3环申请内存时页面保护与_MMVAD_FLAGS.Protection位的对应关系
			Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 技术学习来源:火哥(QQ:471194425) R3环申请内存时页 ... 
- 基于STM32F429的内存管理
			1.内存管理介绍 内存管理,是指软件运行时对计算机内存资源的分配和使用的技术.其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源. 内存管理的实现方法有很多种,他们其实最终都是要 ... 
- RandomAccessFile()实现用户注册功能, 新增,查询,更新
			package seday03.raf;import java.io.IOException;import java.io.RandomAccessFile;import java.util.Arra ... 
- JS基础语法---函数也是一种数据类型
			1. 如何获取某个变量的类型? typeof 2. 函数是有数据类型 ,数据类型:是function function f1() { console.log("我是函数"); } ... 
