linux系統
php源碼包下載地址:https://www.php.net/downloads.php
PHP 7.3開始,開發拓展,取消了 ./ext_skel 命令工具,
要使用 php ext_skel.php 命令的形式創建拓展
一、下載源碼包解壓後,編譯安裝php
#下載源碼包 php-7.3.12.tar.gz
[root@localhost package]# wget https://www.php.net/distributions/php-7.3.12.tar.gz
[root@localhost package]# ll
total 143964
-rw-r--r--. 1 root root 19457403 Nov 22 14:48 php-7.3.12.tar.gz
#解壓
[root@localhost package]# tar -zxvf php-7.3.12.tar.gz
[root@localhost package]# ll
total 143968
drwxr-xr-x. 14 1000 1000 4096 Jul 3 19:30 php-7.3.12
-rw-r--r--. 1 root root 19457403 Nov 22 14:48 php-7.3.12.tar.gz
#安裝php運行環境
[root@localhost package]# yum install libxml libxml2 libxml2-devel -y
[root@localhost package]# yum install openssl openssl-devel -y
[root@localhost package]# yum install curl libcurl libcurl-devel -y
[root@localhost package]# yum install libjpeg-devel -y
[root@localhost package]# yum install libpng-devel -y
[root@localhost package]# yum install freetype-devel -y
[root@localhost package]# yum install libicu-devel -y
[root@localhost package]# yum install glibc-headers gcc-c++ -y
[root@localhost package]# yum -y install libxslt libxslt-devel
[root@localhost package]# yum install libzip-devel -y
[root@localhost package]# yum install autoconf -y
# 安裝 php 調試跟蹤工具
[root@localhost etc]# yum install strace -y
#安裝 libzip
[root@localhost package]# yum remove libzip -y
[root@localhost package]# wget https://nih.at/libzip/libzip-1.2.0.tar.gz
[root@localhost package]# tar -zxvf libzip-1.2.0.tar.gz
[root@localhost package]# cd libzip-1.2.0
[root@localhost libzip-1.2.0]# ./configure
[root@localhost libzip-1.2.0]# make && make install
[root@localhost libzip-1.2.0]find /usr/local -iname 'zipconf.h'
[root@localhost libzip-1.2.0]ln -s /usr/local/lib/libzip/include/zipconf.h /usr/local/include
#添加搜索路徑到配置文件
echo '/usr/local/lib64
/usr/local/lib
/usr/lib
/usr/lib64'>>/etc/ld.so.conf
#更新配置
ldconfig -v
#切換目錄 ,編譯安裝 php-7.3.12
[root@localhost package]# cd php-7.3.12
[root@localhost php-7.3.12]# ./configure --prefix=/usr/local/php7.3.12 --with-config-file-path=/usr/local/php7.3.12/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype-dir=/usr/local/freetype --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --enable-intl --enable-pcntl --enable-ftp --with-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --with-gettext --disable-fileinfo --enable-opcache --with-xsl
[root@localhost php-7.3.12]# make clean
[root@localhost php-7.3.12]# make && make install
#查看php 版本,安裝完畢
[root@localhost php-7.3.12]# /usr/local/php7.3.12/bin/php -v
PHP 7.3.12 (cli) (built: Nov 22 2019 16:44:43) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.12, Copyright (c) 1998-2018 Zend Technologies
具體配置php可參考另一篇文章,這裏不多說:https://blog.csdn.net/daily886/article/details/79504404
二、開始拓展配置
# 回到 php-7.3.12 編譯包的解壓目錄下面 ,切換到 ext 目錄
[root@localhost php-7.3.12]# cd ext
# 查看拓展使用方法
[root@localhost ext]# /usr/local/php7.3.12/bin/php ext_skel.php --help
php ext_skel.php --ext <name> [--experimental] [--author <name>]
[--dir <path>] [--std] [--onlyunix]
[--onlywindows] [--help]
--ext <name> The name of the extension defined as <name>
--experimental Passed if this extension is experimental, this creates
the EXPERIMENTAL file in the root of the extension
--author <name> Your name, this is used if --std is passed and
for the CREDITS file
--dir <path> Path to the directory for where extension should be
created. Defaults to the directory of where this script
lives
--std If passed, the standard header and vim rules footer used
in extensions that is included in the core, will be used
--onlyunix Only generate configure scripts for Unix
--onlywindows Only generate configure scripts for Windows
--help This help
#創建hello world 拓展
[root@localhost ext]# /usr/local/php7.3.12/bin/php ext_skel.php --ext hello_world
Copying config scripts... done
Copying sources... done
Copying tests... done
Success. The extension is now ready to be compiled into PHP. To do so, use the
following steps:
cd /path/to/php-src
./buildconf
./configure --enable-hello_world
make
Don't forget to run tests once the compilation is done:
make test TESTS=ext/hello_world/tests
Thank you for using PHP!
#切換到 hello_world 拓展目錄
[root@localhost ext]# cd hello_world
[root@localhost hello_world]# ll
total 16
-rw-r--r--. 1 root root 3004 Nov 22 17:03 config.m4
-rw-r--r--. 1 root root 246 Nov 22 17:03 config.w32
-rw-r--r--. 1 root root 2408 Nov 22 17:03 hello_world.c
-rw-r--r--. 1 root root 364 Nov 22 17:03 php_hello_world.h
drwxr-xr-x. 2 root root 54 Nov 22 17:03 tests
編輯 config.m4 ,內容如下:
dnl config.m4 for extension hello_world
dnl Comments in this file start with the string 'dnl'.
dnl Remove where necessary.
dnl If your extension references something external, use with:
dnl PHP_ARG_WITH(hello_world, for hello_world support,
dnl Make sure that the comment is aligned:
dnl [ --with-hello_world Include hello_world support])
dnl Otherwise use enable:
PHP_ARG_ENABLE(hello_world, whether to enable hello_world support,
dnl Make sure that the comment is aligned:
[ --enable-hello_world Enable hello_world support], no)
if test "$PHP_HELLO_WORLD" != "no"; then
dnl Write more examples of tests here...
dnl # get library FOO build options from pkg-config output
dnl AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
dnl AC_MSG_CHECKING(for libfoo)
dnl if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists foo; then
dnl if $PKG_CONFIG foo --atleast-version 1.2.3; then
dnl LIBFOO_CFLAGS=\`$PKG_CONFIG foo --cflags\`
dnl LIBFOO_LIBDIR=\`$PKG_CONFIG foo --libs\`
dnl LIBFOO_VERSON=\`$PKG_CONFIG foo --modversion\`
dnl AC_MSG_RESULT(from pkgconfig: version $LIBFOO_VERSON)
dnl else
dnl AC_MSG_ERROR(system libfoo is too old: version 1.2.3 required)
dnl fi
dnl else
dnl AC_MSG_ERROR(pkg-config not found)
dnl fi
dnl PHP_EVAL_LIBLINE($LIBFOO_LIBDIR, HELLO_WORLD_SHARED_LIBADD)
dnl PHP_EVAL_INCLINE($LIBFOO_CFLAGS)
dnl # --with-hello_world -> check with-path
dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
dnl SEARCH_FOR="/include/hello_world.h" # you most likely want to change this
dnl if test -r $PHP_HELLO_WORLD/$SEARCH_FOR; then # path given as parameter
dnl HELLO_WORLD_DIR=$PHP_HELLO_WORLD
dnl else # search default path list
dnl AC_MSG_CHECKING([for hello_world files in default path])
dnl for i in $SEARCH_PATH ; do
dnl if test -r $i/$SEARCH_FOR; then
dnl HELLO_WORLD_DIR=$i
dnl AC_MSG_RESULT(found in $i)
dnl fi
dnl done
dnl fi
dnl
dnl if test -z "$HELLO_WORLD_DIR"; then
dnl AC_MSG_RESULT([not found])
dnl AC_MSG_ERROR([Please reinstall the hello_world distribution])
dnl fi
dnl # --with-hello_world -> add include path
dnl PHP_ADD_INCLUDE($HELLO_WORLD_DIR/include)
dnl # --with-hello_world -> check for lib and symbol presence
dnl LIBNAME=HELLO_WORLD # you may want to change this
dnl LIBSYMBOL=HELLO_WORLD # you most likely want to change this
dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
dnl [
dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $HELLO_WORLD_DIR/$PHP_LIBDIR, HELLO_WORLD_SHARED_LIBADD)
dnl AC_DEFINE(HAVE_HELLO_WORLDLIB,1,[ ])
dnl ],[
dnl AC_MSG_ERROR([wrong hello_world lib version or lib not found])
dnl ],[
dnl -L$HELLO_WORLD_DIR/$PHP_LIBDIR -lm
dnl ])
dnl
dnl PHP_SUBST(HELLO_WORLD_SHARED_LIBADD)
dnl # In case of no dependencies
AC_DEFINE(HAVE_HELLO_WORLD, 1, [ Have hello_world support ])
PHP_NEW_EXTENSION(hello_world, hello_world.c, $ext_shared)
fi
編輯 hello_world.c ,內容如下:
/* hello_world extension for PHP */
//for php 7.3.12
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_hello_world.h"
/* For compatibility with older PHP versions */
#ifndef ZEND_PARSE_PARAMETERS_NONE
#define ZEND_PARSE_PARAMETERS_NONE() \
ZEND_PARSE_PARAMETERS_START(0, 0) \
ZEND_PARSE_PARAMETERS_END()
#endif
/*自定義函數開始*/
/* {{{ void hello_world_func()
*/
PHP_FUNCTION(hello_world_func)
{
char *name;
size_t name_len;
zend_string *strg;
#ifndef FAST_ZPP //如果沒有定義 FAST_ZPP
//,在PHP7之前一直使用zend_parse_parameters函數獲取參數
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
//ZEND_NUM_ARGS() 告訴Zend引擎要取的參數的信息, TSRMLS_CC 用來確保線程安全,返回值檢測是SUCCESS還是FAILURE。
// | 代表後面的參數可不傳
// s 小寫的s 代表字符串string
// &name 把獲取的字符串傳址給 name
// &name_len 把獲取的字符串長度傳址給 name_len
php_printf("param error!"); // php_printf 是php拓展自帶的打印函數
RETURN_NULL(); //返回空值
}
#else
//在PHP7中新提供的方式。是爲了提高參數解析的性能
ZEND_PARSE_PARAMETERS_START(0, 1) //第一個參數表示必傳的參數格式,第二個參數表示最多傳入的參數個數。
Z_PARAM_OPTIONAL // Z_PARAM_OPTIONAL 對應 | 代表後面的參數可不傳
Z_PARAM_STRING(name, name_len) //Z_PARAM_STRING 對應小寫的s 代表字符串string ,後面的參數代表zend_parse_parameters 的 &name 和 &name_len
ZEND_PARSE_PARAMETERS_END();
#endif
strg = strpprintf(0,"hello world %s!", name); //strpprintf是PHP爲我們提供的字符串拼接的方法。第一個參數是最大字符數,第二個是返回的字符串%s是需要替換的字符串,後面的是參數
RETURN_STR(strg);
}
/* }}} */
/*自定義函數結束*/
/* {{{ void hello_world_test1()
*/
PHP_FUNCTION(hello_world_test1)
{
ZEND_PARSE_PARAMETERS_NONE();
php_printf("The extension %s is loaded and working!\r\n", "hello_world");
}
/* }}} */
/* {{{ string hello_world_test2( [ string $var ] )
*/
PHP_FUNCTION(hello_world_test2)
{
char *var = "World";
size_t var_len = sizeof("World") - 1;
zend_string *retval;
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_STRING(var, var_len)
ZEND_PARSE_PARAMETERS_END();
retval = strpprintf(0, "Hello %s", var);
RETURN_STR(retval);
}
/* }}}*/
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(hello_world)
{
#if defined(ZTS) && defined(COMPILE_DL_HELLO_WORLD)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(hello_world)
{
php_info_print_table_start();
php_info_print_table_header(2, "hello_world support", "enabled");
php_info_print_table_row(2, "author", "daily886"); /* Replace with your name */
php_info_print_table_end();
}
/* }}} */
/* {{{ arginfo
*/
ZEND_BEGIN_ARG_INFO(arginfo_hello_world_test1, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_hello_world_test2, 0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(hello_world_func, 0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ hello_world_functions[]
*/
static const zend_function_entry hello_world_functions[] = {
PHP_FE(hello_world_test1, arginfo_hello_world_test1)
PHP_FE(hello_world_test2, arginfo_hello_world_test2)
PHP_FE(hello_world_func, hello_world_func)
PHP_FE_END
};
/* }}} */
/* {{{ hello_world_module_entry
*/
zend_module_entry hello_world_module_entry = {
STANDARD_MODULE_HEADER,
"hello_world", /* Extension name */
hello_world_functions, /* zend_function_entry */
NULL, /* PHP_MINIT - Module initialization */
NULL, /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(hello_world), /* PHP_RINIT - Request initialization */
NULL, /* PHP_RSHUTDOWN - Request shutdown */
PHP_MINFO(hello_world), /* PHP_MINFO - Module info */
PHP_HELLO_WORLD_VERSION, /* Version */
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_HELLO_WORLD
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
# endif
ZEND_GET_MODULE(hello_world)
#endif
創建拓展
[root@localhost hello_world]# find / -name phpize
/usr/local/php7.3.12/bin/phpize
/package/php-7.3.12/scripts/phpize
[root@localhost hello_world]# /usr/local/php7.3.12/bin/phpize
Configuring for:
PHP Api Version: 20180731
Zend Module Api No: 20180731
Zend Extension Api No: 320180731
[root@localhost hello_world]# find / -name php-config
/usr/local/php7.3.12/bin/php-config
/package/php-7.3.12/scripts/php-config
[root@localhost hello_world]# ./configure --with-php-config=/usr/local/php7.3.12/bin/php-config
[root@localhost hello_world]# make && make install
Installing shared extensions: /usr/local/php7.3.12/lib/php/extensions/no-debug-non-zts-20180731/
# php拓展 hello_world.so 生成成功
[root@localhost hello_world]# find / -name hello_world.so
/usr/local/php7.3.12/lib/php/extensions/no-debug-non-zts-20180731/hello_world.so
/package/php-7.3.12/ext/hello_world/modules/hello_world.so
/package/php-7.3.12/ext/hello_world/.libs/hello_world.so
加載 hello_world.so 拓展並使用
# 添加用戶
[root@localhost php-7.3.12]# /usr/sbin/groupadd -f nginx
[root@localhost php-7.3.12]# /usr/sbin/useradd -g nginx nginx
# 切換到 php 安裝目錄
[root@localhost php-7.3.12]# cd /usr/local/php7.3.12
# 切換到 etc 目錄
[root@localhost php7.3.12]# cd etc
# 查找 php.ini初始配置
[root@localhost etc]# find / -name php.ini*
/package/php-7.3.12/php.ini-development
/package/php-7.3.12/php.ini-production
# 複製到當前目錄
[root@localhost etc]# cp /package/php-7.3.12/php.ini-development php.ini
[root@localhost etc]# ll
total 80
-rw-r--r--. 1 root root 5407 Nov 22 16:56 php-fpm.conf.default
drwxr-xr-x. 2 root root 30 Nov 22 16:56 php-fpm.d
-rw-r--r--. 1 root root 71709 Nov 23 09:08 php.ini
########## 設置 php 全局
[root@localhost etc]# ln -s /usr/local/php7.3.12/etc/php.ini /etc/php.ini
[root@localhost etc]# ln -s /usr/local/php7.3.12/bin/php /usr/local/bin/php
# 編輯 php.ini 加入一行
[root@localhost etc]# vi php.ini
extension=hello_world
########## 設置 php-fpm 全局
[root@localhost etc]# ln -s /usr/local/php7.3.12/sbin/php-fpm /usr/local/bin/php-fpm
[root@localhost etc]# php-fpm -v
PHP 7.3.12 (fpm-fcgi) (built: Nov 22 2019 16:46:26)
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.12, Copyright (c) 1998-2018 Zend Technologies
[root@localhost etc]# chmod -R 777 /usr/local/php7.3.12
############# 複製 php-fpm 配置文件
[root@localhost etc]# cp php-fpm.conf.default php-fpm.conf
[root@localhost etc]# cp php-fpm.d/www.conf.default php-fpm.d/www.conf
######### 配置 php-fpm.conf ################
[root@localhost etc]# vi php-fpm.conf
# 開啓 pid 和 log
pid = /usr/local/php7.3.12/var/run/php-fpm.pid
error_log = /usr/local/php7.3.12/var/log/php-fpm.log
# :wq 保存退出 ################
######### 配置 php-fpm.d/www.conf ################
[root@localhost etc]# vi php-fpm.d/www.conf
# 大概 23 行,設置用戶和用戶組爲 nginx
user = nginx
group = nginx
# 大概 36 行,監聽端口 9000
listen = 127.0.0.1:9000
# :wq 保存退出 ################
######### 查找 php-fpm 的系統啓動文件
[root@localhost etc]# find / -name init.d.php-fpm
/package/php-7.3.12/sapi/fpm/init.d.php-fpm
####### 複製啓動文件 到 etc/init.d目錄下
[root@localhost etc]# cp /package/php-7.3.12/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
############ 配置權限 並添加到自啓動列表
[root@localhost etc]# chmod 755 /etc/init.d/php-fpm
[root@localhost etc]# chkconfig --add php-fpm
[root@localhost etc]# chkconfig php-fpm on
########## 配置完畢
[root@localhost etc]# service php-fpm start
Starting php-fpm done
[root@localhost etc]# php-fpm -m
[PHP Modules]
bcmath
cgi-fcgi
Core
ctype
curl
date
dom
filter
ftp
gd
gettext
hash
hello_world
# 加載 hello_world 拓展成功
使用拓展的函數
編輯一個 test.php 並保存,內容如下
<?php
$test = hello_world_test2();
echo $test;
echo "\r\n";
$str = hello_world_func("daily886 done");
echo $str;
echo "\r\n";
$str2 = hello_world_func();
echo $str2;
~
運行 test.php ,拓展運行正常
[root@localhost etc]# php test.php
Hello World
hello world daily886 done!
hello world `]!
------------------------------------------------------------
創建拓展參考:
https://www.php.cn/php-weizijiaocheng-392678.html
拓展使用參考: