首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

ThinkPHP 開發移動端 API 接口與自動模板切換兩大方案

     編輯:PHP 綜合知識

方案一:原生 API 接口(JSON 輸出、統一規範)

公共輔助函數 (Common/function.php)

// 成功返回
function returnApiSuccess($msg = '', $data = []) {
    exit(json_encode([
        'flag' => 'Success',
        'msg'  => $msg,
        'data' => $data,
    ], JSON_UNESCAPED_UNICODE));
}

// 失敗返回
function returnApiError($msg = '') {
    exit(json_encode([
        'flag' => 'Error',
        'msg'  => $msg,
    ], JSON_UNESCAPED_UNICODE));
}

// 系統繁忙
function returnApiErrorExample() {
    returnApiError('當前系統繁忙,請稍後重試!');
}

// 參數校驗 (POST)
function checkDataPost($required = '') {
    if ($required) {
        foreach (explode(',', $required) as $field) {
            if (!isset($_POST[$field]) || $_POST[$field] === '') {
                returnApiError("$field 不能為空");
            }
        }
    }
    $data = I('post.');
    unset($data['_URL_'], $data['token']);
    return $data;
}

// 參數校驗 (GET)
function checkDataGet($required = '') {
    if ($required) {
        foreach (explode(',', $required) as $field) {
            if (!isset($_GET[$field]) || $_GET[$field] === '') {
                returnApiError("$field 不能為空");
            }
        }
    }
    $data = I('get.');
    unset($data['_URL_'], $data['token']);
    return $data;
}

控制器示例

class ApiController extends Controller {
    // 獲取單個發布信息
    public function getReleaseInfo() {
        checkDataPost('id'); // 必傳 id
        $where['id'] = I('post.id');
        $field = 'id,fruit_name,high_price,low_price,address,size,weight,fruit_pic,remark';

        $info = D('Release')->field($field)->where($where)->find();
        if (!$info) returnApiError('未找到信息');

        // 截取備註
        $info['remark'] = mb_substr($info['remark'], 0, 49, 'utf-8') . '...';

    // 圖片路徑拼接完整 URL
        $info['fruit_pic'] = array_filter(explode(',', $info['fruit_pic']));
        foreach ($info['fruit_pic'] as &$pic) {
            $pic = 'https://' . $_SERVER['HTTP_HOST'] . '/Uploads/Release/' . $pic;
        }

        returnApiSuccess('', $info);
    }
}

App 端接收示例 (JSON 解碼後)

{
  "flag": "Success",
  "msg": "",
  "data": {
    "id": "2",
    "fruit_name": "蘋果",
    "high_price": "8.0",
    "low_price": "5.0",
    "address": "天津小白樓水果市場",
    "size": "2.0",
    "weight": "2.0",
    "remark": "急需...",
    "fruit_pic": [
      "https://fruit.example.com/Uploads/Release/201508/xxx.png",
      "https://fruit.example.com/Uploads/Release/201508/yyy.jpg"
    ]
  }
}

方案二:移動端自動切換模板主題(偽原生、開發效率高)

1. 移動設備檢測函數 (Common/common.php)

function is_mobile() {
    // 1. 標準頭
    if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) return true;
    if (isset($_SERVER['HTTP_CLIENT']) && $_SERVER['HTTP_CLIENT'] === 'PhoneClient') return true;
    if (isset($_SERVER['HTTP_VIA']) && stripos($_SERVER['HTTP_VIA'], 'wap') !== false) return true;

    // 2. User-Agent 關鍵字
    if (isset($_SERVER['HTTP_USER_AGENT'])) {
        $keywords = ['nokia','sony','ericsson','mot','samsung','htc','sgh','lg','sharp','sie-',
                     'philips','panasonic','alcatel','lenovo','iphone','ipod','blackberry',
                     'meizu','android','netfront','symbian','ucweb','windowsce','palm',
                     'operamini','operamobi','openwave','nexusone','cldc','midp','wap','mobile'];
        if (preg_match('/(' . implode('|', $keywords) . ')/i', $_SERVER['HTTP_USER_AGENT'])) {
            return true;
        }
    }

    // 3. Accept 頭判斷
    if (isset($_SERVER['HTTP_ACCEPT'])) {
        $accept = $_SERVER['HTTP_ACCEPT'];
        if (strpos($accept, 'vnd.wap.wml') !== false &&
            (strpos($accept, 'text/html') === false ||
             strpos($accept, 'vnd.wap.wml') < strpos($accept, 'text/html'))) {
            return true;
        }
    }
    return false;
}

2. 公共控制器基類 (Lib/Action/CommonAction.class.php)

class CommonAction extends Action {
    protected function _initialize() {
        if (is_mobile()) {
            // 切換到 Mobile 主題
            C('DEFAULT_THEME', 'Mobile');
            // 可選:設置移動端專用佈局
            // $this->layout = 'Layout/mobile';
        }
        // 其他通用初始化:權限檢查、菜單數據等
    }
}

3. 目錄結構

Tpl/
├── default/          # PC 模板
│   ├── Index/
│   │   └── index.html
│   └── Layout.html
└── Mobile/           # 移動端模板
    ├── Index/
    │   └── index.html
    └── Layout.html

4. 控制器繼承

class IndexAction extends CommonAction {
    public function index() {
        $this->display(); // 自動渲染 Tpl/Mobile/Index/index.html (移動端) 或 Tpl/default/...
    }
}

方案對比與選擇建議

維度方案一:原生 API方案二:模板切換
架構模式前後端分離服務端渲染 (SSR)
App 開發原生/Flutter/React Native 直接調用WebView/H5 混合開發
性能極佳 (僅傳數據)一般 (傳 HTML+CSS+JS)
SEO需額外 SSR/預渲染天然友好
開發效率需雙端協作單端模板複用 PC 邏輯
維護成本接口文檔、版本管理模板同步修改
推薦場景成熟 App、多端複用、高併發快速上線、H5 為主、資源有限

進階:API 版本控制與簽名驗證

// 基礎控制器增加簽名驗證
class ApiBase extends Controller {
    protected function _initialize() {
        // 1. 版本控制
        $version = I('get.v', '1.0');
        define('API_VERSION', $version);

        // 2. 簽名驗證 (簡化版)
        $params = $_GET;
        unset($params['sign']);
        ksort($params);
        $signStr = http_build_query($params) . '&key=' . C('API_SECRET');
        if (md5($signStr) !== I('get.sign')) {
            returnApiError('簽名驗證失敗');
        }

        // 3. 限流 (Redis)
        $ip = get_client_ip();
        $key = "api_limit:$ip:" . date('YmdH');
        $count = S($key) ?: 0;
        if ($count > 1000) returnApiError('請求過於頻繁');
        S($key, $count + 1, 3600);
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved