《细说PHP》第四版 样章 第23章 自定义PHP接口规范 8

23.5.2  架构详解

本例的实现最重要的就是服务层的设计,有两个配置文件config.php和api.php,其中文件config.php是全局的配置文件,用于整个程序全局需要的参数设置。可以根据程序扩展需求,在配置文件中增加新的配置选项。config.php文件的内容如下所示:

6214f1efb17d4b31bd8bbc53c4eac270.png

本例配置文件采用PHP常量和数组两种格式,直接加载这个文件,常量就可以在任意位置使用,数组也可以作为全局变量直接在程序中使用。这个配置文件中包含了项目根目录“S_ROOT”和程序根目录“DS”两个常量,以及一个多维数组$configs。可以通过改变数组中的元素值,配置数据库的连接信息,以及改变和客户端匹配的“token”字符串。

配置文件api.php一定要根据程序相关的规则,添加路由记录,不能是任意格式的。因为路由主程序会用这个文件中设置好的路由规则匹配当前的URL,来选择控制器去处理请求,给客户端返回响应消息。api.php添加的部分路由规则示例如下:

8a709ce107b84320b4449eadfb3c58c2.png

在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文件中的代码如下所示:

885beef9a8d44e0e94cb60d4dd082d3b.png

通过在主入口文件index.php中,直接调用Request类中的init()方法,获取用户请求的全部信息,并应用在路由等类中,使用Request类中的getMethod()方法获取用户的请求动作,通过getUri()方法获取请求的URI信息,还能通过all()方法得到一个数组,获取全部用户请求的信息。

API服务执行后,需要返给用户信息。不管是成功执行,还是在中间某个环节出现了问题,都需要给用户一个明确的响应,而且响应信息按RESTful API的规范,格式需要统一,这样方便用户接到响应信息后能进行规范的处理。response.php文件中的代码如下所示:

2b853ecb03a5405184885cc0acad6653.png

在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文件中的代码如下所示:

5c5d8f57ca834ade98e0373964f802a1.png

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文件中的代码如下所示:

f0330ced5a4a488bb92012bbba9fd28b.png

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

猜你喜欢

转载自www.cnblogs.com/itxdl/p/11489642.html