php扩展开发详细笔记

 更新时间:2016年11月25日 15:27  点击:2035
下面我们一起来看一篇关于php扩展开发详细笔记吧,希望这篇文章能够给各位同学带来帮助,具体的如下文介绍。

php内核编写的扩展有两个工作方式

(1). 编译为动态共享对象/可装载模块,也就是常见的 .so扩展,这种扩展可以在php的配置文件中方便的开启或者关闭

(2). 静态编译到php中,使用静态编译方法比较容易上手本文介绍方式

第一种方式:

编写或者下载扩展包

phpize

./configure

make

make install

配置php.ini中的.so文件

第二种方式:

第一步:编译安装php

1. ./configure –prefix=/opt/php56/ –enable-debug –enable-maintainer-zts

2. make

3. make install

4. make clean

这样一个新的php安装在了/opt/php56目录下

php.ini目录:/opt/php56/lib/php.ini

第二步:扩展准备工作

1. PHP在源码中提供了一个扩展骨架构造脚本: ext_skel,脚本放在/usr/local/php-5.6.25/ext目录下。它的使用方式如下:

./ext_skel –extname=mfs –proto=mfs.def

解释一下,–extname明显就是我们要创建的扩展的名称,–proto的proto是prototype的缩写,也就是扩展对外提供的函数原型,可以在这个文件中添加要导出的函数签名,每个函数做一行,这样ext_skel脚本可以自动创建它们的骨架代码。

2. 举个例子,字符串复制函数:

string self_concat(string str, int n)

把这一行保存为mfs.def文件,放在ext文件夹下。

第三步:基本骨架

1. 执行 第二步中的ext_skel命令

此时,/usr/local/php-5.6.25/ext目录下会生成mfs文件夹,并生成一些代码文件和配置文���,php扩展配置文件是/usr/local/php-5.6.25/ext/mfs/config.m4

我们需要打开16行和18行代码的注释,如图:

这样就可以重新生成configure文件可以使用enable-mfs静态编译扩展

第四步:重新生成configure文件,并编译安装php

php安装目录 /usr/local/php-5.6.25

1. ./buildconf –force

2../configure –enable-mfs –prefix=/opt/php56 –with-config-file-path=/opt/php56/lib/php.ini

3. make

4. make install

这样编译的php就带了mfs扩展,并且可以使用def文件中定义的原型函数,但是由于并没有编写函数的具体内容

可以使用/usr/local/php-5.6.25/ext/mfs/mfs.php 进行测试,如下图:

表明脚本已经编译到php了。

第五步:编写扩展函数内容

先看一下有ext_skel脚本自动生成的self_concat函数代码,在ext/mfs/mfs.c:76行

PHP_FUNCTION(self_concat){char *str = NULL;int argc = ZEND_NUM_ARGS();int str_len;long n;if (zend_parse_parameters(argc TSRMLS_CC, “sl”, &str, &str_len, &n) == FAILURE)return;php_error(E_WARNING, “self_concat: not yet implemented”);}

这些代码是一个导出函数的基本框架了。

使用PHPFUNCTION()宏来生成一个适合于Zend引擎的函数原型。其中比较重要的是 zend_parse_parameters 函数,用来获取函数传递的参数;该函数的原型是:

zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, …);

第一个参数是参数的个数,通常使用ZEND_NUM_ARGS()的返回值,TSRMLS_DC这个照写就可以了,第三个参数比较复杂是一个表示函数期望的参数类型的字符串,后面紧跟参数值的变量列表,这里有一个PHP的松散变量和动态类型推断到C语言类型的转换。

第三个参数根据一个参数类型对照表生成:

类型指定符 对应的C类型 描述
l long 符号整数
d double 浮点数
s char *, int 二进制字符串,长度
b zend_bool 逻辑型(1或0)
r zval * 资源(文件指针,数据库连接等)
a zval * 联合数组
o zval * 任何类型的对象
O zval * 指定类型的对象。需要提供目标对象的类类型
z zval * 无任何操作的zval
考虑上面代码的实例:

