thumbsupcat/iced-americano

用 PHP 编写的微框架

dev-master 2023-11-14 10:03 UTC

This package is auto-updated.

Last update: 2024-09-14 11:50:49 UTC


README

用 PHP 编写的用于 Web 服务的微框架

目的

用 PHP 编写提供路由、会话、数据库等功能的 Web 框架。

目标

  • 路由:从 HTTP 请求中提取方法、路径。可以注册和执行处理器和中间件。
  • 数据库:使用 PDO,以 MySQL 为基础。
  • 会话:可以使用数据库来管理会话。
  • 主题:可以选择 HTML 模板并传递变量以向用户显示页面,类似于模板引擎。
  • 模块化:基于用户提供的模块,Web 服务运行。

实现后思考

这个项目是在听 Inflearn 课程 的同时进行的。我尽量避免机械地输入代码,但与其说是我自己主导,不如说是跟着课程的方向前进。项目完成后,我用 Laravel 开发了另一个 项目。使用 Laravel 后,我发现它与这个项目在很多方面都很相似。当然,Laravel 方面要大得多,也复杂得多,但结构相似。而且,这个项目非常忠实于这种结构和趋势。因此,我决定一个个仔细研究。

该项目中存在一个名为 RequestContext 的类。这是用于注册路由的对象。请求包含的上下文是什么?那将是方法、URI、处理器。如果将处理器细分,则可以分为路由专用处理器和通用中间件。因此,RequestContext 成为一个包含方法、URI、处理器、中间件的容器,它具有用户请求的上下文。这个对象看起来是被动性的。因为它是被路由注册和执行的,所以服务器在接收和处理请求的过程中,RequestContext 看起来就像一个被动对象。

然而,从面向对象的角度来看,每个对象都是主动的。因此,路由可以将请求分配给适当的需求上下文,但需求上下文也可以选择检查这个请求是否适合自己。在这个项目中,我们选择了后者。路由只是将需求上下文包含起来执行,而请求是否合适、是否将参数传递给已注册的处理器等,则由需求上下文负责。需求上下文不是包含上下文数据的简单数据块,而是作为一个对象执行。

看起来被动的对象实现是主动的,这很符合代码,代码的执行也更加流畅。因此,我想更多地了解面向对象。我读了一本名为 面向对象的事实与误解 的书。因此,我将我的结论整理在 链接 中。

实现内容

整体执行流程

整体执行流程 从客户端请求的入口点(index.php)接收请求并执行 Application。Application 是框架中提供的类,其中包含 ServiceProvider。ServiceProdiver 是包含用户想要提供给 Web 服务的功能的类。从路由、会话管理到时区设置等所有操作都定义在其中。Application 将按顺序执行注册的 ServiceProvider,并向客户端响应。

目录结构

src
    │  Application.php
    │
    ├─Database
    │      Adaptor.php
    │
    ├─Http
    │      Request.php
    │
    ├─Routing
    │      Middleware.php
    │      RequestContext.php
    │      Route.php
    │
    ├─Session
    │      DatabaseSessionHandler.php
    │
    └─Support
            ServiceProvider.php
            Theme.php

详细信息

路由

  • 目录:Routing
  • 文件:Route.php, RequestContext.php, Middleware.php
  • 路由定义了对 HTTP 请求的响应。有定义了 HTTP 方法、路径、响应操作的处理器。
  • 路径有如 '/post' 这样的静态路径和如 '/post/{id}' 这样的动态路径,因此需要相应的处理。
  • Middleware 定义了可以在多个路由中使用的通用处理器。有用于响应的主处理器,以及在此之前调用的中间件。
  • RequestContext 是用于管理路由所需材料的单元。
    • match 方法接收要比较的 URL 作为参数,并检查当前 RequestContext 是否处理当前的请求。如果匹配成功,则返回动态路径中的数据。
    • runMiddleware 方法执行所有注册的中间件。
  • Route 负责路由。使用 RequestContext 注册和执行路由。
    • run 方法比较 HTTP 请求信息和注册的路由,并执行。
    • 检查 get、post、delete 等 HTTP 方法和路径,提取与动态路径相对应的数据,并调用处理器。

HTTP 请求

  • 目录:Http
  • 文件:Request.php
  • 分析传入的 HTTP 请求并提取方法、路径等功能。

数据库

  • 目录:Database
  • 文件:Adaptor.php
  • 在内部使用PDO访问数据库。通过使用预编译语句来防止SQL注入。
  • 可以使用exec方法处理CRUD操作。
  • 使用getAll方法从表中获取数据。通过指定类,可以以该类的实例接收数据。

会话

  • 目录:Session
  • 文件:DatabaseSessionHandler.php
  • 通过继承PHP为会话提供的SessionHandlerInterface来构建类。
  • 内部使用Adaptor类。
  • 会话中保存的数据与数据库连接并管理。

主题

  • 目录:Support
  • 文件:Theme.php
  • 结构化以允许使用预先编写的布局,就像模板引擎一样。
  • view方法中使用变量变量(使用$$)来将字符串作为变量名进行替换,以便可以使用传递的关联数组的键作为布局的变量名。
  • setLayout方法负责调用一次,并负责整个布局(头部、导航、主要内容、页脚)。在view方法中变化的是主要内容。

ServiceProvider

  • 目录:Support
  • 文件:ServiceProvider.php
  • ServiceProvider提供了一个框架,允许用户注册服务(服务器运行期间要执行的逻辑)。
  • ServiceProvider提供了错误处理、会话管理、数据库控制、路由、主题等功能,提供给Application。
  • 最初是一个抽象类,但由于内部没有操作,所以已将其更改为接口。

Application

  • 目录:根目录(src目录)
  • 文件:Application.php
  • Application负责接收ServiceProvider并执行。
  • 路由、会话管理等所有逻辑都必须由用户定义并注册到Application中,使用ServiceProvider。

参考

此代码基于PHP 7+ 编程:面向对象课程编写。