函数计算PHP Runtime - exception 处理

主目录:php runtime FAQ

在本文中,我们来细化讲讲函数计算中 php runtime 中的异常处理问题,在官方文档中 php runtime 错误处理 没有讲解函数计算php runtime 环境中对于具体的错误类型是怎么处理的?比如级别很低的notice或者warning, 先来看几个例子:

example

Warning
<?php
function handler($event, $context) {
  $a = 1/0;
  return "ok";
}

执行结果:

{
   "errorMessage": "Division by zero",
   "errorType": "ErrorException",
   "stackTrace": {
      "file": "/code/index.php",
      "line": 3,
      "traceString": ""
   }
} 
NOTICE
<?php
function handler($event, $context) {
  $a = ["a" => 1, "b" => 2];
  $b = $a["c"];
  return "ok";
}

执行结果:

 {
   "errorMessage": "Undefined index: c",
   "errorType": "ErrorException",
   "stackTrace": {
      "file": "/code/index.php",
      "line": 11,
      "traceString": ""
   }
} 

从上面两个例子我们可以看出,函数计算的 php runtime 对代码检查十分严格,不管什么级别的ERROR_TYPE, 都是按照异常来处理,但是有些使用有些php库的时候,可能会有一些warning或者notice,这个时候会导致在函数计算的环境中不能使用这种php 库,比如aliyun-openapi-php-sdk

比如下面的代码:

<?php

require_once __DIR__ . '/aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php';
use imm\Request\V20170906 as Imm;

define('PREVIEWURL', 'https://preview.imm.aliyun.com/index.html');

function handler($event, $context) {
    $accessKeyId     = $context["credentials"]["accessKeyId"];
    $accessKeySecret = $context["credentials"]["accessKeySecret"];
    $securityToken   = $context["credentials"]["securityToken"];
    $region          = $context['region'];

    $iClientProfile = DefaultProfile::getProfile(
        $region,
        $accessKeyId,
        $accessKeySecret,
        $securityToken
    );

    $client         = new DefaultAcsClient($iClientProfile);
    $PREVIEWTGTPATH = 'fc-demo-preview-output-php';
    $immProject     = "imm-demo";
    $srcUri         = "oss://fc-imm-demo/test-data/office/test.pptx";

    $bucket   = "fc-imm-demo";
    $fileName = "test.pptx";
    $tgtUri   = sprintf("oss://%s/%s/%s", $bucket, $PREVIEWTGTPATH, $fileName);

    $request = new Imm\CreateOfficeConversionTaskRequest();
    $request->setProject($immProject);
    $request->setSrcUri($srcUri);
    $request->setTgtType("vector");
    $request->setTgtUri($tgtUri);
    $response = $client->getAcsResponse($request);
    print_r($response);
}

执行就会收到这个错误, 上面 example 中的 NOTICE 转变为exception:

 {
   "errorMessage": "Undefined index: cn-hangzhou#imm",
   "errorType": "ErrorException",
   "stackTrace": {
      "file": "/code/aliyun-openapi-php-sdk/aliyun-php-sdk-core/Regions/LocationService.php",
      "line": 58,
      "traceString": ""
   }
} 

php runtime 中自定义error_handler

当遇见上面所述对的问题时,我们如何规避这种问题呢?答案是使用set_error_handler 来定义自己的处理方法,从而屏蔽runtime中严格处理, 对于 Warning 和 Notice 这种级别等错误, 详情可以参考:http://www.php.net/manual/zh/function.set-error-handler.php

对于上面这种问题,我们修改代码如下:

<?php

require_once __DIR__ . '/aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php';
use imm\Request\V20170906 as Imm;

define('PREVIEWURL', 'https://preview.imm.aliyun.com/index.html');

function myErrorHandler($errno, $errstr, $errfile, $errline) {
    if (!(error_reporting() & $errno)) {
        return false;
    }

    switch ($errno) {
    case E_USER_ERROR:
        $errInfo = array(
            "errorMessage" => $errstr,
            "errorType"    => \ServerlessFC\friendly_error_type($errno),
            "stackTrace"   => array(
                "file" => $errfile,
                "line" => $errline,
            ),
        );
        throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
        break;

    default: // E_USER_WARNING | E_USER_NOTICE
        break;
    }

    /* Don't execute PHP internal error handler */
    return true;
}

function handler($event, $context) {
    // set to the user defined error handler
    set_error_handler("myErrorHandler");
    
    $accessKeyId     = $context["credentials"]["accessKeyId"];
    $accessKeySecret = $context["credentials"]["accessKeySecret"];
    $securityToken   = $context["credentials"]["securityToken"];
    $region          = $context['region'];

    $iClientProfile = DefaultProfile::getProfile(
        $region,
        $accessKeyId,
        $accessKeySecret,
        $securityToken
    );

    $client         = new DefaultAcsClient($iClientProfile);
    $PREVIEWTGTPATH = 'fc-demo-preview-output-php';
    $immProject     = "imm-demo";
    $srcUri         = "oss://fc-imm-demo/test-data/office/test.pptx";

    $bucket   = "fc-imm-demo";
    $fileName = "test.pptx";
    $tgtUri   = sprintf("oss://%s/%s/%s", $bucket, $PREVIEWTGTPATH, $fileName);

    $request = new Imm\CreateOfficeConversionTaskRequest();
    $request->setProject($immProject);
    $request->setSrcUri($srcUri);
    $request->setTgtType("vector");
    $request->setTgtUri($tgtUri);
    $response = $client->getAcsResponse($request);
    print_r($response);
}

总结

本文中,详细解析了函数计算 php runtime 中对于异常的处理, 在php runtime 中,严格规范代码,我们期望加强检查以便减少用户编写代码犯错的可能,但是针对一些第三方库的引入使用可能因为warning或者notice而无法使用时,函数计算允许用户通过自定义的set_error_handler来覆盖runtime中默认处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值