lucinda/abstract_mvc

基于STDIN类型(URL请求、异常)进行扩展的抽象MVC API

v2.1.1 2022-06-05 07:10 UTC

README

目录

关于

此API是一个 框架(需要开发者进行绑定),用于包含与STDIN类型(控制台、URL请求或异常)无关的MVC API部分。它作为以下API的基础:

  • STDOUT MVC API:其中STDIN来自URL请求
  • STDERR MVC API:其中STDIN来自URL/控制台请求的STDERR
  • 控制台MVC API(待完成):其中STDIN来自控制台请求

API完全遵循PSR-4规范,仅需要PHP8.1+解释器和SimpleXML扩展。要快速了解其工作原理,请查看

  • 配置:设置XML文件以配置此API
  • 绑定点:将用户在XML/代码中定义的自定义组件绑定到API原型,以获得必要的功能
  • 参考指南:描述所有与开发者相关的API类、方法和字段
  • 单元测试:API具有100%的单元测试覆盖率,使用UnitTest API而不是PHPUnit,以获得更大的灵活性

所有类都属于 Lucinda\MVC 命名空间!

配置

要配置此API,您必须有一个包含以下标签的XML文件

  • 应用:(必填)基于属性和标签配置您的应用程序
  • 解析器:(必填)配置您的应用程序能够解析响应的格式
  • 路由:(必填)配置将请求的资源绑定到控制器和视图的路由

应用程序

此标签的最大语法是

<application default_format="..." default_route="..." version="...">
	<paths views="..."/>
</application>

其中

  • application:(必填)包含根据属性和标签配置应用程序的设置
    • default_format:(必填)定义应用程序的默认显示格式(扩展名)。
      必须与 解析器 中的 format 属性匹配!
    • default_route:(必填)定义在应用程序未指定任何参数时使用的隐式路由。
      必须与 路由 中的 id 属性匹配!
    • version:(可选)定义应用程序版本,用于版本化静态资源。
    • paths:(可选)根据属性保存API使用的核心组件的位置
      • views:(可选)保存用户定义视图所在的文件夹(如果为HTML)

标签示例

<application default_format="html" default_route="" version="1.0.1">
	<paths views="application/views"/>
</application>

解析器

此标签的基本语法是

<resolvers>
	<resolver format="..." content_type="..." class="..."/>
	...
</resolvers>

其中

  • 解析器: (必填) 包含根据响应格式(扩展名)解析视图的设置。为每个支持的格式持有子元素
    • 解析器: (必填) 根据属性配置一个特定格式的视图解析器
      • 格式: (必填) 定义视图解析器处理的显示格式(扩展名)。
        示例: "html"
      • 内容类型: (必填) 定义与上述显示格式匹配的内容类型。
        示例: "text/html"
      • 类名: (必填) 用户定义的PS-4自动加载兼容类(包括命名空间)的名称,该类将解析视图。
        必须是一个ViewResolver实例!

标签示例

<resolvers>
    <resolver format="html" content_type="text/html" class="Lucinda\Project\Resolvers\Html" charset="UTF-8"/>
    <resolver format="json" content_type="application/json" class="Lucinda\Project\Resolvers\Json" charset="UTF-8"/>
</resolvers>

路由

此标签的最大语法是

<routes>
    <route id="..." controller="..." view="..." format="..."/>
    ...
</routes>

其中

  • 路由: (必填) 包含处理请求的路由规则
    • 路由: (可选) 包含基于属性的特定于请求URI的路由规则
      • id: (必填) 唯一路由标识符(例如:请求的资源URL,不带尾随斜杠)
        示例: "users/(name)"
      • 控制器: (可选) 用户定义的PS-4自动加载兼容类(包括命名空间)的名称,该类将根据模型减轻请求和响应。
        必须是一个Runnable实例!
      • 视图: (可选) 包含用户定义的模板文件,该文件包含请求的响应配方。示例:"homepage"
      • 格式: (可选) 包含响应格式,如果与application中的default_format不同。
        必须与解析器中的format属性匹配!

标签示例

<routes>
    <route id="index" controller="HomepageController" view="index"/>
    <route id="user/(id)" controller="UserInfoController" view="user-info" format="json"/>
</routes>

绑定点

为了保持灵活性和实现最佳性能,API所做的假设不超过绝对必要的!相反,它通过XML提供了将原型绑定到其上的能力

程序性绑定

它为开发人员提供了一种通过FrontController构造函数程序性地将其原型绑定到其上的能力

单元测试

为了测试和示例,请检查API源中的以下文件/文件夹

  • test.php:在控制台运行单元测试
  • unit-tests.xml:设置单元测试并模拟 "loggers" 标签
  • tests:来自src文件夹的类的单元测试

参考指南

这些类由API完全实现

以下抽象类需要由开发人员扩展,以便获得以下能力

类 Application

Application 封装从 XML 中检测到的信息,并定义以下与开发者相关的公共方法

其他公共方法仅与在此之上构建的 API 相关

类 Application Route

Application\Route 封装从匹配的 route XML 标签中检测到的信息,并定义以下公共方法

类 Application Format

Application\Format 封装从匹配的 resolver XML 标签中检测到的信息,并定义以下公共方法

