zoukankan      html  css  js  c++  java
  • 云函数 SCF 中 PHP 的一些入门坑

    本文来自 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 = 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 实战开发!

    传送门:

    欢迎访问:Serverless 中文网,您可以在 最佳实践 里体验更多关于 Serverless 应用的开发!


    推荐阅读:《Serverless 架构:从原理、设计到项目实战》

  • 相关阅读:
    团队编程规范
    软工小组:我们都是水果
    Github与SmartGit使用说明与建议
    Github for Windows使用图文教程
    SQL语句实现mysql数据库快速插入1000w条数据
    dijkstra+relax修改
    Kuchiguse (20)简单字符串处理,输入坑
    1098. Insertion or Heap Sort (25)堆排序
    Consecutive Factors(求n的连续约数)
    Dijkstra(第二关键词最优),路径保存DFS
  • 原文地址:https://www.cnblogs.com/serverlesscloud/p/13225391.html
Copyright © 2011-2022 走看看