本文來自 Serverless 社區用戶「逸笙」投稿
由于云函式 SCF 本身是用 bootstrap.php 來呼叫我們的入口函式,默認為 index.main\_handler,意思是呼叫 index.php 檔案中的 main\_handler(),所以很多地方寫法要有改變,php 一般提供網頁服務,所以我主要講API 網關配合的云函式 SCF,
main_handler($event, $context)函式會傳入2個引數,首先這2個引數是object,需要用->來訪問子項,如 $event->{'headers'} ,不是很方便,我一般轉換成陣列:
$event = json_decode(json_encode($event), true);
這樣就比較方便了,如 $event['headers']['host'] ,
大家可以列印這兩個引數看一眼里面有些什么,
我們可以從中獲取到很多有用的東西,比如:
$_GET = $event['queryString'];
$_POST = $event['body'];
$_COOKIE = $event['headers']['cookie'];
在云函式 SCF 中運行的 php 程式,因為瀏覽器是提交給 API 網關,不是提交給 SCF 的,這些超全域變數完全沒有獲取到東西,所以要這樣來獲取,
但我們發現,$event['body'] 與 $event['headers']['cookie'] 本身是一個長字串,里面有好幾個值,并且里面 url 編碼了,這樣不方便使用,所以做些小操作:
$postbody = explode("&",$event['body']);
foreach ($postbody as $postvalues) {
$pos = strpos($postvalues,"=");
$_POST[urldecode(substr($postvalues,0,$pos))]=urldecode(substr($postvalues,$pos+1));
}
$cookiebody = explode("; ",$event['headers']['cookie']);
foreach ($cookiebody as $cookievalues) {
$pos = strpos($cookievalues,"=");
$_COOKIE[urldecode(substr($cookievalues,0,$pos))]=urldecode(substr($cookievalues,$pos+1));
}
這樣就方便使用了,
在云函式 SCF 中,全域變數目前有個坑,就是上次訪問獲取的全域變數在這次并不會清空,所以本次訪問的時候,上次提交的值可能還在全域變數中,這個情況不管是 php 固有的超全域還是自己定義的,都有這個情況,所以使用前注意 unset,
用戶提交過來的資料,除了 GET、POST、COOKIE,還有一種比較重要的就是路徑了,比如這樣一個 url: https://hostname/path/file.jpg?foo=bar,在 API 網關中,/path/file.jpg 會被放到 $event['path'] 中,但注意,如果通過 API 網關默認 url 訪問,里面會含有 /functionname ,注意去除(以下代碼將路徑里起始的 '/' 也去除了):
$function_name = $context['function_name'];
$host_name = $event['headers']['host'];
$serviceId = $event['requestContext']['serviceId'];
if ( $serviceId === substr($host_name,0,strlen($serviceId)) ) {
// using long url of API gateway
// 使用API網關長鏈接時
$path = substr($event['path'], strlen('/' . $function_name . '/'));
} else {
// using custom domain
// 使用自定義域名時
$path = substr($event['path'], strlen($event['requestContext']['path']=='/'?'/':$event['requestContext']['path'].'/'));
}
取得用戶提交的資訊后,就可以自己處理了,程序不詳談,只是注意:
SCF 是只讀的,只有
/tmp/目錄可讀寫,這個 tmp 目錄并發實體間互不相通,實體結束后銷毀,
處理完后,就要輸出給瀏覽器了,注意,因為跟瀏覽器對話的是 API 網關,
在代碼中直接 echo 的話,只會顯示在運行日志中,瀏覽器完全看不到,
所以
我們需要在
main\_handler中把需要顯示的東西 return 給 API 網關,
這時,如果要回傳一個網頁,那 API 網關要勾選「集成回應」,SCF 這邊要回傳一個特定結構的陣列,這樣瀏覽器才會正常顯示,不然瀏覽器就會只看到一堆字串,
return [
'isBase64Encoded' => false,
'statusCode' => 200,
'headers' => [ 'Content-Type' => 'text/html' ],
'body' => $html
];
其中 body 就是我們要回傳的網頁內容,是個字串;
headers 是給瀏覽器辨認的,Location 或 Set-Cookie 要放在這里面;
statusCode 是狀態碼,可以在 Location 時為 302,也可以在某些時候 404;
isBase64Encoded 是 API 網關用的,告訴它,body 里面是否 base64 加密,
這樣回傳,瀏覽器就會顯示一個 HTML 網頁了,
但有些時候,我們想給一個檔案給用戶下載,這時候,就要用到 isBase64Encoded 了:
$image_data = https://www.cnblogs.com/serverlesscloud/p/fread(fopen('logo.png', 'r'), filesize('logo.png'));
return [
'isBase64Encoded' => true,
'statusCode' => 200,
'headers' => [ 'Content-Type' => 'image/png' ],
'body' => base64_encode($image_data)
];
這樣瀏覽器會直接得到一個 png 檔案,有些瀏覽器彈出下載,有些自己就打開了,
上面代碼已經提交到云函式 SCF 模板庫:https://github.com/tencentyun/scf-demo-repo/tree/master/Php7.2-QRcodewithLogo ,不吝賜教!
One More Thing
3 秒你能做什么?喝一口水,看一封郵件,還是 —— 部署一個完整的 Serverless 應用?
復制鏈接至 PC 瀏覽器訪問:https://serverless.cloud.tencent.com/deploy/express
3 秒極速部署,立即體驗史上最快的 Serverless HTTP 實戰開發!
傳送門:
- GitHub: github.com/serverless
- 官網:serverless.com
歡迎訪問:Serverless 中文網,您可以在 最佳實踐 里體驗更多關于 Serverless 應用的開發!
推薦閱讀:《Serverless 架構:從原理、設計到專案實戰》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/2240.html
標籤:其他
