moudarir / codeigniter-rest-api
Codeigniter 3 Rest API
Requires
- php: >=7.4
- ext-json: *
- ext-libxml: *
- ext-simplexml: *
- firebase/php-jwt: ^6.3
- nesbot/carbon: ^2.72
README
基于 CodeIgniter RestServer 的 Codeigniter 3 RESTful 服务器实现
重大变更 在版本
3.0中实现。进行了完整的代码重构并实现了新的路由系统,灵感来自 Luthier CI。
目录
需求
- PHP:
7.4到8.2已测试。 - Codeigniter:
^3.1.13。 - Composer
安装
当前版本
3.0.*需要 php 7.4 或更高版本 (php 支持的版本)
此库使用 Composer 进行安装。
在您的 composer.json 文件相同的路径下运行此命令行(推荐)
composer require moudarir/codeigniter-rest-api
或者,在您的 composer.json 文件中,在 require 部分添加以下代码
{
...
"require": {
...
"moudarir/codeigniter-rest-api": "^3.0"
},
...
}
然后运行
composer install
实现
语言/翻译
您可以在 application/language/ 文件夹中找到与您的语言相关的文件。它基于您的 [your-project]/application/config/config.php 配置文件中的 $config['language'] 设置。
支持的语言
- 英语
- 法语
- 阿拉伯语
文件与配置
首先,将 CI 项目中所有必需的文件复制到您的 CI 项目中
application/config/rest-api-server.php=>[your-project]/application/config/rest-api-server.phpapplication/controllers/DefaultController.php=>[your-project]/application/controllers/DefaultController.phpapplication/language/*/rest-api-server_lang.php=>[your-project]/application/language/*/rest-api-server_lang.phpapplication/routes/*=>[your-project]/application/routes/*
不要 更改
[your-project]/application/config/rest-api-server.php和[your-project]/application/language/*/rest-api-server_lang.php的文件名。
确保 [your-project]/application/config/config.php 文件中的 enable_hooks 和 composer_autoload 键设置为以下内容
$config['enable_hooks'] = true; $config['composer_autoload'] = true; // Or the path to 'autoload.php' file. Ex: APPPATH.'vendor/autoload.php'
接下来,在 [your-project]/application/config/hooks.php 文件中设置以下代码
$hook = \Moudarir\CodeigniterApi\Routes\Hook::initialize();
并在 [your-project]/application/config/routes.php 文件中
$route = \Moudarir\CodeigniterApi\Routes\Router::getRoutes();
重要
执行 dumping/queries.sql 文件以创建 API 正确工作所需的表。
将要创建的表是 users、api_keys、api_key_limits 和 api_key_logs。
现在,您可以使用此库了 👌。
关于路由
旧路由的实现已弃用。现在路由已简化以实现最佳使用。请参阅 使用方法。
使用方法
在 [your-project]/application/routes/api.php 文件中添加一些路由(如果不存在)。
\Moudarir\CodeigniterApi\Routes\Router::group('users', ['namespace' => 'api'], function () { \Moudarir\CodeigniterApi\Routes\Router::get('', 'apiUsers@index'); \Moudarir\CodeigniterApi\Routes\Router::post('', 'apiUsers@create'); \Moudarir\CodeigniterApi\Routes\Router::post('login', 'apiUsers@login'); \Moudarir\CodeigniterApi\Routes\Router::put('{id}', 'apiUsers@update'); \Moudarir\CodeigniterApi\Routes\Router::get('{id}', 'apiUsers@show'); }); // This will generate route array like this: /** $route = [ "users" => [ "GET" => "api/apiUsers/index", "POST" => "api/apiUsers/create", ], "users/login" => [ "POST" => "api/apiUsers/login" ], "users/([0-9]+)" => [ "PUT" => "api/apiUsers/update/$1" "GET" => "api/apiUsers/show/$1" ], "default_controller" => "welcome", // Can be changed in '[your-project]/application/config/rest-api-server.php' file. "translate_uri_dashes" => false, // Can be changed in '[your-project]/application/config/rest-api-server.php' file. "404_override" => "pageNotFound/index", // Can be changed in '[your-project]/application/config/rest-api-server.php' file. ] **/
现在,我们可以创建我们的 [your-project]/application/controllers/api/ApiUsers.php 控制器
<?php defined('BASEPATH') || exit('No direct script access allowed'); use Firebase\JWT\JWT; use Moudarir\CodeigniterApi\Exceptions\DatabaseCreateException; use Moudarir\CodeigniterApi\Http\Server; use Moudarir\CodeigniterApi\Models\ApiKey; use Moudarir\CodeigniterApi\Models\User; class ApiUsers extends Server { public function index() { $entity = new User(); $page = $this->get('page'); $total = $entity->count(); $response = [ 'total' => $total, 'items' => $total === 0 ? [] : $entity->all(['page' => $page, 'limit' => $this->get('limit')]), ]; if ($page !== null) { $response['page'] = (int)$page === 0 ? 1 : (int)$page; } self::getResponse()->ok($response); } public function show(int $id) { if ($id <= 0) { self::getResponse()->badRequest(); } $item = (new User())->find($id); if ($item === null) { self::getResponse()->notFound(); } self::getResponse()->ok(['item' => $item]); } public function create() { $post = $this->post(); $errors = []; if (array_key_exists('email', $post)) { $email = $this->post('email'); if (empty($email) || filter_var($email, FILTER_VALIDATE_EMAIL) === false) { $errors['email'] = "This field is not a valid email address."; } } else { $errors['email'] = "This field is required."; } if (!empty($errors)) { self::getResponse()->error($errors); } $entity = new User(); try { $hashedPassword = password_hash($post['password'], PASSWORD_ARGON2I, [ 'memory_cost' => 1 << 12, 'time_cost' => 2, 'threads' => 2 ]); $entity::getDatabase()->trans_start(); $user = $entity ->setFirstname($post['firstname']) ->setLastname($post['lastname']) ->setEmail($post['email']) ->setPassword($hashedPassword) ->create(); $apikey = (new ApiKey()) ->setUserId($user->getId()) ->setKey() ->setUsername() ->setPassword() ->create(); if ($entity::getDatabase()->trans_status() === false) { $entity::getDatabase()->trans_rollback(); } else { $entity::getDatabase()->trans_commit(); } self::getResponse()->ok([ 'message' => "User account created successfully.", 'data' => [ 'user_id' => $user->getId(), 'api_key' => $apikey->getKey(), 'username' => $apikey->getUsername(), 'password' => $apikey->getPassword(), ] ]); } catch (DatabaseCreateException $e) { $entity::getDatabase()->trans_rollback(); self::getResponse()->error("Error occurred during account creation."); } } public function update($id) { self::getResponse()->ok([ 'data' => [ 'info' => $this->getAuthData(), 'args' => $this->put(), 'id' => $id, ] ]); } public function login() { $apiConfig = $this->getApiConfig(); $secret = getenv("JWT_SECRET"); $secret !== false || $secret = $apiConfig['jwt_secret']; $user = (new User())->find($this->getApiKey()['user_id']); $payload = [ 'iss' => 'http://example.org', 'aud' => 'http://example.com', 'iat' => 1356999524, 'nbf' => 1357000000, 'user' => [ 'user_id' => $user['id'], 'firstname' => $user['firstname'], 'lastname' => $user['lastname'], 'email' => $user['email'], ] ]; self::getResponse()->ok([ 'data' => [ 'jwt_key' => JWT::encode($payload, $secret, $apiConfig['jwt_algorithm']), ] ]); } }
认证方法
Rest 服务器可以与 Basic 或 Bearer 授权类型一起使用。然而,它也可以不使用任何授权类型(不安全)。
请求限制目前仅在 Basic 授权类型中工作。
Postman 收集
导入收集
下载我们的 Postman 收集,并将其导入 Postman。
导入环境
我们还提供了一个Postman 环境文件,您也需要导入。
要了解Postman环境是什么,请查看此链接。
编辑环境变量
更新endpoint变量以指向您的Rest服务器。例如:(https//myapi.com/),结尾带斜杠。
✨ 就这么简单!
现在您可以使用Postman集合来测试可用请求。
在Postman集合中,必须遵守请求的执行顺序。
待办事项
- 编写使用说明文档。
- 改进文档。