本文來自 Serverless 社區用戶「逸笙」投稿javascript
因爲雲函數 SCF 自己是用 bootstrap.php
來調用咱們的入口函數,默認爲 index.main\_handler
,意思是調用 index.php
文件中的 main\_handler()
,因此不少地方寫法要有改變。php 通常提供網頁服務,因此我主要講API 網關配合的雲函數 SCF。php
main_handler($event, $context)函數會傳入2個參數,首先這2個參數是object,須要用->來訪問子項,如 $event->{'headers'} ,不是很方便,我通常轉換成數組:html
$event = json_decode(json_encode($event), true);
這樣就比較方便了,如 $event['headers']['host'] 。java
你們能夠打印這兩個參數看一眼裏面有些什麼。git
咱們能夠從中獲取到不少有用的東西,好比:github
$_GET = $event['queryString']; $_POST = $event['body']; $_COOKIE = $event['headers']['cookie'];
在雲函數 SCF 中運行的 php 程序,由於瀏覽器是提交給 API 網關,不是提交給 SCF 的,這些超全局變量徹底沒有獲取到東西,因此要這樣來獲取。express
但咱們發現,$event['body']
與 $event['headers']['cookie']
自己是一個長字符串,裏面有好幾個值,而且裏面 url 編碼了,這樣不方便使用,因此作些小操做:json
$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)); }
這樣就方便使用了。bootstrap
在雲函數 SCF 中,全局變量目前有個坑,就是上次訪問獲取的全局變量在此次並不會清空,因此本次訪問的時候,上次提交的值可能還在全局變量中,這個狀況無論是 php 固有的超全局仍是本身定義的,都有這個狀況,因此使用前注意 unset。api
用戶提交過來的數據,除了 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 = 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 ,不吝賜教!
3 秒你能作什麼?喝一口水,看一封郵件,仍是 —— 部署一個完整的 Serverless 應用?
複製連接至 PC 瀏覽器訪問:https://serverless.cloud.tencent.com/deploy/express
3 秒極速部署,當即體驗史上最快的 Serverless HTTP 實戰開發!
傳送門:
- GitHub: github.com/serverless
- 官網:serverless.com
歡迎訪問:Serverless 中文網,您能夠在 最佳實踐 裏體驗更多關於 Serverless 應用的開發!