moudarir / codeigniter-rest-api
Codeigniter 3 Rest API
Installs: 96
Dependents: 0
Suggesters: 0
Security: 0
Stars: 7
Watchers: 2
Forks: 1
Open Issues: 0
pkg:composer/moudarir/codeigniter-rest-api
Requires
- php: >=7.4
- ext-json: *
- ext-libxml: *
- ext-simplexml: *
- firebase/php-jwt: ^6.3
- nesbot/carbon: ^2.72
README
A RESTful server implementation for Codeigniter 3 based on CodeIgniter RestServer
Break changes made in version
3.0. Full code refactoring and new route system implemented inspired from Luthier CI.
Table of contents
Requirements
- PHP:
7.4to8.2tested. - Codeigniter:
^3.1.13. - Composer
Installation
The current version
3.0.*requires php 7.4 or higher (php supported versions)
This library uses Composer to be installed.
Run this command line (recommended) in the same path as your composer.json file:
composer require moudarir/codeigniter-rest-api
Or, In your composer.json file, add the following code in require section:
{
...
"require": {
...
"moudarir/codeigniter-rest-api": "^3.0"
},
...
}
And then run:
composer install
Implementation
Language / Translation
You can find the file associated with your language in the application/language/ folder. Based on the $config['language'] setting in your [your-project]/application/config/config.php configuration file.
Supported languages
- English
- French
- Arabic
Files & Configuration
The first thing to do is copying all required files in your CI project:
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/*
DO NOT change the
[your-project]/application/config/rest-api-server.phpand[your-project]/application/language/*/rest-api-server_lang.phpfilenames.
Make sure that the enable_hooks and composer_autoload keys in [your-project]/application/config/config.php file are set as following:
$config['enable_hooks'] = true; $config['composer_autoload'] = true; // Or the path to 'autoload.php' file. Ex: APPPATH.'vendor/autoload.php'
Next, set the following code in [your-project]/application/config/hooks.php file:
$hook = \Moudarir\CodeigniterApi\Routes\Hook::initialize();
and in [your-project]/application/config/routes.php file:
$route = \Moudarir\CodeigniterApi\Routes\Router::getRoutes();
Important
Execute the dumping/queries.sql file to create the tables needed for the API to work properly.
Tables that will be created are users, api_keys, api_key_limits and api_key_logs.
You're now ready to begin using the library 👌.
About Routes
The implementation of old routes is deprecated. The routes are now simplified for best use. See Usage.
Usage
Adding some routes for the next example in [your-project]/application/routes/api.php file (if not exists).
\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. ] **/
And now, we can create our [your-project]/application/controllers/api/ApiUsers.php controller:
<?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']), ] ]); } }
Authentication methods
The Rest Server can be used with Basic or Bearer authorization type. However, it can be used without any authorization type (not secure).
The request limit currently only works in the Basic authorization type.
Postman collection
Import the collection
Downloaded our Postman collection, and import it into Postman.
Import the environment
We have also provided a Postman Environment that you need to import as well.
To understand what Postman environments are, please check this link.
Edit the environment variables
Update the endpoint variable to point to your Rest server. Ex: (https//myapi.com/) with trailing slash.
✨ That's it!
You can now use the Postman collection to test available requests.
In the Postman collection, the order of execution of the requests must be respected.
Todo
- Write routing HOW TO USE documentation.
- Improve documentation.