Fork me on GitHub

12.1 What Is Gateway in PhalApi ?

In general, we wrap our API services and only provide some entrances, which connect internal APIs and the outside world. According to different strategy, clients can visit the APIs by RESTfule, PHPRPC, HTTP, or SOAP. What's more, you can custom the format of response, specify current language, publish accessable APIs, etc. Such entrances are what we call gateway in PhalApi.

Some frameworks provide a solid initialization process, which limits developers too much to custom anything else. Instead PhalApi prefer to provide a open initialization process where developers have more freedom to satisfy their business need.

When clients request an API, they will go through open entrance and closed initialization.

12.2 Open Entrance

As an API server system, it need to provide different services for different client terminals and even different user groups usually.

For example,

  • According to different terminals: iOS, Android, PC, Web, Watch
  • According to different user groups: internal admin system, open service platform, A/B Test
  • According to different version: 1.1.1, 1.1.2, ..., 1.1.N
  • According to different projects: maybe there are several projects in the same system

Therefore, is's really a good idea to have multiple access protal.

The most important thing is that, these entrances should keep KISS, and reuse uniform closed initialization as much as possible. Here is such an simple entrance.

<?php
// $vim ./Public/demo/index.php

/**
 * Demo entrance
 */

require_once dirname(__FILE__) . '/../init.php';

// load your API folder
DI()->loader->addDirs('Demo');

/** ---------------- deal with API request ---------------- **/

$api = new PhalApi();
$rs = $api->response();
$rs->output();

What happen in the above entrance is mainly three things as below.

  • Firstly, require uniform initialization file init.php.
  • Secondly, add API project folder Demo.
  • At last, create an instance of PhalApi and reponse to client.

Let's keep going and see what exactly happen in closed initialization.

12.3 Closed Initialization

As we know, even though we provide different entrance for different demension, it's necessary to maintance an uniform initialzation process.

(1) Regular Initialization

The uniform initialization file init.php looks like as before.

/** ---------------- define API project root folder, and register autoload ---------------- **/

date_default_timezone_set('Asia/Shanghai');

defined('API_ROOT') || define('API_ROOT', dirname(__FILE__) . '/..');

require_once API_ROOT . '/PhalApi/PhalApi.php';
$loader = new PhalApi_Loader(API_ROOT, 'Library');

/** ---------------- register & initialize base service components ---------------- **/

// autoload
DI()->loader = $loader;

// configuration
DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');

// debug mode, rename $_GET['__debug__'] as you want
DI()->debug = !empty($_GET['__debug__']) ? true : DI()->config->get('sys.debug');

if (DI()->debug) {
    error_reporting(E_ALL);
    ini_set('display_errors', 'On'); 
}

// logs
DI()->logger = new PhalApi_Logger_File(API_ROOT . '/Runtime', PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);

// database operations based on NotORM, rename $_GET['__sql__']as you want
DI()->notorm = new PhalApi_DB_NotORM(DI()->config->get('dbs'), !empty($_GET['__sql__']));

// setting language, default is English
SL('en');

The codes above are a little long, as they finish most of the initialization work.

At the beginning of the initialization, we set default timezone with PHP original function. We also define a const variable API_ROOT, which is represent the root path of our project.

date_default_timezone_set('Asia/Shanghai');

defined('API_ROOT') || define('API_ROOT', dirname(__FILE__) . '/..');

Then we introduce PhalApi by requiring file PhalApi.php and creating an instance of PhalApi_Loader. Please note that we load folder `Library at first. Library is very usefull and we talk about later.

require_once API_ROOT . '/PhalApi/PhalApi.php';
$loader = new PhalApi_Loader(API_ROOT, 'Library');

After that, everything begins to be very interesting and amazing. We have switched from original PHP development to fresh PhalApi development. But if we want to go futher more, we need to prepare some necessary weapons at first.

Autoload Service

// autoload
DI()->loader = $loader;

More detail is avaliable on Autoload.

Config Service

// configuration
DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');

More detail is avaliable on Config.

Debug Mode

// debug mode, rename $_GET['__debug__'] as you want
DI()->debug = !empty($_GET['__debug__']) ? true : DI()->config->get('sys.debug');

If you want to enable debug mode in the whole project, you can set sys.debug to be true. Otherwise, if you just want to enable debug mode in one request, you can set $_GET['__debug__'] to be true.

Logger Service

// logs
DI()->logger = new PhalApi_Logger_File(API_ROOT . '/Runtime', PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);

More detail is avaliable on Logger.

Databse Service

// database operations based on NotORM, rename $_GET['__sql__']as you want
DI()->notorm = new PhalApi_DB_NotORM(DI()->config->get('dbs'), !empty($_GET['__sql__']));

More detail is avaliable on Logger.

Besides, we can set current language as below.

// setting language, default is English
SL('en');

More detail is avaliable on i18n.

(2) Custom Initialization

There is some comment custom service following regular initialization. This part is optional, not necessary.

/** ---------------- custom more optional service components ---------------- **/

/**
// signature verification servcie
DI()->filter = 'PhalApi_Filter_SimpleMD5';
 */

/**
// cache" Memcache/Memcached
DI()->cache = function () {
    return new PhalApi_Cache_Memcache(DI()->config->get('sys.mc'));
};
 */

/**
// support with JsonP reponse
if (!empty($_GET['callback'])) {
    DI()->response = new PhalApi_Response_JsonP($_GET['callback']);
}
 */

If you want verfify whether the request is legal, you can use DI()->filer service.

// signature verification servcie
DI()->filter = 'PhalApi_Filter_SimpleMD5';

More detail is avaliable on 4.7 API signature with filter.

If you need a cache service, you can uncomment these lines.

// cache" Memcache/Memcached
DI()->cache = function () {
    return new PhalApi_Cache_Memcache(DI()->config->get('sys.mc'));
};

More detail is avaliable on Cache.

If you want to response with JSONP, you should uncomment these lines.

// support with JsonP reponse
if (!empty($_GET['callback'])) {
    DI()->response = new PhalApi_Response_JsonP($_GET['callback']);
}

More detail is avaliable on 6.7 Response with other format, such as JSONP.

12.4 The Architecture