本文来自 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 应用的开发!