jimbojsb / adore
基于 Aura 组件的轻量级 Action-Domain-Responder 框架
Requires
- aura/router: 2.*
- aura/web: 2.*
This package is auto-updated.
Last update: 2024-09-18 04:41:49 UTC
README
Adore 是 Action-Domain-Responder 模式的极轻量级实现。目前,这段代码“可以工作”,但应被视为预alpha草稿。我预计它不会在功能复杂性上增长,但API可能会根据使用Adore实际构建应用程序时发现的发现而大幅变化。
背景
Action-Domain-Responder 是针对 Web 应用程序而言的传统 MVC 概念的“改进”。Paul Jones 在此处详细定义了它:Action-Domain-Responder。该文档定义了模式和关注点分离,但没有提供任何具体的实现细节,并特别指出了缺乏“粘合剂”来连接各种概念。Adore 试图成为这种粘合剂,提供路由、分配和处理响应。此外,Adore 还提供了一种将操作和响应组件连接起来的方式。Adore 完整地以一个 PHP 文件的形式提供,包含一个类和两个特质。
依赖项
为了不重新发明轮子,Adore 依赖于 Aura\Web
和 Aura\Router
而不是提供这些功能的定制实现。这使得 Adore 非常简洁,并专注于解决问题的未解决部分。
安装和运行时配置
虽然 Adore 以单个 PHP 文件提供,但确实存在外部依赖项。因此,唯一的推荐安装方法是使用 Composer。将以下内容添加到您的 composer.json
{ "require": { "jimbojsb/adore": "dev-master" } }
引导
使用 Adore 的第一步是创建一个 Adore\Application
的新实例。这通常发生在您的 index.php
中。
require_once __DIR__ . '/../vendor/autoload.php'; $app = new Adore\Application;
连接操作和响应者
Adore 假设您将提供自己的方法来加载操作和响应者类,可能是 PSR 自动加载。但 Adore 仍需要知道如何解析这些类的名称。这是通过工厂闭包来完成的。以下示例假设但并不强制执行基本应用程序命名空间组织。
$app->setActionFactory(function($actionName) { $properActionName = ucfirst($actionName) . "Action"; $className = "\\MyApp\\Action\\$properActionName"; return new $className; }); $app->setResponderFactory(function($responderName) { $properResponderName = ucfirst($responderName) . "Responder"; $className = "\\MyApp\\Responder\\$properResponderName"; return new $className; });
对于您的操作和响应者,任何初始依赖注入都应在这些闭包内处理。
注意:您指定的响应者工厂将被另一个闭包包装,以帮助注入一个 Response
对象。
错误处理
Adore 尝试提供一些基本的错误处理功能。这是通过提供在无路由匹配时调用的操作名称以及在执行过程中抛出异常时调用的附加操作名称来实现的。这些操作的实际名称可以是任何您喜欢的名称,并且它们通过您提供的相同操作工厂来解决。
$app->setErrorAction("Error"); $app->setNotFoundAction("Notfound");
路由
Adore 代理 Aura\Router
。有关完整的路由语法,请参阅 Aura\Router
文档。路由至少需要匹配路径和操作名称。可选地,您还可以指定路由匹配的 HTTP 动词以及要注入操作的其他参数。
// Route with plain path matching $app->addRoute("/", "Homepage"); // Route with url parameters $app->addRoute("/blog/post/{post_slug}", "BlogPost"); // Route that will only match on a POST request $app->addRoute("/login", "Login", ["POST"]); // Route with additional hard-coded parameters $app->addRoute("/about", "StaticContent", ["file" => "about.md"]);
分配
配置好您的 Adore\Application
实例后,实际分配它非常简单,只需调用即可
$app->run();
分配请求的操作顺序大致如下
- 创建一个新的
Aura\Web\Request
对象 - 创建一个新的
Aura\Router
对象并将其加载到路由定义中 - 路由请求
- 使用提供的操作工厂创建适当的操作对象
- 将参数、请求和响应工厂注入到操作中
- 在操作上调用
_init()
- 分发操作,它应该返回一个响应器
- 调用响应器
- 从响应器获取响应对象并将其发送到客户端
创建操作和响应器
Adore 试图在您的代码中占用非常小的空间。它提供特性而不是接口或抽象类,因此您可以根据自己的意愿构建应用程序的继承树。Adore 提供的特性主要用于依赖注入和便利。它们不是严格必需的,因为 PHP 不能对特性进行类型检查,但如果您选择不使用它们,您将需要手动实现它们的方法和属性。
Adore 中的操作和响应器被设计成可调用的对象。您的代码执行的入口点将是 __invoke
方法。
Adore 特性上的所有方法和属性都以前缀 _ 开头,以避免与您的代码发生名称冲突。
操作
操作应该是一个简单的 PHP 类,使用 Adore\ActionTrait
并包含一个 _invoke()
方法。此外,如果您需要在分发之前进行额外的设置,您可以提供一个 _init()
方法。_init()
在操作完全连接后调用。您的操作应返回一个可调用的响应器。
class MyAction { use \Adore\ActionTrait; public function __invoke() { // business logic here return new Responder($data); } }
如果您的 _invoke
方法有参数,Adore 将尝试将那些命名属性与请求参数的键匹配,以便将参数传递给您的函数,作为便利。
Adore\ActionTrait
提供以下受保护属性
_params
- 由路由过程派生的所有参数的数组_request
- 一个Aura\Web\Request
的实例,代表当前的 HTTP 请求上下文。有关Aura\Web\Request
的完整功能列表,请参阅Aura\Web
文档
Adore\ActionTrait
有一个响应器工厂的引用,并提供一个辅助方法 ->getResponder($responderName)
,可以在您的操作内部生成已连接和初始化的响应器。这是实例化响应器的首选方法。
响应器
响应器应该是一个简单的 PHP 类,使用 Adore\ResponderTrait
并包含一个 _invoke()
方法。此外,如果您需要在分发之前进行额外的设置,您可以提供一个 _init()
方法。_init()
在响应器完全连接后调用。您的响应器将预先注入一个 Aura\Web\Response
对象。它应适当地处理该对象。在调用您的响应器后,Adore 将使用该响应对象向客户端发送一个正确格式化的 HTTP 响应。
class MyResponder { use \Adore\ResponderTrait; public function __invoke() { // presentation logic here $this->_response->content->set("Hello World"); } }
Adore\ResponderTrait
提供以下受保护属性
_response
- 一个Aura\Web\Request
的实例。有关Aura\Web\Response
对象的完整功能列表,请参阅Aura\Web
文档。
已知问题
- 如果有的话,错误操作处理和异常捕获几乎不起作用
- 严重依赖
Aura
组件。也许可以考虑在 PSR-7 的背景下进行改进?