if (zend_parse_parameters(argc TSRMLS_CC, “sl”, &str, &str_len, &n) == FAILURE)return;

“sl”: 第一个字符s代表二进制字符串,它在后面的参数列表中对应两个值,一个 &str, 一个&strlen;第二个字符’l’(L的小写),表示整数类型参数对应 &n。

扩展中的字符串都是二进制字符串,即并不以\0作为字符串结束,而是使用一个str_len表示字符串长度,具体看_zval结构体。
下面的工作就是修改这个函数了。

完成第一个导出函数

将自动生成的函数更新为:

PHP_FUNCTION(self_concat)

{

char *str = NULL;

int argc = ZEND_NUM_ARGS();

int str_len;

long n;

char *result; /* Points to resulting string */

char *ptr; /* Points at the next location we want to copy to */

int result_length; /* Length of resulting string */

if (zend_parse_parameters(argc TSRMLS_CC, “sl”, &str, &str_len, &n) == FAILURE) {

return;

}

result_length = (str_len * n);

result = (char *) emalloc(result_length + 1);

ptr = result;

while (n–) {

memcpy(ptr, str, str_len);

ptr += str_len;

}

*ptr = ‘\0’;

RETURN_STRINGL(result, result_length, 0);

}

按���上面的方法,重新编译php,也就是第四步重新执行, 就可以在php文件中直接使用slef_concat()函数拼接字符串了。

成功输出拼接的字符串,OK!

MAMP Pro是一款适用于Mac操作系统的软件了,我们今天介绍过几篇在mamp上的安装配置了,但小编需要重新编辑安装mamp上的环境了,具体的如下


MAMP自带的PHP版本在编译的时候是没有加上--enable-debug选项的,于是我打算自己重新编译一下PHP方便自己在进行PHP扩展研究的时候可以用gdb来查看core dump文件。

首先使用MAMP中的php版本查看phpinfo()
得到了MAMP在编译时候的参数

--more--
并且在后面加上了--enable-debug选项

sudo './configure' '--with-mysql=mysqlnd' '--with-gd' '--with-jpeg-dir=/Applications/MAMP/Library' '--with-png-dir=/Applications/MAMP/Library' '--with-zlib' '--with-zlib-dir=/Applications/MAMP/Library' '--with-freetype-dir=/Applications/MAMP/Library' '--prefix=/Applications/MAMP/bin/php/php5.5.26' '--exec-prefix=/Applications/MAMP/bin/php/php5.5.26' '--sysconfdir=/Applications/MAMP/bin/php/php5.5.26/conf' '--with-config-file-path=/Applications/MAMP/bin/php/php5.5.26/conf' '--enable-ftp' '--enable-gd-native-ttf' '--with-bz2=/usr' '--with-ldap' '--with-mysqli=mysqlnd' '--with-t1lib=/Applications/MAMP/Library' '--enable-mbstring=all' '--with-curl=/Applications/MAMP/Library' '--enable-sockets' '--enable-bcmath' '--with-imap=shared,/Applications/MAMP/Library/lib/imap-2007f' '--enable-soap' '--with-kerberos' '--enable-calendar' '--with-pgsql=shared,/Applications/MAMP/Library/pg' '--enable-exif' '--with-libxml-dir=/usr/include' '--with-gettext=shared,/Applications/MAMP/Library' '--with-xsl=/Applications/MAMP/Library' '--with-pdo-mysql=mysqlnd' '--with-pdo-pgsql=shared,/Applications/MAMP/Library/pg' '--with-mcrypt=shared,/Applications/MAMP/Library' '--with-openssl' '--enable-zip' '--with-iconv=/Applications/MAMP/Library' '--enable-opcache' '--enable-cgi' '--enable-intl' '--with-icu-dir=/Applications/MAMP/Library' '--with-tidy=shared' '--enable-wddx' '--with-libexpat-dir=/Applications/MAMP/Library' --enable-debug
将重新下载的php对应版本新建了一个目录,解压在了以下的文件夹中

/Applications/MAMP/bin/php/php5.5.26/include/php

第一次使用上面的参数第一次编译报错:

configure: error: Cannot find OpenSSL's <evp.h>

