1. 程式人生 > >PHP 擴充套件開發初探

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 下以 .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 原始碼的地址是:https://windows.php.net/download/

 

開啟該地址後,下載如下圖所示的原始碼:

 

在這裡,下載 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 的檔案,在命令列中執行:

1 php ext_skel_win32.php --extname=loaddll

其中,loaddll 是要建立的擴充套件的名稱。想要成功執行該命令,需要將 PHP 的可執行程式新增到環境變數中。

 

執行情況如下:

λ php ext_skel_win32.php --extname=loaddll
Creating directory loaddll
FIND: Parameter format not correct
chmod: missing operand after ‘644’
Try 'chmod --help' for more information.
FIND: Parameter format not correct
chmod: missing operand after ‘755’
Try 'chmod --help' for more information.
Creating basic files: config.m4 config.w32 .gitignore loaddll.c php_loaddll.h CREDITS EXPERIMENTAL tests/001.phpt loaddll.php [done].


To use your new extension, you will have to execute the following steps:


1.  $ cd ..
2.  $ vi ext/loaddll/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-loaddll
5.  $ make
6.  $ ./sapi/cli/php -f ext/loaddll/loaddll.php
7.  $ vi ext/loaddll/loaddll.c
8.  $ make


Repeat steps 3-6 until you are satisfied with ext/loaddll/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.

看到如上的輸出提示,則說明我們建立的 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 中增加如下程式碼

1 #define PHP_COMPILER_ID "VC15" 

注意這裡的 VC15 ,在下載原始碼的時候,我們已經見到過這個標識了。

 

接著,從 PHP 的安裝目錄中複製 php7ts.lib 檔案到 loaddll 目錄下,注意,是從PHP 的安裝目錄中,而不是 PHP 原始碼的目錄中。

 

php7ts.lib 在目錄 php7.2.10\dev 目錄下,我使用的是 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 的測試檔案,在命令列下進行執行該命令:

1 php loaddll.php

輸出內容如下:

1 λ php loaddll.php
2 Functions available in the test extension:
3 confirm_loaddll_compiled
4 
5 Congratulations! You have successfully modified ext/loaddll/config.m4. Module loaddll is now compiled into PHP.

如下圖:

看到如上輸出,說明該擴充套件的模板編譯成功,可以繼續開發實際的擴充套件模組了。

 

總結

很多時候,學習程式設計的第一步就是搭建環境,而往往搭建環境的過程中由於步驟過於複雜,而資料又沒有傻瓜化的詳細步驟,導致很多想要學習或入門的程式設計師連第一步都無法踏出。對於開發 PHP 擴充套件而言也是一樣的。

如何通過 PHP 擴充套件來讓 PHP 程式可以直接呼叫 DLL 中的函式,除了需要掌握 C 語言的知識以外,還需要掌握 Windows 程式設計的知識,本文就不再討論了,因為有 C 語言的知識和 Windows 程式設計的知識,在 PHP 擴充套件中呼叫 DLL 並非難事。

希望本文對大家有所幫助!

 


 

歡迎大家關注微信公眾號:“碼農UP2U”

&n