PHP 扩展是什么?通俗解释 PHP 扩展的功能与优势
什么是 PHP 扩展

通俗来讲,PHP 扩展属于增强 PHP 语言功能的一类插件。PHP 为我们提供了编程语言的相关语法,其中包含了分支、循环、函数以及类等方面,而这些都是 PHP 自身所具备的。在某些情形下若需在 PHP 语言基础上进行拓展,就需借助 PHP 底层所提供的数据结构与接口来开发 PHP 扩展,以此来对 PHP 语言进行补充或扩展,让其更为强大。当然,PHP 自身已集成了一些基础性、强大性、优秀性的 PHP 扩展。
PHP 扩展的好处
从上面的了解可知,PHP 扩展能够在 PHP 原本的基础上对其功能进行扩展,让它变得更加强大。另外,PHP 扩展可以借助“插件式”的办法来管理和维护 PHP 的功能。如果把全部功能都整合到 PHP 语言中,那么 PHP 可能会过于臃肿,并且也不够灵活。而有了扩展,就把这个问题给解决了。
PHP 扩展的存在形式
在 Linux 系统当中,PHP 扩展是以.so 文件的形式而存在的。在 Windows 系统之下,PHP 扩展则是以.dll 文件的形式而存在的。
什么时候使用 PHP 扩展
单独使用 PHP 语言无法满足所有开发需求。例如在项目中使用 Redis 或 MongoDB 时,就需要相应的 PHP 扩展。通过这些扩展可以增强 PHP 语言,使 PHP 能够操作 Redis 或者 MongoDB,从而完成功能更强大的项目。
什么时候开发自己的 PHP 扩展
开发自己的 PHP 扩展是否是必须的呢?答案其实是否定的。一般而言,作为一个 PHPer ,通常不需要自己去开发 PHP 扩展。然而,在某些特定的情况下,可能就必须要开发 PHP 扩展了。例如,我就碰到了这样的问题。合作的第三方给出了 Windows 下的动态链接库文件,即.dll 文件,且这并非 COM 的 DLL 文件。然而,我未能找到在 PHP 下加载和调用 DLL 文件的方法。所以,我需要编写 PHP 扩展,借助 PHP 的扩展来实现对第三方提供的 DLL 文件的加载与调用。
开发自己的 PHP 扩展
我之前已经提及了所遇到的问题,合作的第三方提供了适用于 Windows 的动态链接库文件。然而,我未能找到在 PHP 环境下加载和调用 DLL 文件的方法,所以决定自己编写 PHP 扩展,以实现加载和调用第三方提供的 DLL 文件中的导出函数。以下是我关于搭建开发 PHP 扩展环境的记录,同时也是我对编译 PHP 扩展源码的记录。
准备工具
首先说明,DLL 文件仅能在 Windows 系统中运行,在 Linux 系统中无法运行。接着,我们的这个扩展不将 Linux 系统纳入考虑范围,只需考虑 Windows 系统就行。所以,准备的开发工具是 VS2015。起初,我在网上进行资料查找。很多资料都提到,在 Windows 下开发 PHP 扩展需安装 CygWin。通过我自己的学习,现在可以告知大家“不需要”。我们的扩展仅在 Windows 系统上运行。若要在 Linux 系统上运行,对于是否需要 Cygwin 我并不清楚。其他版本的 VS 应该是可以的。我只测试了 VS2015 ,没有测试其他版本。
下载 PHP 的源代码
需要安装 VS2015,同时还需要下载 PHP 的源码,我下载的是 PHP 7.2 的源码。
下载 PHP 源码的地址是:
打开该地址后,下载如下图所示的源代码:
在这里,下载 PHP 7.2 的源码,并且要注意在源码的下方有一个 VC15 x64 的字样。
下载完的的文件为:php-7.2.20-src.zip
下载完源码之后进行解压操作,解压之后所形成的目录是:php-7.2.20-src
下载源码并非复杂之事。页面中存在多个版本的源码可供下载,选择其中一个有时会让人纠结。在此,我们下载 php7.2 的源码,因为本地使用的是 php7.2 的环境。
创建扩展
进入 php-7.2.20-src\ext 这个目录,在该目录当中有一个文件叫 ext_skel_win32.php,在命令行里执行:
使用 php ext_skel_win32.php 并加上 --extname=loaddll 这个参数
其中,扩展的名称是 loaddll。要成功执行该命令,就需要把 PHP 的可执行程序添加到环境变量里。
执行情况如下:
使用 php ext_skel_win32.php 并加上 --extname=loaddll 这个参数
Creating directory loaddll
发现:参数格式不正确。
chmod 命令在“644”之后缺少操作数。
使用 'chmod --help' 可以获取更多信息。
FIND: Parameter format not correct
chmod 命令在“755”之后缺少操作数。
Try 'chmod --help' for more information.
1. $ cd ..
在 vi 的 ext/loaddll/config.m4 文件中
3. $ ./buildconf
使用以下命令进行配置:./configure --with-loaddll 或者./configure --enable-loaddll
5. $ make
使用以下命令:./sapi/cli/php 并通过 -f 参数指定 ext/loaddll/loaddll.php 文件
$ vi 位于 ext/loaddll/loaddll.c 中
8. $ make
重复步骤 3 到 6,直至你对 ext/loaddll/config.m4 感到满意,并且
按照需要多次重复执行最后两个步骤并编写代码。
看到上述输出提示,就意味着我们创建的 PHP 扩展已经生成成功了。以上输出呈现如下:
此时,在 \ext 目录下生成了一个名为 loaddll 的目录。这个目录是生成出来的 PHP 的扩展模板,能够在该模板的基础上进行开发。
使用 VS2015 创建扩展项目
打开 VS2015 ,我使用的是 VS2015 ,其他开发环境未进行测试。
在 VS2015 里选择“文件”,接着选择“新建”,再选择“从现有代码创建项目”,以此来创建 PHP 扩展的解决方案,如下图所示:
选择了“从现有代码创建项目”这一选项之后,就会有创建项目的向导显现出来,其样子如下图所示:
直接点击 “下一步”,到如下图:
在这一步骤中,需选择刚才生成的扩展模板的目录,接着将项目名称填入其中,此项目名称为“loaddll”,之后点击“下一步”,便可到达如下图所示的界面。
此步骤选择DLL项目,点击下一步,到达如下图:
直接点击“下一步”,到达如下图:
点击“完成”,等待 VS2015 开始创建项目。
配置编译选项并编译项目
在 VS2015 完成项目生成之后,需要进行以下操作:切换项目的选项为“Release”以及“x64”,具体情况如下图所示。
切换完成后,在项目上右键选择“属性”,如下图:
将配置类型修改为 DLL 后,生成的目标文件扩展名会自动变为.dll,如下所示:
选择“配置属性”,接着选择“C/C++”,再选择“常规”。然后在“附加包含目录”处点击“编辑”,以此来添加相关的目录,如下图所示。
这里需要包含的目录包括如下图的几个目录:
这里添加了 PHP 源码的几个目录。因为编译 PHP 扩展的源码需要 PHP 的底层内核数据结构来提供支持,所以需要包含上述这些目录。
选择“配置属性”,接着选择“C/C++”,再选择“预处理器”。然后在“预处理器定义”处点击“编辑”,以此来添加相关预处理指令,如下图所示。
在预处理阶段,HAVE_LOADDLL 里的 LOADDLL 属于扩展名称,COMPILE_DL_LOADDLL 中的 LOADDLL 同样也是扩展名称,并且这个名称要与最初生成扩展模板时的名称保持一致。
编译源代码
将 php-7.2.20-src\win32\build\ 目录下的 config.w32.h.in 复制到 php-7.2.20-src\main\ 目录中,然后将其重命名为 config.w32.h。这个.h 文件在编译过程中是必需的,然而在 php-7.2.20-src\main\ 目录下原本并不存在该文件,所以需要手动进行复制操作。
在 config.w32.h 中增加如下代码
定义了 PHP 的编译器标识为 "VC15" 。
注意这个 VC15 。在进行源代码下载的时候,我们已经看到过这个标识了。
首先,找到 PHP 的安装目录。然后,从该安装目录中复制 php7ts.lib 文件。最后,将复制的文件粘贴到 loaddll 目录下。需要注意的是,是从 PHP 的安装目录进行复制,而非 PHP 源代码的目录。
在目录 php7.2.10\dev 下有 php7ts.lib ,我使用的是 wamp64 中的 php7.2.10 ,大家可使用对应的.lib 文件,此.lib 文件必须是 php7.2 的,因为我们下载的是 php7.2 的源码。
在项目的 resource Files 这个位置添加 php7ts.lib 文件,添加这个文件的操作相对比较简单,只需要通过右键进行添加就可以了。
按下 F7 生成解决方案,如图:
看到“成功 1 个”文件之后,在目录 \php-7.2.20-src\ext\loaddll\x64\Release 这个位置会生成一个 loaddll.dll 文件,而这个文件就是我们的 PHP 扩展文件。
PHP 扩展的安装与测试
将 VS2015 生成的 loaddll.dll 改名为 php_loaddll.dll ,接着把它拷贝到 PHP 环境的扩展里,我的路径是 php\php7.2.10\ext ,熟悉 PHP 的想必都会添加 PHP 扩展。如下图:
在 php.ini 文件中增加配置,如下图:
通过使用 php -m 这个命令来查看是否存在 loaddll.dll 模块,具体情况如下所示:
phpinfo 查看,如下图:
从上面能够得知,我们的 PHP 扩展已经顺利安装完毕,接下来就需要对我们的扩展能否运行进行测试。
在 PHP 的源码目录中,php-7.2.20-src\ext\loaddll\ 这个位置有一个名为 loaddll.php 的测试文件,在命令行环境下可以执行该命令。
php loaddll.php
输出内容如下:
λ php loaddll.php
测试扩展中可用的功能有:
confirm_loaddll_compiled
如下图:
看到上述输出,意味着该扩展的模板编译已成功,能够继续开发实际的扩展模块了。
总结
很多时候,学习编程的首要步骤是搭建环境。然而,在搭建环境的过程中,由于步骤较为复杂,并且相关资料也没有进行傻瓜化处理,没有给出详细的步骤,这就使得很多想要学习或入门的程序员连第一步都难以迈出。对于开发 PHP 扩展来说,情况也是如此。
要让 PHP 程序通过 PHP 扩展直接调用 DLL 中的函数,一方面需要掌握 C 语言的知识,另一方面还需要掌握 Windows 程序设计的知识。本文不讨论此内容,因为具备 C 语言知识和 Windows 程序设计知识后,在 PHP 扩展中调用 DLL 并非难事。
希望本文对大家有所帮助!