_美國著名棒球運動員約格.貝拉說過:“通過仔細地觀察,你可以了解很多事情。”_
##1.29.1 絕對的開放,還是絕對的固化?
框架應該都會考慮這樣一個問題:到底是應該給應用項目提供統一固定的入口和初始化流程呢,還是應該給他們完全自由的空間?
但我發現,很多PHP的框架都提供了一個絕對的固化流程。也就是你能作出改動的地方很少,雖然這樣應用不需要過多地去考慮。
然而我覺得,這樣做,弊大于利。特別在現在項目需求背景各有各的不同時。所以,我為PhalApi框架選擇了開放式的初始化做法。考慮到若開放的度太大,項目可能會迷茫,所以又結合了統一的初始化。
下面分別說明這兩點:開放式入口和封閉式的初始化。
##1.29.2 開放式的入口
作為一個接口系統,是需要為不同的終端、不同的開放人群,甚至不同的版本提供不同的服務的。
如:
+ 按不同的終端:iOS設備、Android設備、PC版、網頁版
+ 按不同的開放人群:手機客戶端、內部管理后臺、內部其他系統、公共開放平臺
+ 按不同的版本:版本從V1、V2到VN
+ 按不同的項目:同一個應用下可能會存在多個項目,當然更推薦每個項目單獨一個系統
基于此,為不同的維度提供不同的入口就很有現實實用場景了。
更為重要的是,這些不同的入口都應該盡可能簡單,并能統一共享公共的組件資源、數據庫、日志系統這些。一個可能的入口示例如下:
```javascript
<?php
/**
* Demo 統一入口
*/
require_once dirname(__FILE__) . '/../init.php';
//裝載你的接口
DI()->loader->addDirs('Demo');
/** ---------------- 響應接口請求 ---------------- **/
$api = new PhalApi();
$rs = $api->response();
$rs->output();
```
簡單解讀一下上面的代碼,首先要加載統一初始化文件,其實裝載掛靠的接口項目(對應你的項目目錄的名稱),最后創建一個PhalApi接口實例進行響應、輸出結果。
下面來看下統一初始化文件需要做的事情。
##1.29.3 封閉式的初始化
不言而喻,盡管我們有按不同維度劃分入口的需要,但統一初始化的過程更是必不可少的。
不同的入口提供了各維度定制的機會,統一的初始化則為應用提供了統一定制的機會。
###(1)常規入口代碼
常規的入口,需要以下初始化操作:
```javascript
<?php
/**
* 統一初始化
*/
/** ---------------- 根目錄定義,自動加載 ---------------- **/
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);
/** ---------------- 注冊&初始化服務組件 ---------------- **/
//自動加載
DI()->loader = $loader;
//配置
DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');
//日志紀錄
DI()->logger = new PhalApi_Logger_File(API_ROOT . '/Runtime',
PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);
//數據操作 - 基于NotORM,$_GET['__sql__']可自行改名
DI()->notorm = function() {
$debug = !empty($_GET['__sql__']) ? true : false;
return new PhalApi_DB_NotORM(DI()->config->get('dbs'), $debug);
};
//調試模式,$_GET['__debug__']可自行改名
DI()->debug = !empty($_GET['__debug__']) ? true : DI()->config->get('sys.debug');
//翻譯語言包設定
SL('zh_cn');
```
###(2)常規代碼解讀
上面是框架執行所需的基礎服務注冊和配置,一般直接可用,但也可以根據需要作些細微的調整。如日志的級別設定、調試的參數修改(改成一個只有自己知道的參數名字,別讓外界知道!)等。
出于讓大家對初始化過程有一個更理性的認識,這里補充一下各代碼的作用。
最開始是利用了PHP原生態的時區設置和宏定義:
```javascript
date_default_timezone_set('Asia/Shanghai');
defined('API_ROOT') || define('API_ROOT', dirname(__FILE__) . '/..');
```
接著,便開始引入PhalApi框架的類自動加載器:
```javascript
require_once API_ROOT . '/PhalApi/PhalApi.php';
$loader = new PhalApi_Loader(API_ROOT);
```
這樣,我們就可以從原生態的PHP開發,切入到了PhalApi接口開發模式。但在捲起袖口準備大干一場前,我們還需要注冊一些必備的服務:
```javascript
//自動加載
DI()->loader = $loader;
//配置
DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');
//日志紀錄
DI()->logger = new PhalApi_Logger_File(API_ROOT . '/Runtime',
PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);
//數據操作 - 基于NotORM,$_GET['__sql__']可自行改名
DI()->notorm = function() {
$debug = !empty($_GET['__sql__']) ? true : false;
return new PhalApi_DB_NotORM(DI()->config->get('dbs'), $debug);
};
```
上面的自動加載、配置、日志和數據庫操作通常而言,對于一個項目都是必須的。
但配置文件的路徑可自行指定,日志的存儲類型也可以自由組合(多個類型采用或運算),還可以選擇你合適的數據庫配置。
注意到,PhalApi_DB_NotORM初始化時,除了配置文件外,還有一個debug參數,此參數的作用是用于控制是否打印顯示執行的SQL語句及對應消耗的時間。
至此,我們已經為項目完成了絕大部分的基礎服務注冊,且上面的初始化順序建議保留不變。因為,前后有依賴關系。
但為了讓我們的項目更有活力、更具生氣、更國際化,我們還可以多加這么兩行代碼:
```javascript
//調試模式,$_GET['__debug__']可自行改名
DI()->debug = !empty($_GET['__debug__']) ? true : DI()->config->get('sys.debug');
//翻譯語言包設定
SL('zh_cn');
```
這里,也有一個debug參數,之所以和數據庫的分開,是因為如果混在一起會導致返回結果解析失敗(如不再是JSON格式)。
此debug的來源,默認來自環境的系統配置文件(如區分生產環境和測試環境);也可以來自某個請求的手動設置,這樣,開發同學便可以快速進行在線調試了。
而這個參數,則是框架代碼、項目代碼以及擴展類庫所共用的調試開關,至于各個場景使用的效果,視各環節而定。
SL()是一個快速函數,作用是設定翻譯語言包。如果覺得中文下的UTF-8查看不直觀,可以自行加個參數修改,如:
```javascript
SL(isset($_GET['__lan__']) ? $_GET['__lan__'] : 'zh_cn');
```
###(3)更多定制注冊代碼
上面的操作,涵蓋了大部分項目的需要。除此之外,還有一些額外的服務,可根據自身的情況,定制處理:
```javascript
/** ---------------- 以下服務組件就根據需要定制注冊 ---------------- **/
//緩存 - MC
/**
DI()->cache = function() {
$mc = new PhalApi_Cache_Memcached(DI()->config->get('sys.mc'));
return $mc;
};
*/
//簽名驗證服務
//DI()->filter = 'Common_SignFilter';
//支持JsonP的返回
if (!empty($_GET['callback'])) {
DI()->response = new PhalApi_Response_JsonP($_GET['callback']);
}
```
###(4)更多定制解讀
此部分的注冊,非項目必須部分。可根據需要,自行定制。
如上面出現的第一個,即緩存服務,使用的是Memcached:
```javascript
DI()->cache = function() {
$mc = new PhalApi_Cache_Memcached(DI()->config->get('sys.mc'));
return $mc;
};
```
接下來的,是重要的接口簽名驗證服務。之所以沒有提供這個服務的實現,是出于更高安全性考慮而建議項目各自制定簽名規則并實現。然后這樣簡單注冊即可被框架自動調用:
```javascript
//簽名驗證服務
//DI()->filter = 'Common_SignFilter';
```
在有些需要支持JsonP返回的場景,可以使用PhalApi_Response_JsonP返回格式開放callback操作:
```javascript
//支持JsonP的返回
if (!empty($_GET['callback'])) {
DI()->response = new PhalApi_Response_JsonP($_GET['callback']);
}
```
##1.29.4 用一張圖來表示

