在一些必要的情境我們不得不自己開發出自己的本地PHP函數滿足一些特定的需求,而新的函數必須存在於PHP模組中。下面將介紹最簡單的PHP模組開發:構建自己的say_hello($arg)函數來輸出hello world : $arg。
本文檔介紹的PHP模組開發僅僅是動動手做做hello world的程度,關於為什麼這麼做暫時不會介紹太多,更加詳細的介紹後續解剖。
下面通過簡單的幾個步驟可以完成模組hello world層級的模組:
產生模組基礎結構
修改模組代碼,添加say_hello 函數
修改編譯設定檔
產生模組共用庫
配置模組,使模組生效
測試模組
1、產生模組基礎
進入php原始碼目錄下的ext目錄。
執行./ext_skel ––extname=sayhello (我這裡的“–”編碼有問題請不要直接拷貝)
輸出:
[root@myhost ext]# ./ext_skel ––extname=sayhello
Creating directory sayhello
Creating basic files: config.m4 config.w32 .cvsignore sayhello.c php_sayhello.h CREDITS EXPERIMENTAL tests/001.phpt sayhello.php [done].
To use your new extension, you will have to execute the following steps:
1. $ cd ..
2. $ vi ext/sayhello/config.m4
3. $ ./buildconf
4. $ ./configure ––[with|enable]-sayhello
5. $ make
6. $ ./php -f ext/sayhello/sayhello.php
7. $ vi ext/sayhello/sayhello.c
8. $ make
Repeat steps 3-6 until you are satisfied with ext/sayhello/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
code and repeat the last two steps as often as necessary.
看到顯示輸出表示模組基礎結構已經產生,我們來看下產生的模組包含哪些檔案:
-rw-r–r– 1 root root 2103 Apr 9 05:05 config.m4 //編譯設定檔
-rw-r–r– 1 root root 310 Apr 9 05:05 config.w32 //w32編譯設定檔
-rw-r–r– 1 root root 8 Apr 9 05:05 CREDITS //作者資訊
-rw-r–r– 1 root root 0 Apr 9 05:05 EXPERIMENTAL //測試版資訊標識
-rw-r–r– 1 root root 2755 Apr 9 05:05 php_sayhello.h //模組定義標頭檔
-rw-r–r– 1 root root 5294 Apr 9 05:05 sayhello.c //模組實現檔案
-rw-r–r– 1 root root 508 Apr 9 05:05 sayhello.php //用來測試模組載入的php檔案
drwxr-xr-x 2 root root 4096 Apr 9 05:05 tests //測試檔案目錄
這個時候模組的骨架已經出來了,我們下一步就可以將目標的say_hello()函數加入。
2、實現say_hello()函數
開啟模組的php_sayhello.h 檔案,增加為php say_hello()準備的c函數定義:
PHP_FUNCTION(say_hello); //php 原始碼為模組開放定義了許多宏,習慣了使用還是蠻方便的
增加完以後我們再對PHP_FUNCTION(say_hello)在say_hello.c中增加具體的實現:
PHP_FUNCTION(say_hello){char *arg = NULL;int arg_len;if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) ==FAILURE) { //擷取php代碼的輸入參數,方式與scanf差不多return;}zend_printf("hello world : %s",arg);RETURN_STRINGL(arg, arg_len, 1);}
現在實現代碼也寫了,我們還需要將這個函數註冊到php本地函數中,需要修改sayhello.c中的sayhello_functions:
zend_function_entry sayhello_functions[] = {PHP_FE(confirm_sayhello_compiled, NULL) /* For testing, remove later. */PHP_FE(say_hello, NULL) //好,現在say_hello函數也註冊了{NULL, NULL, NULL} /* Must be the last line in sayhello_functions[] */};
3、修改編譯設定檔
開啟config.m4,將以下內容前的注釋符“dnl”去掉:
dnl PHP_ARG_ENABLE(sayhello, whether to enable sayhello support,
dnl Make sure that the comment is aligned:
dnl [ --enable-sayhello Enable sayhello support])
dnl PHP_SUBST(SAYHELLO_SHARED_LIBADD)
4、編譯模組、產生共用庫
我這裡採用的是動態庫的模組產生方式,比靜態編譯進php速度快多了,方便調試(使用上並非用php的dl()函數載入動態庫,後續可以看到)。
進入(cd) sayhello模組檔案夾,執行php安裝路徑bin下的phpize:
[root@myhost sayhello]# /opt/php_server/php/bin/phpize
Configuring for:
PHP Api Version: 20041225
Zend Module Api No: 20060613
Zend Extension Api No: 220060519
此時為模組編譯的configure檔案已經產生。繼續產生Makefile檔案:
[root@myhost sayhello]# ./configure –with-php-config=/opt/php_server/php/bin/php-config
……沒問題的話是沒有錯誤的
現在可以編譯了:
make
代碼沒有問題的話不會有錯的。
編譯完,進行模組安裝:
[root@myhost sayhello]# make install
Installing shared extensions: /opt/php_server/php/lib/php/extensions/no-debug-non-zts-20060613/
顯示模組已經安裝至/php安裝路徑/extensions/no-debug-non-zts-20060613/ 路徑下了。
5、配置模組,使其被載入
開啟你的php.ini檔案開始修改吧:
擴充路徑設定:
修改extension_dir = “/php安裝路徑/lib/php/extensions/no-debug-non-zts-20060613″ //看看上述的模組安裝路徑就知道了
增加模組設定:
[sayhello]
extension=sayhello.so
ok 大功告成,重新啟動你的php模組把。
6、測試模組
寫以下php測試代碼執行:
<?php$a = say_hello("frank");echo "<br>";echo $a;?>;
開啟這個網頁後顯示:
hello world : frank
frank
成功運行,模組測試通過。