为了更好地了解视图最终将如何解析,请查看以下 如何解析视图 文档!

类 Response

Response 封装用于生成响应的操作。它定义了以下与开发者相关的公共方法

当 API 完成处理时,它将调用 commit 方法将头信息和响应体发送回调用者!

类 Response Status

Response\Status 封装响应 HTTP 状态,并定义以下与开发者相关的公共方法

类 Response View

Response\View 实现 \ArrayAccess 并封装将后来绑定到响应体的模板和数据。它定义了以下与开发者相关的公共方法

通过实现 \ArrayAccess,开发者可以像处理数组一样处理此对象

$this->response->view()["hello"] = "world";

类 Response Redirect

Response\Redirect 是一个 Runnable,它封装了带有其选项的 http 状态 301/302 重定向。它定义了以下与开发者相关的公共方法

示例

$redirection = new Lucinda\\MVC\\Redirect("https://www.google.com");
$redirection->setPermanent(false);
$redirection->run();

接口 Runnable

接口 Runnable 它实现,该类包含以下公共方法

使用示例

https://github.com/aherne/lucinda-framework/blob/master/src/Controllers/SecurityPacket.php

抽象类 ViewResolver

抽象类 ViewResolver 实现了 Runnable 并封装将 Response\View 转换为最终响应格式的响应体

开发者需要为每个解析器实现 run 方法,在方法中,他们可以通过构造函数访问 API 注入的以下受保护字段

使用示例

https://github.com/aherne/lucinda-framework/blob/master/src/ViewResolvers/Html.php

为了更好地了解视图解析器的工作方式,请查看以下 如何定位视图解析器 部分!

规格说明

由于此 API 是构建 MVC API 的框架,因此它包含一系列规范,这些规范可能或可能不会在此自动实现

如何检测响应格式

为了更好地理解在 application XML 标签中 default_formatdefault_route 属性如何与 routes 标签中的 format 属性和 resolvers 标签中的 format 属性一起工作,让我们以这个 XML 为例。

<application default_route="index" default_format="html" ...>
	...
</application>
<routes>
    <route id="index" .../>
    <route id="blog" format="json" .../>
    <route id="users" .../>
    ...
</routes>
<resolvers>
    <resolver format="html" .../>
    <resolver format="json" .../>
    ...
</resolvers>

以上将出现以下情况:

这种逻辑需要由子 API 实现,因为解析器的本质取决于 STDIN 类型!

视图解析器是如何定位的

为了更好地理解在 application XML 标签中 default_format 属性如何与 resolvers 标签中的 formatclass 属性一起工作,让我们以这个 XML 为例。

<application default_format="html" ...>
	...
</application>
...
<resolvers>
    <resolver format="html" class="Lucinda\Project\ViewResolvers\Html" .../>
</resolvers>

在这种情况下,如果 composer.json 中的 "psr-4" 属性将 "Lucinda\Project\" 与 "src/" 文件夹关联,那么

  • 自动加载的文件将是 src/ViewResolvers/Html.php
  • 那里找到的类必须
    • 命名为: "Html"
    • 属于命名空间: "Lucinda\Project\ViewResolvers"
    • 扩展 ViewResolver

这个逻辑完全由这个 API 实现!开发者只需要在 XML 中插入合适的 ViewResolver 类。

如何检测路由

为了更好地理解在 application XML 标签中 default_route 属性如何与 routes 标签中的 id 属性一起工作,让我们以这个 XML 为例。

<application default_route="index" ...>
	...
</application>
<routes>
    <route id="index" .../>
    <route id="blog" .../>
    ...
</routes>

假设 STDIN 来自 HTTP 请求,以上将出现以下情况:

这个逻辑需要由子 API 实现,因为请求的逻辑取决于 STDIN 类型!

如何定位控制器

为了更好地理解在 application XML 标签中 default_route 属性如何与 routes 标签中的 idcontroller 属性一起工作,让我们以这个 XML 为例。

<application default_route="index" ...>
	...
</application>
...
<routes>
    <route id="index" controller="Lucinda\Project\Controllers\Homepage" .../>
</routes>

在这种情况下,如果 composer.json 中的 "psr-4" 属性将 "Lucinda\Project\" 与 "src/" 文件夹关联,那么

  • 自动加载的文件将是: "src/Controllers/Homepage.php"
  • 那里找到的类必须
    • 命名为: "Homepage"
    • 属于命名空间: "Lucinda\Project\Controllers"
    • 扩展 Lucinda**???**\Controller

如你所见,控制器命名空间被省略了,因为控制器本身必须由子 API 实现(因为它依赖于 STDIN 类型)。

如何定位视图

为了更好地理解在 application XML 标签中 views 属性如何与 routes 标签中的 idview 属性一起工作,让我们以这个 XML 为例。

<application ...>
	<paths views="application/views"/>
</application>
...
<routes>
    <route id="user/info" view="user-info" .../>
</routes>

在这种情况下,如果路由 "user/info" 与 STDIN 请求匹配,那么

  • 自动加载的文件将是: "application/views/user-info.???"

如你所见,视图扩展被省略了,因为视图本身必须由子 API 实现(因为它依赖于 STDIN 类型)。