什麼是 PHP 擴展 通俗說,PHP 擴展是增強 PHP 語言功能的插件。PHP 提供了編程語言的語法,比如分支、迴圈、函數、類等,這些是 PHP 本身所提供的。在某些情況下需要在 PHP 語言的基礎上進行擴展,那麼就需要通過 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”