davidwyly / rxn
Rxn PHP 示例项目
Requires
- php: ^7.0
- vlucas/phpdotenv: ^2.5
Requires (Dev)
- phpunit/phpunit: ^7
This package is not auto-updated.
Last update: 2024-09-29 04:49:24 UTC
README
A fast, simple, and powerful API framework for PHP. Responds to API requests with JSON, ensuring that your backend is completely separated from your frontend
请注意:Rxn 目前处于积极开发中,并被认为仍处于 早期 alpha 阶段
Rxn("reaction"的缩写)是一个旨在简化PHP生成视图的复杂性和混乱的框架 -- 将视图卸载到任何您喜欢的任何前端。
Rxn背后的哲学很简单:严格的后端/前端解耦。
- 后端应该 仅 通过API访问
- 后端应该 仅 以JSON格式渲染响应
- 前端应负责解析JSON响应
- 前端应负责生成用户视图
- 通过严格的 后端/前端解耦,可以发生一些奇妙的事情
- 后端和前端都可以分别使用版本化的API合约作为参考进行开发
- 后端和前端都具有较少的纠缠复杂性,提供简单且干净的流程
- 后端或前端可以完全用完全不同的解决方案替换,从而在以后提供更大的灵活性
- 并行前端开发变得极其简化(例如,利用内部应用程序、外部应用程序、手机应用程序等,使用相同的后端)。
Alpha 版本特性
包括计划的beta版功能(未勾选)
- 3.5+ GPA代码气候
- 80%+ 单元测试代码覆盖率
- 温和的学习曲线 (你不必是专家就可以快速上手)
- 通过Composer安装
- 与现有数据库模式简单的工作流程
- 代码生成
- 命令行界面(CLI)实用工具,用于创建控制器和模型
- 代码生成
- 数据库抽象
- PDO支持多个数据库
- 支持多个数据库连接
- 安全
- 预处理语句 (有助于防止SQL注入攻击)
- I/O清理 (有助于防止XSS攻击)
- 会话同步令牌 (有助于防止CSRF攻击)
- SSL/TLS支持 (有助于防止中间人攻击)
- 强大的错误处理 (在任意位置抛出异常,Rxn 处理其余部分)
- 调试实用工具
- 版本化 (有助于将来减少API维护的麻烦)
- 版本化控制器
- 版本化操作
- 脚手架 (快速应用程序原型设计)
- 无版本CRUD端点,反映当前的记录
- URI路由
- 使用Apache2
- 使用NGINX
- 依赖注入(DI)容器容器
- 控制器方法注入
- DI自动绑定 (使用类型提示自动注入构造函数参数)
- 对象关系映射(ORM)
- Rxn-ORM
- 对任何数据库记录或关系表进行CRUD操作
- ORM自动绑定 (从数据库结构和外键自动推导关系)
- 软删除
- 支持第三方ORM
- Rxn-ORM
- 速度和性能
- PSR-4自动加载 (小体积)
- 缓存机制
- 本地查询缓存 (带有过期时间)
- 对象文件缓存 (快速的实例化)
- 认证
- 支持第三方库
- OAUTH2
- OpenId
- SAML
- 支持第三方库
- 使用现有(或生成的)API合约自动验证API请求
- 事件日志记录
- 邮件发送器
- 调度器
- 可选的模块化插件,实现松耦合和更高的灵活性
许可证
Rxn 采用许可和免费的 MIT 许可。
分层命名空间和自动加载
Rxn 使用与类文件目录结构明确匹配的命名空间结构。虽然这也非常方便,但它主要用于实现一些相当酷的自动加载功能。
例如,假设你创建了一个名为 \Organization\Product\Model\MyAwesomeModel
的类。只需将文件放入遵循命名空间约定的目录结构中(例如,{root}/organization/product/model/MyAwesomeModel.php
)。当你需要调用该类时,只需直接调用类即可。无需在任何地方放置 require
。
BEFORE(未使用自动加载)
<?php require_once('/organization/product/model/MyAwesomeModel.php'); use \Organization\Product\Model\MyAwesomeModel; $object = new MyAwesomeModel() // object gets created!
AFTER(使用自动加载)
<?php use \Organization\Product\Model\MyAwesomeModel; $object = new MyAwesomeModel() // object gets created!
这种模式也存在于 Rxn 的原生类中。例如,响应类(\Rxn\Framework\Http\Response
)位于 {root}/rxn/api/controller
目录。自动加载是 Rxn 减少开销的许多方法之一。
自动加载功能支持以下文件扩展名(你还可以在 \Rxn\Framework\Config
中定义自定义扩展名)
- .php
- .class.php
- .interface.php
- .model.php
- .controller.php
错误处理
Rxn 生存、呼吸、进食异常。考虑以下代码片段
try { $result = $databse->query($sql,$bindings); } catch (\PDOException $exception) { throw new \Exception("Something went terribly wrong!",422); }
如果你在任何地方抛出 \Exception
,Rxn 将自动终止,回滚任何正在进行的数据库事务,然后使用 JSON 优雅地响应
{ "_rxn": { "success": false, "code": 422, "result": "Unprocessable Entity", "message": "Something went terribly wrong!", //... } }
路由请求参数
使用 Rxn 的后端可能的一个 API 端点示例可能如下所示
https://yourapp.tld/v2.1/order/doSomething
其中
v2.1
是端点的版本
order
是控制器
doSomething
是控制器的动作
(一个公共方法)
现在,如果你想在请求中添加一个 id
=1234
的 GET 键值对,在 PHP 中你通常会这样做
BEFORE
https://yourapp.tld/v2.1/order/someAction?id=1234
在 Rxn 中,你可以通过在 URL 中使用正斜杠(/
)作为分隔符来简化这一点,如下所示
AFTER
https://yourapp.tld/v2.1/order/someAction/id/1234
在 version
、controller
和 action
之后,参数的个数必须是奇数,否则会导致错误。
版本化控制器与动作
通过版本化你的端点 URL(例如,v1.1
、v2.4
等),你可以放心地知道,当你改变后端端点行为时,你不会意外地破坏前端。此外,版本化还有助于保持你的文档井然有序;前端开发者可以按照文档进行构建,一切都将 正常工作。
因此,对于版本为 v2.1
的端点,第一个数字(2
)是 控制器版本,第二个数字(1
)是 动作版本。下面的示例是声明控制器版本 2
和动作版本 1
的方法
namespace Organization\Product\Controller\v2; class Order extends \Rxn\Framework\Http\Controller { public function doSomething_v1() { //... } }
这允许创建可维护、符合现实的文档,前端和后端开发者都可以支持。
脚手架
想要探索和实验你的新式后端架构吗?没问题,只要你有数据库模式,你就有一系列脚手架 API 可以玩耍!使用类似以下 URI 访问脚手架端点(注意 api
而不是版本号)
https://yourapp.tld/api/order/create
https://yourapp.tld/api/order/read/id/{id}
https://yourapp.tld/api/order/update/id/{id}
https://yourapp.tld/api/order/delete/id/{id}
https://yourapp.tld/api/order/search
脚手架 API 是无版本号的 API,旨在允许前端开发者通过创建、读取、更新和删除(CRUD)操作以及搜索的形式完全访问后端。它们的主要优点是在应用开发的早期阶段,你不需要花费大量时间手动创建 CRUD 端点。(因为需求在这些开发早期阶段不断变化,事情一直在不断变化。)
警告:由于脚手架API没有版本号,它们继承了所有与无版本号API相关的问题。一旦后端被更改,这些API也会相应更改;这可能会以意想不到或隐蔽的方式破坏应用程序。因此,在开发过程即将完成时,将无版本号API转换为有版本号的API是明智之举。
依赖注入(DI)容器
尽管大多数人甚至没有意识到,也会以某种形式进行依赖注入,但事实上,手动实例化和注入具有大量依赖关系的类可能相当麻烦。以下示例应有助于展示通过容器容器进行自动依赖注入的好处。
之前(手动DI)
// instantiate the dependencies $config = new Config(); $database = new Database($config); $registry = new Registry($config,$database); $filecache = new Filecache($config); $map = new Map($registry,$database,$filecache); // call the action method $this->doSomething_v1($registry,$database,$map); public function doSomething_v1(Registry $registry, Database $database, Map $map) { $customer = new Customer($registry,$database,$map); //... }
之后(使用DI容器容器)
// call the action method $this->doSomething_v1($app->container); public function doSomething_v1(Container $container) { $customer = $container->get(Customer::class); //... }
希望您能看出好处。使用Rxn,无需每次都实例化前提条件!使用容器容器让生活更轻松。
控制器方法注入
只需将所需的类作为参数进行类型提示,然后瞬间,DI容器容器将为您猜测所有依赖项,并自动加载和注入它们。无需混乱的require。 您无需手动注入依赖项!
之前(手动实例化)
// require the dependencies require_once('/path/to/Config.php'); require_once('/path/to/Collector.php'); require_once('/path/to/Request.php'); public function doSomething_v1() { // instantiate the dependencies $config = new Config(); $collector = new Collector($config); $request = new Request($collector,$config); // grab the id from the request $id = $request->collectFromGet('id'); //... }
之后(自动实例化和注入)
public function doSomething_v1(Request $request) { // grab the id from the request $id = $request->collectFromGet('id'); //... }
看到区别了吗?