brew link openssl --forece
再编译,又获得如下错误

configure: error: jpeglib.h not found
使用brew安装jpeglib

sudo brew install jpeglib
接下来又报错

configure: error: png.h not found
sudo brew install t1lib
报错

configure: error: Cannot locate header file libintl.h
用以下来解决

sudo brew install gettext
1) 安装 gettext:

brew install gettext
2) 编辑configure文件
将:

for i in $PHP_GETTEXT /usr/local /usr ; do
更改为:

for i in $PHP_GETTEXT /usr/local /usr /usr/local/opt/gettext; do
3)重新运行 ./configure

报错

configure: error: utf8_mime2text() has new signature, but U8T_CANONICAL is missing. This should not happen. Check config.log for additional information
安装

sudo brew install imap-uw
报错

configure: error: mcrypt.h not found. Please reinstall libmcrypt.
安装

sudo brew install libmcrypt
报错

configure: error: Cannot find libpq-fe.h. Please specify correct PostgreSQL installation path
安装

sudo brew install PostgreSQL
之后

sudo make && sudo make install
会报错找不到libxml/parse.h

改成

/usr/include/libxml2
安装iconv

sudo brew install homebrew/dupes/libiconv
在修复libiconv报错的时候,网上一篇文章写移动/use/lib/目录底下的libiconv.*移动到其他目录,替换刚刚安装的libiconv来交叉编译,结果刚移动系统就崩溃了。这个库应该是系统很多程序调用的库, 花了一晚上重装了个系统,打算明天用docker来装个PHP环境。

brew 又叫Homebrew,是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件, 只需要一个命令, 非常方便brew类似ubuntu系统下的apt-get的功能,下面我们来看MAC利用brew安装PHP7环境的方法

最近几年一直在LNMP环境下进行开发,其中的PHP还是5.5版本,有点老旧,去年12月PHP7已经正式发布,新增了一些语法特性,最大的亮点是性能的提升,所以一直想升级到PHP7,由于时间关系一直拖到现在。到写本文为止PHP最新版本为:7.0.9的stable,所以稳定性上基本不用担心。

之前写的 MAC下安装LNMP环境 是用brew安装的,这次升级PHP7继续使用brew, 安装/升级软件很方便。

升级brew

brew update
配置

brew tap homebrew/dupes
brew tap homebrew/versions 
brew tap homebrew/homebrew-php
安装PHP7

brew install php70
遇到的问题

安装提示:

➜  ~ brew install php70
==> Installing php70 from homebrew/php
Error: Cannot install homebrew/php/php70 because conflicting formulae are installed.

  php55: because different php versions install the same binaries.

Please `brew unlink php55` before continuing.

Unlinking removes a formula's symlinks from /usr/local. You can
link the formula again after the install finishes. You can --force this
install, but the build may fail or cause obscure side-effects in the
resulting software.
根据提示执行: brew unlink php55
继续安装: brew install php70

配置文件

安装好后生成的配置文件都在 /usr/local/etc/php/7.0 目录里,分别如下:

php.ini /usr/local/etc/php/7.0/php.ini
php-fpm.conf /usr/local/etc/php/7.0/php-fpm.conf
php, phpize, php-config ls /usr/local/opt/php70/bin
php-fpm /usr/local/opt/php70/sbin/php-fpm

加入开机启动

mkdir -p ~/Library/LaunchAgents
ln -sfv /usr/local/opt/php70/homebrew.mxcl.php70.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php70.plist
命令行配置

vim ~/.zshrc

export PATH="$(brew --prefix php55)/bin:$PATH"
替换为
export PATH="$(brew --prefix homebrew/php/php70)/bin:$PATH"

alias php-fpm.start="launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php55.plist"
alias php-fpm.stop="launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.php5.plist"
alias php-fpm.restart='php-fpm.stop && php-fpm.start'
修改为

alias php-fpm.start="launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php70.plist"
alias php-fpm.stop="launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.php70.plist"
alias php-fpm.restart='php-fpm.stop && php-fpm.start'
重新加载配置文件

source ~/.zshrc
验证版本

