函式計算PHP Runtime - exception 處理
在本文中,我們來細化講講函式計算中 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 庫,比如ofollow,noindex" target="_blank">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; } // set to the user defined error handler set_error_handler("myErrorHandler"); 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); }
總結
本文中,詳細解析了函式計算 php runtime 中對於異常的處理, 在php runtime 中,嚴格規範程式碼,我們期望加強檢查以便減少使用者編寫diamante犯錯的可能,但是針對一些第三方庫的引入使用可能因為warning或者notice而無法使用時,函式計算允許使用者通過自定義的set_error_handler來覆蓋runtime中預設處理。