API 介面需統一回傳結構:{retcode, msg, data},並支援多種輸出格式 (JSON、XML、JSONP、Array) 以滿足不同客戶端需求。DataReturn 類別封裝此邏輯,一行代碼即可完成格式化輸出。
<?php
class DataReturn {
private $type, $xmlroot, $callback, $returnData;
public function __construct(array $param = []) {
$this->type = strtoupper($param['type'] ?? 'JSON'); // JSON, XML, CALLBACK, ARRAY
$this->xmlroot = $param['xmlroot'] ?? 'xmlroot';
$this->callback = $param['callback'] ?? '';
$fmt = $param['format'] ?? [];
$retcodeKey = $fmt['retcode'] ?? 'retcode';
$msgKey = $fmt['msg'] ?? 'msg';
$dataKey = $fmt['data'] ?? 'data';
$this->returnData = [
$retcodeKey => $param['retcode'] ?? 0,
$msgKey => $param['msg'] ?? '',
$dataKey => $param['data'] ?? ''
];
}
public function data_return() {
ob_clean();
switch ($this->type) {
case 'JSON': $this->json_return(); break;
case 'XML': $this->xml_return(); break;
case 'CALLBACK':$this->callback_return(); break;
case 'ARRAY': $this->array_return(); break;
default: $this->json_return();
}
exit;
}
private function json_return() {
header('Content-Type: application/json; charset=utf-8');
if ($this->callback)
echo $this->callback . '(' . json_encode($this->returnData) . ');';
else
echo json_encode($this->returnData);
}
private function xml_return() {
header('Content-Type: text/xml; charset=utf-8');
echo $this->xml_encode($this->returnData, $this->xmlroot);
}
private function callback_return() {
header('Content-Type: text/html; charset=utf-8');
$cb = $this->callback ?: 'callback';
echo "<script>$cb(" . json_encode($this->returnData) . ");</script>";
}
private function array_return() {
// 僅內部呼叫用,不直接輸出
var_dump($this->returnData);
}
private function xml_encode($data, $root) {
$xml = "<?xml version='1.0' encoding='utf-8'?><$root>";
foreach ($data as $k => $v) {
$xml .= "<$k>" . (is_array($v) ? $this->xml_encode($v, 'item') : htmlspecialchars($v)) . "</$k>";
}
$xml .= "</$root>";
return $xml;
}
}
<?php
require 'DataReturn.class.php';
// 成功回傳 JSON
$ret = new DataReturn([
'type' => 'JSON',
'retcode' => 200,
'msg' => 'OK',
'data' => ['id' => 1, 'name' => 'Test']
]);
$ret->data_return();
// 失敗回傳 JSONP (前端傳 ?callback=myFunc)
$ret = new DataReturn([
'type' => 'CALLBACK',
'callback' => $_GET['callback'] ?? '',
'retcode' => 400,
'msg' => '參數錯誤'
]);
$ret->data_return();
code/retcode/status 等)。type 參數決定輸出,業務邏輯無需關心格式細節。callback(...) 而非 <script> 标签,避免 XSS 風險 (需前端信任來源)。exit 確保無額外輸出干擾。JsonSerializable 介面,讓領域物件自行定義序列化形態。ResponseInterface,回傳 Response 物件而非直接輸出,利於測試與中介軟體處理。spatie/array-to-xml) 處理屬性、命名空間、CDATA 等細節。DataReturn 以單一類別統一 API 回傳格式與多格式輸出,大幅減少控制器樣板代碼。理解其「配置驅動輸出」思想,有助於構建一致、可維護的 API 基礎設施。