在本文中,我们根据一个具体的问题的抛出以及解决的过程,来讲解php runtime 中怎么对 内置的扩展进行加载和卸载。
主目录:php runtime FAQ
问题
根据官方文档 php执行环境内置库可以知道, 函数计算环境中内置了tablestore php sdk,但是编写如下代码使用该 sdk 编写如下代码:
<?php
use Aliyun\OTS\Consts\ColumnTypeConst;
use Aliyun\OTS\Consts\PrimaryKeyTypeConst;
use Aliyun\OTS\Consts\RowExistenceExpectationConst;
use Aliyun\OTS\OTSClient as OTSClient;
function handler($event, $context) {
$logger = $GLOBALS['fcLogger'];
$logger->info('FC recv:'.$event);
$accessKeyId = $context["credentials"]["accessKeyId"];
$accessKeySecret = $context["credentials"]["accessKeySecret"];
$securityToken = $context["credentials"]["securityToken"];
$endpoint = "cn-shanghai.ots.aliyuncs.com";
$otsClient = new OTSClient (array (
'EndPoint' => $endpoint,
'AccessKeyID' => $accessKeyId,
'AccessKeySecret' => $accessKeySecret,
'InstanceName' => 'iot-qyt',
'StsToken' => $securityToken
));
$request = array (
'table_name' => 'gateway',
'primary_key' => array ( // 主键
array('id', 'abcd')
),
"max_versions" => 1
);
$response = $otsClient->getRow ($request);
print json_encode ($response);
return;
}
点击运行的时候,会出现如下错误:
{
"errorMessage": "Call to undefined method Google\\Protobuf\\Internal\\DescriptorPool::getDescriptorByClassName()",
"errorType": "Error",
"stackTrace": {
"file": "/var/fc/runtime/php7.2/builtIn/vendor/aliyun/aliyun-tablestore-sdk-php/src/OTS/ProtoBuffer/Protocol/Message.php",
"line": 46,
"traceString": ""
}
}
原因
目前函数计算的 php 安装 protobuf 扩展,而tablestore 依赖使用了php 脚本版本的protobuf,此时tablestore sdk 优先使用了扩展,就出现了上面的这种错误
解法
在函数计算的php runtime 中,为了支持用户自定义增加和删减内置扩展,扩展没有采用built-in php 形式,这就给了用户自由操作的空间。在官方教程中,有使用自定义扩展 教程,但是针对内置扩展的选用却没有涉及,在本文中,我们探讨怎么删减或替换内置的扩展。
首先看一下,函数计算有哪些扩展:
extension=session.so
extension=ftp.so
extension=shmop.so
extension=bcmath.so
extension=gettext.so
extension=pcntl.so
extension=simplexml.so
extension=xmlreader.so
extension=bz2.so
extension=gmp.so
extension=pdo.so
extension=soap.so
extension=xmlrpc.so
extension=calendar.so
extension=iconv.so
extension=pdo_mysql.so
extension=sockets.so
extension=xmlwriter.so
extension=ctype.so
extension=imagick.so
extension=phar.so
extension=sysvmsg.so
extension=dom.so
extension=json.so
extension=posix.so
extension=sysvsem.so
extension=exif.so
extension=zip.so
extension=memcached.so
extension=mbstring.so
extension=protobuf.so
extension=sysvshm.so
extension=fileinfo.so
extension=mysqli.so
extension=redis.so
extension=tokenizer.so
extension=zip.so
extension=memcached.so
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/opcache.so
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/xdebug.so
在这个案例中,我们不希望引入 protobuf 这个 extension 影响 php 版本的google/protobuf 的使用,具体操作如下:
- 在函数入口文件的相同目录创建一个 extension 目录,目录如下:
.
|____extension
| |____my_ext.ini
|____index.php
- 编辑 my_ext.ini, 注释掉protobuf。
注:这里可以增加其他extension和注释掉其他不需要的extension, 优化php runtime 的启动速度。
extension=session.so
extension=ftp.so
extension=shmop.so
extension=bcmath.so
extension=gettext.so
extension=pcntl.so
extension=simplexml.so
extension=xmlreader.so
extension=bz2.so
extension=gmp.so
extension=pdo.so
extension=soap.so
extension=xmlrpc.so
extension=calendar.so
extension=iconv.so
extension=pdo_mysql.so
extension=sockets.so
extension=xmlwriter.so
extension=ctype.so
extension=imagick.so
extension=phar.so
extension=sysvmsg.so
extension=dom.so
extension=json.so
extension=posix.so
extension=sysvsem.so
extension=exif.so
extension=zip.so
extension=memcached.so
extension=mbstring.so
;extension=protobuf.so
extension=sysvshm.so
extension=fileinfo.so
extension=mysqli.so
extension=redis.so
extension=tokenizer.so
extension=zip.so
extension=memcached.so
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/opcache.so
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/xdebug.so
- 基于上述目录的代码包创建函数
- 设置函数的环境变量,PHP_INI_SCAN_DIR 指向代码目录下面的
my_ext.ini
, 此时 php 没有加载 protobuf 扩展。
这个时候,执行上面有关tablestore的操作就没有问题了。
总结
本文通过一个问题的解法,抛出函数计算环境中怎么加载和卸载扩展的原理和机制,函数计算php runtime 内置组都多的扩展给用户方便的同时,又给与用户更加高阶的对扩展自定义操作,祝大家在世界第一语言的环境中玩的开心。