主目录: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中默认处理。