ggedde / spry
PHP API 框架
Requires
- php: >=5.5.0
- ggedde/spry-background-process: ~1.0.4
- ggedde/spry-cli-connector: ~1.1.0
- ggedde/spry-core: ~1.1.11
- ggedde/spry-db: ~1.0.9
- ggedde/spry-log: ~1.0.4
- ggedde/spry-rate-limits: ~1.0.2
- ggedde/spry-utilities: ~1.0.9
- ggedde/spry-validator: ~1.0.1
- ggedde/spry-webtools: ~1.0.3
- dev-master
- 1.1.11
- 1.1.5
- 1.1.4
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.20
- 1.0.19
- 1.0.18
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- 0.9.34
- 0.9.33
- 0.9.32
- 0.9.31
- 0.9.30
- 0.9.29
- 0.9.28
- 0.9.27
- 0.9.26
- 0.9.25
- 0.9.24
- 0.9.23
- 0.9.22
- 0.9.21
- 0.9.20
- 0.9.19
- 0.9.18
- 0.9.17
- 0.9.16
- 0.9.15
- 0.9.14
- 0.9.13
- 0.9.12
- 0.9.11
- 0.9.10
- 0.9.9
- 0.9.8
- 0.9.7
- 0.9.6
- 0.9.5
- 0.9.4
- 0.9.3
- 0.9.2
- 0.9.1
- 0.9.0
This package is auto-updated.
Last update: 2024-09-16 19:23:50 UTC
README
轻量级的 PHP API 框架
非常适合 CRUD 应用
@PSR2 和 @Symfony 兼容
文档
安装
安装 Spry 并使用它的最佳方式是通过 CLI。 https://github.com/ggedde/spry-cli
composer global require ggedde/spry-cli
请参考 CLI 页面上的 安装过程。
然后在命令行中
spry new [project_name]
cd [project_name]
将为您自动创建一个端点
public/index.php
include dirname(__DIR__).'/vendor/autoload.php'; include dirname(__DIR__).'/spry/init.php';
手动安装
composer require ggedde/spry
如果您尚未添加,需要添加 composer 自动加载器。然后使用 run 方法并包含您的配置文件路径或包含一个配置对象。请参阅 配置
示例
include_once '/vendor/autoload.php'; Spry\Spry::run('../config.php');
快速入门
通过 CLI 创建项目
spry new [project_name]
cd [project_name]
文件夹结构
- public/
index.php
- spry/
- components/
- logs/
- api.log
- php.log
- config.php
- init.php
要启动 Spry 测试服务器,请运行
spry up
然后在单独的终端中运行一些测试
spry test
创建单个文件组件
spry component MyComponent
现在查看和编辑 spry/components/MyComponent.php
从新组件更新数据库模式到数据库
spry migrate
使用新组件再次运行测试
spry test
就这样!
编码愉快
嗯,我想你可能还需要更多信息。您的大部分编码将在您创建的组件文件中,其余的可能在配置文件中。下面有更多详细信息:)
配置
Spry 需要一个配置文件或配置对象。
当使用配置文件时,Spry 将传递一个预先初始化的 $config 对象到文件。您只需设置对象内的变量即可
示例配置文件
<?php $config->salt = ''; $config->endpoint = 'https://:8000'; $config->componentsDir = __DIR__.'/components'; ...
访问配置设置
您可以通过从 Spry 调用 config() 对象来访问任何设置
示例
echo Spry::config()->salt; echo Spry::config()->db['database_name']
扩展配置设置
您可以在组件、提供者或插件中添加自己的设置,然后在稍后访问它们
config.php
$config->mySetting = '123';
MyComponent.php
echo Spry::config()->mySetting;
组件
Spry 主要通过在 Spry 配置 中设置的 componentsDir 添加的组件来使用。
组件是 SpryComponent 命名空间内的类。
组件可以通过使用内置方法设置自己的路由、响应代码、数据库模式和测试。或者您可以通过配置.php 配置一切
这些内置方法都是可选的
任何解析路由的方法称为控制器,并接收来自路由的任何参数。
基本示例
<?php namespace Spry\SpryComponent; use Spry\Spry; class MyComponent { private static $id = 2; // Component ID public static function setup() { Spry::addFilter('configure', 'MyComponent::stuff'); } public static function stuff($config) { // Do Stuff return $config; } public static function getRoutes() { return [ '/items/{id}' => [ 'label' => 'Get Item', 'controller' => 'MyComponent::get', 'access' => 'public', 'methods' => 'GET', 'params' => [ 'id' => [ 'required' => true, 'type' => 'int', ], ], ], ]; } public static function getCodes() { return [ 0 => [ 'success' => ['en' => 'Successfully Retrieved Item'], 'warning' => ['en' => 'No Item with that ID Found'], 'error' => ['en' => 'Error: Retrieving Item'], ], 1 => [ 'info' => ['en' => 'Empty Results'], 'success' => ['en' => 'Successfully Retrieved All Items'], 'error' => ['en' => 'Error: Retrieving All Items'], ], ]; } public static function getSchema() { return [ 'items' => [ 'columns' => [ 'name' => [ 'type' => 'string', ], ], ], ]; } public static function getTests() { return [ 'items_get' => [ 'label' => 'Get Example', 'route' => '/items/123', 'method' => 'GET', 'params' => [], 'expect' => [ 'status' => 'success', ], ], ]; } public static function get($params = []) { $response = Spry::db()->get('items', '*', $params) return Spry::response(self::$id, 01, $response); } }
路由
当使用单个文件组件时,您可以通过在 getRoutes() 方法中返回路由来设置组件中的路由。
示例
public static function getRoutes() { return [ '/items/{id}' => [ 'label' => 'Get Item', 'controller' => 'MyComponent::get', 'access' => 'public', 'methods' => 'GET', 'params' => [ 'id' => [ 'required' => true, 'type' => 'int', ], ], ], ]; }
或者是在配置设置中
$config->routes[ '/items/{id}' => [ 'label' => 'Get Item', 'controller' => 'MyComponent::get', 'access' => 'public', 'methods' => 'GET', 'params' => [ 'id' => [ 'required' => true, 'type' => 'int', ], ], ], ... ];
路由选项
参数选项
数据库
Spry的默认数据库提供者是基于Medoo的SpryDB
查看SpryDB的完整文档
这允许您在不更改项目代码的情况下,稍后更换提供者。
Spry::db()->get('items', '*', ['id' => 123]); Spry::db()->select('items', '*', ['date[>]' => '2020-01-01']); Spry::db()->insert('items', ['name' => 'test', 'date' => '2020-01-01']); Spry::db()->update('items', ['name' => 'newtest'], ['id' => 123]); Spry::db()->delete('items', ['id' => 123]);
Spry配置设置
$config->dbProvider = 'Spry\\SpryProvider\\SpryDB'; $config->db = [... ];
日志
Spry的默认日志提供者是SpryLogger
查看SpryLogger的完整文档
这允许您在不更改项目代码的情况下,稍后更换提供者。
Spry::log()->message("My Message"); Spry::log()->warning("Warning"); Spry::log()->error("Error");
Spry配置
$config->loggerProvider = 'Spry\\SpryProvider\\SpryLogger'; $config->logger = [... ];
响应
Spry有两个内置函数用于构建响应(response 和 stop)。
response
Spry::response($data = null, $responseCode = 0, $responseStatus = null, $meta = null, $additionalMessages = []);
您可以使用此功能构建响应数据,并从控制器返回它。
$responseCode: 这是组件的响应代码ID。 $responseStatus: 可以是 null | info | success | warning | error
如果为 null,则函数将根据 $data 的值自动检测状态
示例
$data = ['id' => 123, 'name' => 'John']; return Spry::response($data, 0);
stop
Spry::stop($responseCode = 0, $responseStatus = null, $data = null, $additionalMessages = [], $privateData = null);
这将立即终止应用程序并返回响应
示例
if ($error) { Spry::stop(0); }
* 请参阅下面的响应代码以了解其工作方式
响应代码
单个文件组件示例
public static function getCodes() { return [ 0 => [ // Get Single 'success' => ['en' => 'Successfully Retrieved Item'], 'warning' => ['en' => 'No Item with that ID Found'], 'error' => ['en' => 'Error: Retrieving Item'], ], 1 => [ // Get Multiple 'info' => ['en' => 'No Results Found'], 'success' => ['en' => 'Successfully Retrieved Items'], 'error' => ['en' => 'Error: Retrieving Items'], ], 2 => [ // Insert 'success' => ['en' => 'Successfully Created Item'], 'error' => ['en' => 'Error: Creating Item'], ], 3 => [ // Update 'success' => ['en' => 'Successfully Updated Item'], 'error' => ['en' => 'Error: Updating Item'], ], 4 => [ // Delete 'success' => ['en' => 'Successfully Deleted Item'], 'error' => ['en' => 'Error: Deleting Item'], ], ]; }
配置文件示例
请注意,您需要为组件代码添加一个组编号。在单个文件组件设置中不需要此操作。
$config->tests[ 1 => [ 0 => [ // Get Single 'success' => ['en' => 'Successfully Retrieved Item'], 'warning' => ['en' => 'No Item with that ID Found'], 'error' => ['en' => 'Error: Retrieving Item'], ], 1 => [ // Get Multiple 'info' => ['en' => 'No Results Found'], 'success' => ['en' => 'Successfully Retrieved Items'], 'error' => ['en' => 'Error: Retrieving Items'], ], 2 => [ // Insert 'success' => ['en' => 'Successfully Created Item'], 'error' => ['en' => 'Error: Creating Item'], ], 3 => [ // Update 'success' => ['en' => 'Successfully Updated Item'], 'error' => ['en' => 'Error: Updating Item'], ], 4 => [ // Delete 'success' => ['en' => 'Successfully Deleted Item'], 'error' => ['en' => 'Error: Deleting Item'], ], ], 2 => [ 0 => [ // Get Single 'success' => ['en' => 'Successfully Retrieved Other Item'], 'warning' => ['en' => 'No Other Item with that ID Found'], 'error' => ['en' => 'Error: Retrieving Other Item'], ], 1 => [ // Get Multiple 'info' => ['en' => 'No Results Found'], 'success' => ['en' => 'Successfully Retrieved Other Items'], 'error' => ['en' => 'Error: Retrieving Other Items'], ], 2 => [ // Insert 'success' => ['en' => 'Successfully Created Other Item'], 'error' => ['en' => 'Error: Creating Other Item'], ], 3 => [ // Update 'success' => ['en' => 'Successfully Updated Other Item'], 'error' => ['en' => 'Error: Updating Other Item'], ], 4 => [ // Delete 'success' => ['en' => 'Successfully Deleted Other Item'], 'error' => ['en' => 'Error: Deleting Other Item'], ], 5 => ['redirect' = ['en' => 'Depricated: This route is depricated']], 6 => ['error' = ['en' => 'Error: Custom Error Message']], 7 => ['error' = ['en' => 'Error: Another Custom Error Message']], 8 => ['error' = ['en' => 'Error: And Another Custom Error Message']], ], ... ];
组件组编号
第一个数字用于通过ID分隔组件代码
例如:
1-200 # Success For Component A
2-200 # Success For Component B
多语言支持
1 => [
'success' => [
'en' => 'Success!',
'es' => '¡Éxito!'
]
]
格式 - 信息、成功、重定向或已弃用、客户端错误和服务器错误
代码中的第一个数字表示代码类型。
[group_id]-[1]xx - 1 表示 '信息' 或 '空'
[group_id]-[2]xx - 2 表示 '成功'
[group_id]-[3]xx - 3 表示 '重定向' 或 '已弃用'
[group_id]-[4]xx - 4 表示 '客户端错误',或 '未知'
[group_id]-[5]xx - 5 表示 '服务器错误'
当使用Spry::response()时,您只需传递最后两位数字作为代码和数据参数。
例如:
Spry::response($data, 1);
如果 $data 是数组但 为空,则响应将自动在代码前加上 1 并返回 1-101。
如果 $data 有值且 不为空,则响应将自动在代码前加上 2 并返回 1-201。
如果 $data 是数组但不是 null,则响应将自动在代码前加上 4 并返回 1-401。
如果 $data 是 false 或 null,则响应将自动在代码前加上 5 并返回 1-501。
响应状态
在响应中,将有一个名为 status 的键
此键的可能值只有 success、error 或 unknown
info、success 和 redirect 都表示成功的响应,将返回 success
warning 和 error 表示失败的响应,将返回 error
测试
Spry自带预构建的测试解决方案。您仍然可以使用PHPUnit等工具,但Spry的测试利用Spry的配置进行快速测试。当使用单个文件组件时,您可以通过在getTests()方法中返回路由来设置组件中的路由。
示例
public static function getTests() { return [ 'items_insert' => [ 'label' => 'Insert Item', 'route' => '/items/insert', 'method' => 'POST', 'params' => [ 'name' => 'TestData', ], 'expect' => [ 'status' => 'success', ], ], 'items_get' => [ 'label' => 'Get Item', 'route' => '/items/{items_insert.body.id}', 'method' => 'GET', 'params' => [], 'expect' => [ 'status' => 'success', ], ], 'items_delete' => [ 'label' => 'Delete Item', 'route' => '/items/delete/', 'method' => 'POST', 'params' => [ 'id' => '{items_insert.body.id}' ], 'expect' => [ 'status' => 'success', ], ], ]; }
或者是在配置设置中
$config->tests[ 'items_get' => [ 'label' => 'Get Example', 'route' => '/items/123', 'params' => [], 'expect' => [ 'code' => '1-200', ], ], 'items_get' => [ 'label' => 'Get Example', 'route' => '/items/123', 'params' => [], 'expect' => [ 'body.id[>]' => 12, ], ], ... ];
测试选项
使用Spry CLI运行测试
所有测试
spry test
特定测试
spry test items_get
更多选项
spry test --verbose --repeat 10
速率限制
Spry的默认速率限制是SpryRateLimits
查看完整文档
这允许您在不更改项目代码的情况下,稍后更换提供者。
添加全局速率限制
$config->rateLimits = [ 'driver' => 'file', 'fileDirectory' => __DIR__.'/rate_limits', 'excludeTests' => false, 'default' => [ 'by' => 'ip', 'limit' => 10, 'within' => 1, 'hook' => 'configure', 'excludeTests' => false ] ];
按路由添加限制
$config->routes = [ '/auth/login' => [ 'label' => 'Auth Login', 'controller' => 'Auth::login', 'access' => 'public', 'methods' => 'POST', 'limits' => [ 'by' => 'ip', 'limit' => 1, 'within' => 3, 'excludeTests' => false ], 'params' => [ 'email' => [ 'required' => true, 'type' => 'string', ], 'password' => [ 'required' => true, 'type' => 'string', ], ], ], ];
生命周期
按完成顺序排列钩子和过滤器生命周期
非生命周期钩子和过滤器
钩子
钩子允许你在特定的时间和生命周期中运行自己的代码。这是运行中间件和其他生命周期感知代码的方式。
添加钩子
Spry::addHook(string $hookName, string|callable $controller, [ mixed $extraData = null [, int $order = 0 ]] ) : void
示例
Spry::addHook('configure', 'Spry\\SpryComponent\\MyComponent::myMethod', ['bar' => 345], 100);
运行钩子
Spry::runHook(string $hookName, [ mixed $data ] ) : void
示例
Spry::runHook('configure',['foo' => 123] [[ mixed $data = null ], mixed $meta = null ] );
您的控制器
class MyComponent public static function myMethod($data = null, $meta = null, $extraData = null) { $data // [foo => 123] $meta // null $extraData // [bar => 345] // Do Stuff }
过滤器
过滤器允许你在特定的时间和生命周期中过滤数据。通常,过滤器需要一个返回值。
添加过滤器
Spry::addFilter(string $filterName, string|callable $controller, [ mixed $extraData = null [, int $order = 0 ]] ) : void
示例
Spry::addFilter('configure', 'Spry\\SpryComponent\\MyComponent::myMethod', ['bar' => 345], 100);
运行过滤器
Spry::runFilter(string $filterName, [[ mixed $data = null ], mixed $meta = null ] ) : void
示例
$config = Spry::runFilter('configure', $config, ['component' => 'someComponent', 'var' => 'abc']);
您的控制器
class MyComponent public static function myMethod($config = null, $meta = null, $extraData = null) { $config // $config $meta // ['component' => 'someComponent', 'var' => 'abc'] $extraData // [bar => 345] // Do Stuff return $config; }
待办事项
- 添加PHPUnit测试
- 添加类型和接口
- 审查和优化性能
- 审查PSR-7响应规范
- 喝一杯啤酒!