PHP版本

➜  ~ /usr/local/opt/php70/bin/php -v
PHP 7.0.9 (cli) (built: Jul 21 2016 14:50:47) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
php-fpm版本

➜  ~ /usr/local/opt/php70/sbin/php-fpm -v
PHP 7.0.9 (fpm-fcgi) (built: Jul 21 2016 14:50:51)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
启动PHP-FPM

执行: php-fpm.start

检查是否启动成功:

➜  ~ ps aux|grep php-fpm
qloog           60380   0.2  0.0  2432792    604 s001  R+    6:00PM   0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn php-fpm
qloog           60378   0.0  0.0  2473348    620   ??  S     6:00PM   0:00.00 /usr/local/opt/php70/sbin/php-fpm --fpm-config /usr/local/etc/php/7.0/php-fpm.conf
qloog           60377   0.0  0.0  2473348    648   ??  S     6:00PM   0:00.00 /usr/local/opt/php70/sbin/php-fpm --fpm-config /usr/local/etc/php/7.0/php-fpm.conf
qloog           60372   0.0  0.0  2475396   7844   ??  S     6:00PM   0:00.03 /usr/local/opt/php70/sbin/php-fpm --fpm-config /usr/local/etc/php/7.0/php-fpm.conf
安装扩展

yaf

brew install php70-yaf

配置文件
/usr/local/etc/php/7.0/conf.d/ext-yaf.ini

memcached

brew install php70-memcached

配置文件
/usr/local/etc/php/7.0/conf.d/ext-memcached.ini

redis

brew install php70-redis

配置文件
/usr/local/etc/php/7.0/conf.d/ext-redis.ini

xdebug

brew install php70-xdebug

配置文件
/usr/local/etc/php/7.0/conf.d/ext-xdebug.ini

swoole

brew install php70-swoole

配置文件
/usr/local/etc/php/7.0/conf.d/ext-swoole.ini

更多扩展执行 brew install 扩展名 进行安装

在php5.3.9添加了max_input_vars函数它限制了提交数据的长度了,如果我们长度限制100而提交的数据为200那么就会只保存前面100个字符哦,下面来看看。

公司运营的论坛被网络攻击,无奈没有很好的解决方法,就只有一个个的封IP地址,最终封了1600多个ip段,2个月后网络攻击逐步减少,担心会屏蔽正常用户,所以开始解封一批国内的字段的ip地址,论坛程序是discuz,由于discuz在禁止ip字段页面没有做分页功能,其导致1600多个字段同时读取在页面上。

问题来了,删除ip字段时程序不响应,在记录数1000条以上,不管是提交一条删除记录,还是全部删除记录,都是没效果的。

1000条记录下,删除功能失效

1000条记录下,删除功能失效

最终在discuz官方论坛管理员帮助下解决!

discuz官方 

discuz官方

解决方法:在php.ini里面加入

max_input_vars,指的是表达提交的数量,默认值为 1000。官方添加这个变量的目的是为了更好的保护服务器不受攻击。避免堵塞。

max_input_vars = 2000

实例代码:

max_execution_time = 30     ; Maximum execution time of each script, in seconds
max_input_time = 60     ; Maximum amount of time each script may spend parsing request data
max_input_vars = 2000

重启php-fpm后,功能正常了。

[!--infotagslink--]

