PHP扩展开发详解-2016.04.05
学习背景
PHP extension提供了与C交互的接口,从个人的理解上,很好的提供了一种将固化、重复、性能要求高的行为下沉的机制,处于php内核与php应用空间之间,为程序员提供了一种利用php高性能(相对)完成任务的可能性,因此在工作中使用该模式完成一些相对底层、高效的操作。同时,因为PHP是在C语言之上的封装,极大提升了易用性,导致一些底层功能无法完成(例如swoole),因此也需要这样的口子,使PHPER可以实现更丰富的功能。
参考资料
正文
对于扩展程序,在进行源码编译时有两种选择:1是将其编译到PHP应用程序中;2是以.so动态链接库的方式,单独编译。由于PHP通常对应的是前端开发,需求经常变化,因此保证PHP应用体积够小,功能简单。在实际生产环境中,后者的方法处于多数。
需要扩展PHP的功能,可以通过扩展或加入第三方包。目前有几种方法:
- PECL:PHP Extension Community LibraryPHP扩展库,是使用c语言实现的PHP扩展,对语言本身外放方法。
- PEAR:the PHP Extension and Application RepositoryPHP扩展与应用库,代码由PHP实现,逐渐被composer取代。
- composer:PHP包管理工具,一般放在github、bitbucket上,使用composer管理的包,可以很轻松的利用SPL的autoload机制,将扩展的包打入自己的框架/项目。是目前比较火的PHP包管理方式。
言归正传,如何将一个现有的extension源码添加入指定的PHP环境,分为以下几步(以鸟哥的taint为例):
#我一般都会将扩展源码整理到PHP源码下的ext目录下,当前使用的PHP版本为7.1
$git clone https://github.com/laruence/taint.git ./taint
$cd ./taint
#这一步在同时存在多个php版本的环境中尤其要注意,可以使用php -v 来确定当前版本,最好使用绝对路径处理
$<your own php bin path>/phpize
$./configure
$./make #这里通常不选择make install,生成的.so/.la文件都在当前文件夹下的module文件中
#去php.ini所在目录并修改,可以使用php -i | grep 'ini'查看这个文件在哪儿
$vim <your own php lib path>php.ini
#如果要在fast-cgi或者php_mod模式下生效,还需要重启http服务器
$service php-fpm restart
$apachectl restart
#检查一下模块是否加载上了
$<your own php bin path>/php -m | grep taint
要编写自己的扩展,首先需要在项目下创建一个项目(摆姿势),php提供了非常便利的工具,找到PHP的源文件夹下,进入扩展源码所在目录ext/内,使用扩展初始化创建工具ext_skel,例如我们创建名为test的扩展,会在当前文件夹下生成一个名为test的扩展文件包的新文件夹,里面包含有一个php extension所需的所有骨架文件:
$./ext_skel --extname=test
#程序在终端打印以下信息
Creating directory test
Creating basic files: config.m4 config.w32 .gitignore test.c php_test.h CREDITS EXPERIMENTAL tests/001.phpt test.php [done].
To use your new extension, you will have to execute the following steps:
1. $ cd ..
2. $ vi ext/test/config.m4
3. $ ./buildconf
4. $ ./configure --[with|enable]-test
5. $ make
6. $ ./sapi/cli/php -f ext/test/test.php
7. $ vi ext/test/test.c
8. $ make
生成的扩展test目录结构如下:
$ tree
.
├── CREDITS
├── EXPERIMENTAL
├── config.m4 #unix类系统配置
├── config.w32 #windows系统配置
├── php_test.h #
├── test.c #扩展
├── test.php
└── tests
└── 001.phpt