【玩转腾讯云】SCF中php的一些入门坑

作者本身去年才开始接触php与SCF,如有错误请不吝指教。

由于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: i21aA.D.e8/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 ,目前SCF中的QRcode模板代码只有二维码演示,还没有文件下载演示,等待官方同步。

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
【玩转腾讯云】SCF中php的一些入门坑
由于SCF本身是用bootstrap.php来调用我们的入口函数,默认为index.main_handler,意思是调用index.php文件中的main_ha...
<<上一篇
下一篇>>