此文章发布于60
个月前,部分信息可能已经过时
,请自行斟酌确认。
需求背景
微酷最近使用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。