相关文章

  • PHP添加MongoDB扩展实例教程

    由于要使用mikoomi mongodb plugin插件,所以需要php对mongodb的扩展支持,默认通过源安装的php并没有mongodb的扩展支持,具体可以通过php -m|grep mongo 验证 。这里就结...2016-11-25
  • Linux下PHP安装curl扩展支持https例子

    安装curl扩展支持https是非常的重要现在许多的网站都使用了https了,下面我们来看一篇关于PHP安装curl扩展支持https例子吧。 问题: 线上运行的lamp服务器,默认yu...2016-11-25
  • vscode搭建STM32开发环境的详细过程

    这篇文章主要介绍了vscode搭建STM32开发环境的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-05-02
  • PHP扩展开发教程(总结)

    PHP是一种解释型的语言,对于用户而言,我们精心的控制内存意味着easier prototyping和更少的崩溃!当我们深入到内核之后,所有的安全防线都已经被越过,最终还是要依赖于真正有责任心的软件工程师来保证系统的稳定运行。1、线...2015-11-08
  • 浅谈Vue开发人员的7个最好的VSCode扩展

    这篇文章主要介绍了浅谈Vue开发人员的7个最好的VSCode扩展,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-01-20
  • 安卓开发之Intent传递Object与List教程

    下面我们一起来看一篇关于 安卓开发之Intent传递Object与List的例子,希望这个例子能够为各位同学带来帮助。 Intent 不仅可以传单个的值,也可以传对象与数据集合...2016-09-20
  • php微信公众账号开发之五个坑(二)

    这篇文章主要为大家详细介绍了php微信公众账号开发之五个坑,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-02
  • 如何设计一个安全的API接口详解

    在日常开发中,总会接触到各种接口,前后端数据传输接口,第三方业务平台接口,下面这篇文章主要给大家介绍了关于如何设计一个安全的API接口的相关资料,需要的朋友可以参考下...2021-08-12
  • 微信开发生成带参数的二维码的讲解

    在微信公众号平台开发者那里,在“账号管理”那里,有一项功能是“生成带参数的二维码”,通过这儿生成的二维码,只要通过微信扫一扫之后,会把事件自动推送到微...2016-05-19
  • PHP安装threads多线程扩展基础教程

    一、下载pthreads扩展下载地址:http://windows.php.net/downloads/pecl/releases/pthreads二、判断PHP是ts还是nts版通过phpinfo(); 查看其中的 Thread Safety 项,这个项目就是查看是否是线程安全,如果是:enabled,一般来说...2015-11-24
  • 分享我对JS插件开发的一些感想和心得

    这篇文章主要给大家分享我对JS插件开发的一些感想和心得的相关资料,需要的朋友可以参考下...2016-02-09
  • Chrome插件开发系列一:弹窗终结者开发实战

    从这一节开始,我们将从零开始打造我们的chrome插件工具库,第一节我们将讲一下插件开发的基础知识并构建一个简单但却很实用的插件,在构建之前,我们先简单的了解一下插件以及插件开发的基础知识...2020-10-03
  • Redis集群水平扩展、集群中添加以及删除节点的操作

    这篇文章主要介绍了Redis集群水平扩展、集群中添加以及删除节点的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-25
  • Cocos2d-x UI开发之CCControlColourPicker控件类使用实例

    这篇文章主要介绍了Cocos2d-x UI开发之CCControlColourPicker控件类使用实例,本文代码中包含大量注释来讲解CCControlColourPicker控件类的使用,需要的朋友可以参考下...2020-04-25
  • 详解微信开发中snsapi_base和snsapi_userinfo及静默授权的实现

    这篇文章主要介绍了详解微信开发中snsapi_base和snsapi_userinfo及静默授权的实现的相关资料,需要的朋友可以参考下...2017-03-13
  • Java开发SpringBoot集成接口文档实现示例

    这篇文章主要为大家介绍了Java开发SpringBoot如何集成接口文档的实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步...2021-10-28
  • Drupal8模块开发之区块和表单教程

    前页我们讲了 Drupal8模块开发之路由、控制器和菜单链接教程 ,现在我们将学习进一步开发Drupal8模块,区块和表单。 上一教程:Drupal8模块开发之路由、控制器和菜单链...2016-11-25
  • 基于jQuery实现收缩展开功能

    这篇文章主要介绍了基于jQuery实现收缩展开功能的相关资料,需要的朋友可以参考下...2016-03-22
  • 24个ES6方法解决JS实际开发问题(小结)

    这篇文章主要介绍了24个ES6方法解决JS实际开发问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-01
  • Linux环境 php mcrypt扩展完全安装笔记

    mcrypt 是 php 里面重要的加密支持扩展库,Linux环境下默认是没开启的,在某些功能时,我们需要安装mcrypt扩展才能正常访问,本文就来讲讲如何完全安装这个模块。 如果你...2016-11-25