- 歡迎使用PhalApi!
- 接口,從簡單開始!
- [1.1]-下載與安裝
- [1.2]-創建一個自己的項目
- [1.3]-在線體驗
- [1.4]-文檔、幫助和官網
- [1.10]-對PhalApi框架的抉擇
- [1.11]-快速入門(backup)
- [1.12]-參數規則:接口參數規則配置
- [1.13]-統一的接口請求方式:_sevice=XXX.XXX
- [1.14]-統一的返回格式和結構:ret-data-msg
- [1.15]-數據庫操作:基于NotORM的使用及優化
- [1.16]-配置讀取:內外網環境配置的完美切換
- [1.17]-日記紀錄:簡化版的日記接口
- [1.18]-快速函數:人性化的關懷
- [1.19]-DI服務速查:各資源服務一覽表
- [1.20]-DB操作:數據庫基本操作速查
- [1.21]-類的自動加載:遵循PEAR包的命名規范
- [1.22]-簽名驗證:自定義簽名規則
- [1.23]-請求和響應:GET和POST兩者皆可得及超越JSON格式返回
- [1.24]-緩存策略:更靈活地可配置化的多級緩存
- [1.25]-國際化翻譯:為走向國際化提前做好翻譯準備
- [1.26]-數據安全:數據對稱加密方案
- [1.27]-精益開發:更富表現力的Model層和重量級數據獲取的應對方案
- [1.28]-COOKIE:對COOKIE原生態的支持及記憶加密升級版
- [1.29]-開放與封閉:多入口和統一初始化
- [1.30]-保持的力量:接口開發最佳實踐
- [1.31]-新型計劃任務:以接口形式實現的計劃任務
- [2.11]-核心思想:DI依賴注入-讓資源更可控
- [2.12]-海量數據:可配置的分庫分表
- [2.13]-接口調試:在線SQL語句查看與性能優化
- [2.14]-測試驅動開發:意圖導向編程下的接口開發
- [2.15]-演進:新型計劃任務續篇
- [2.16]-領域驅動設計:應對復雜領域業務的Domain層
- [2.17]-微服務:Api接口服務層
- [2.18]-定制化:資源服務的再實現
- [2.19]-擴展庫:可重用的擴展類庫
- [2.20]-約定編程:架構明顯的編程風格
- [2.21]-服務器統一部署方案簡明版:CentOs---Nginx---php-fpm---MySql-[--Memcached]
- [2.22]-更多工具:精益項目和團隊建設
- [3.1]-擴展類庫:微信開發
- [3.2]-擴展類庫:代理模式下phprpc協議的輕松支持
- [3.3]-擴展類庫:基于PHPMailer的郵件發送
- [3.4]-擴展類庫:優酷開放平臺接口調用
- [3.5]-擴展類庫:七牛云存儲接口調用
- [3.6]-擴展類庫:新型計劃任務
- [3.8]-擴展類庫:用戶、會話和第三方登錄集成
- [3.9]-擴展類庫:swoole支持下的長鏈接和異步任務實現
- [3.11]-擴展類庫:基于FastRoute的快速路由
- [4.2]-開發實戰2:模擬優酷開放平臺接口項目開發
- [4.3]-開發實戰3:一個簡單的小型項目開發(奔跑吧兄弟投票活動)
- [5.1]-架構與思想:PhalApi核心設計和思想解讀
- [5.2]-雜談:扯一些PhalApi的前世和今生
- [5.3]-框架總結:術語表和PHP開發建議
- [5.4]-許可
- [5.5]-聯系和加入我們
- [5.6]-更新日記
- [5.8]-致框架貢獻者:加入PhalApi開源指南
- [6.1]-基于接口查詢語言的SDK包
- [6.2]-SDK包(JAVA版)
- [6.3]-SDK包(PHP版)
- [6.4]-SDK包(Objective-C版)
- [6.5]-SDK包(javascript版)
- [6.6]-SDK包(Ruby版)
- [8.1]-PhalApi視頻教程
- 附錄1:接口文檔參考模板