此文章发布于72个月前,部分信息可能已经过时,请自行斟酌确认。
需求背景
微酷最近使用ThinkPHP框架开发了一个移动应用的 api 服务端,通过php_pdo_sqlsrv扩展和MSSQL数据库交互。移动前端技术采用vue + framework7开发,然后发现前端表单页面报错,错误内容大体为:控件期望得 Number 数字类型,结果得到的却是 String 字符串类型。看了下服务端 api 返回的json数据,发现原本数据库(MSSQL)中decimal类型的字段被解释成了string字符串,也就是说json值两边加了引号。
项目环境:
- 服务器:Windows Server 2016 + IIS
- 数据库:Sql Server 2016
- PHP:7.3 + php_pdo_sqlsrv 5.6
- 服务端开发框架:ThinkPHP 5.1
- 移动端:vue + Framework7
解决思路
解决这个问题方法可能有好多,比如前端类转换型,或者服务端 TP 框架的模型也可以定义字段的类型转换,但微酷感觉这样还是麻烦,希望能从根本上解决这个问题,也就是说MSSQL数据库中的decimal字段,提取到 php 中能自动当做float类型(php 是没有 decimal 类型的)。
搜索方案
网上搜索了大半天,发现微软的 SqlSrv 只能将 decimal 类型转为 string 字符串,官方表示也不打算支持转换为 decimal,具体原因见:https://github.com/Microsoft/msphpsql/issues/291。同时链接中也有微软官方人员给出了解决方案:自己修改 SqlSrv 驱动的源代码编译后自用。
那就自己编译吧。
===== PHP 7.3 源码编译 =====
参考资料
- https://wiki.php.net/internals/windows/stepbystepbuild
- https://github.com/Microsoft/msphpsql/tree/dev/buildscripts#windows
编译环境搭建
安装 vs2017
php 7.2、7.3 需要 C++ v15 编译,需要安装 vs2017 的 C++ 功能。

安装后可能要重启,如提示的话重启一下电脑。
下载 php-sdk-binary-tools
下载地址:https://github.com/Microsoft/php-sdk-binary-tools
下载后解压到喜欢的地方,如微酷这里解决到D:\php-sdk,如图:
下载 PHP 源码
下载地址:https://github.com/php/php-src
选择需要编译的 php 版本的分支,然后下载。
微酷这里下载7.3.4版本。
编译 PHP 步骤
运行命令提示符号进入到刚才解决的php-sdk目录(目录名微酷修改过)
运行命令:
phpsdk-vc15-x64.bat其中vc15和x64要根据编译的php版本来定,这里微酷要编译64位的php 7.3,所以要运行vc15的脚本,如图:
继续在当前目录运行命令:
phpsdk_buildtree phpdev注意:这个脚本在bin目录下,不过可以直接在此目录运行。执行后会在当前目录自动创建phpdev目录。
解压 PHP 源码:将之前下载的源码解压到:D:\php-sdk\phpdev\vc15\x64\php-src-7.3.4,如图(文件夹名可改)

下载依赖:还是在之前打开的命令提示符窗口进入到 php 源码目录,然后执行以下命令:
phpsdk_deps -u执行后开始自动下载编译所需要的依赖,下载后会放到D:\php-sdk\phpdev\vc15\x64\deps目录中。下载可能有点慢,等几分钟就好了,一共大约 30 多个文件需要下载,如图。
命令提示符任然定位在 php 源码目录,执行命令:buildconf,然后会提示执行configure --help可以查看可用的参数。

最终微酷使用以下参数编译php:configure --disable-all --enable-cli --disable-zts,其中--disable-zts是生成 NTS 版本的 php。

最后执行执行nmake,执行nmake就开始编译 php 啦,等一会就 ok 了。完成如图:

测试,编译完成后的 php.exe 在源码目录的x64\release目录(根据编译版本目录会不同),运行php -v 测试一下吧。

===== 编译 PHP 扩展=====
微酷这里以编译 pdo_sqlsrv 扩展为例讲解步骤。
- 下载 php_pdo_sqlsrv 源码:https://github.com/Microsoft/msphpsql
- 解压后将
source\shared目录拷贝到source\pdo_sqlsrv和source\sqlsrv各一份。 - 拷贝
source目录下的sqlsrv和pdo_sqlsrv目录到上文中提的 PHP 源码目录下的ext子目录。
- 好了,到这里就可以和前面编译 PHP 一样开始编译扩展了,只是编译配置增加了和扩展相关的参数,这里微酷一次性将所有命令全都列出来,依次执行即可。
# 重新构建 configure.js 以包含进 sqlsrv 和 pdo_sqlsrv 驱动扩展
buildconf --force
# 生成 makefile,启动 sqlsrv、pdo、pdo_sqlserv
configure --disable-all --enable-cli --disable-zts --enable-sqlsrv=shared --enable-pdo --with-pdo-sqlsrv=shared
--编译,编译前可以先执行一下 nmake clean 清理之前的文件
nmake
最终生成的扩展和上面生成的 php.exe 在一起,编译完成。
SqlSrv 将 mssql 中 decimal 类型转为 php 的 float 修改方法
修改pdo_sqlsrv\pdo_stmt.cpp文件,定位到1430行附近找到case SQL_DECIMAL:,移动到case SQL_FLOAT:下面。

编译后编译即可,微酷测试ok。