10/10/2018, 09:54
Viết Extension cho PHP
Nhiều khi bạn muốn xử lý ứng dụng phức tạp (như bản đồ, ứng dụng tra từ điển, ứng dụng tính toán, ...), nếu bạn viết tất cả bằng PHP thì thực sự rất khó và không hiệu quả. Khi đó bạn nên viết bằng C/C++/VC đóng gói các hàm nhân lại và public một số hàm để PHP sử dụng. Việc này chính là bạn viết Extension cho PHP.
Tệp extension cho PHP chính là tệp DLL. Ở đây tôi xin hướng dẫn các bạn một cách chi tiết khi viết tệp này sử dụng bộ Visual Studio 2005 (Với Visual Studio khác bạn cũng làm tương tự thôi).
+ Tạo Project
Để tạo Extension cho PHP, bạn tạo Project DLL cụ thể như sau:
- B1: Bạn New Project, kiểu Project bạn chọn Win32, template thì bạn chọn Win32 Project. Đánh tên project, ở đây tôi lấy tên project là MyPHPExt. Sau đó nhấn OK.
- B2: Tiếp đó bạn chọn Next, bạn chọn kiểu ứng dụng (Application Type) là DLL, rồi nhấn Finish.
+ Cấu hình cho Project
Để tạo DLL cho PHP sử dụng, bạn phải cấu hình lại cho Project này. Bạn mở Properties của Project, rồi bạn cấu hình như sau:
- Đầu tiên bạn download PHP 5 Source tại địa chỉ www.php.net hoặc tại một trong hai địa chỉ:
Download PHP5 Source tại Rapidshare
Download PHP5 Source tại Megaupload
Sau đó bạn giải nén vào ổ C:
- Trong Configuration Properties -> General:
Character Set --> Use Multi-Byte Character Set
- Trong Configuration Properties > C/C++ -> General
Debug Information Format --> Program Database (/Zi)
Detect 64-bit Portability Issues --> No
Additional Include Directories --> C:PHP5Src;C:PHP5Srcmain;C:PHP5Srcend;C:PHP5 SrcTSRM;C:PHP5Src egex
- Trong Configuration Properties > C/C++ -> Preprocessor:
Bạn thêm ZEND_DEBUG=0; ZTS=1; ZEND_WIN32; PHP_WIN32
* Chú ý: Bạn không nên thiết lập ZEND_DEBUG = 1 ngay cả khi bạn dịch Debug.
- Trong Configuration Properties -> Linker -> General:
Additional Include Directories --> C:PHP5Srclib (nơi chứa tệp php5ts.lib)
- Trong Configuration Properties -> Linker -> Input:
Additional Dependencies --> php5ts.lib
+ Viết mã
Ở đây, tôi xin viết một ví dụ đơn giản viết hàm Fib(n) để tính dãy ****nacci: F(n) = F(n-2) + F(n-1), với n>3 và F(1) = F(2) = 1
và hàm SumFib(n1, n2) để tính tổng các ****nacci(n1)+****nacci(n1+1)+...+****nacci(n2).
Tệp MyPhpExt.php sử dụng doạn code PHP để gọi hai hàm này:
Mã: Chọn tất cả
<?php
$n = 10;
$fib = Fib($n);
echo "Fib($n) = $fib<br> ";
$n1 = 5;
$n2 = 10;
$sumfib = SumFib($n1, $n2);
echo "Fib($n1) + ... + Fib($n2) = $sumfib";
?>
Đầu tiên, bạn sửa tệp stdafx.h để include các tệp tiêu đề của PHP Extension:
Mã: Chọn tất cả
#pragma once
/* PHP Zend Extension headers */
/* include zend win32 config first */
#include "zend_config.w32.h"
/* include standard header */
#include "php.h"
Sau đó bạn thêm đoạn code sau vào tệp MyPHPExt.cpp:
Mã: Chọn tất cả
#include "stdafx.h"
/* declaration of functions to be exported */
ZEND_FUNCTION(Fib);
ZEND_FUNCTION(SumFib);
/* compiled function list so Zend knows what's in this module */
zend_function_entry MyPHPExtModule_functions[] = {
ZEND_FE(Fib, NULL)
ZEND_FE(SumFib, NULL)
{NULL, NULL, NULL}
};
/* compiled module information */
zend_module_entry MyPHPExtModule_module_entry = {
STANDARD_MODULE_HEADER,
"MyPHPExt Module",
MyPHPExtModule_functions,
NULL, NULL, NULL, NULL, NULL,
NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
};
/* implement standard "stub" routine to introduce ourselves to Zend */
ZEND_GET_MODULE(MyPHPExtModule)
long ****nacci(long n)
{
long nRet = 0;
if (n>0)
{
if (n<=2)
nRet = 1;
else
nRet = ****nacci(n-1) + ****nacci(n-2);
}
return nRet;
}
ZEND_FUNCTION(Fib){
long n = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &n) == FAILURE) {
RETURN_STRING("Bad parameters!", true);
}
long nRet = ****nacci(n);
RETURN_LONG(nRet);
}
ZEND_FUNCTION(SumFib){
long n1 = 0;
long n2 = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &n1, &n2) == FAILURE) {
RETURN_STRING("Bad parameters!", true);
}
long nRet = 0;
if (n1>n2)
{
long temp = n1;
n1 = n2;
n2 = temp;
}
for (long n=n1; n<=n2; n++)
nRet += ****nacci(n);
RETURN_LONG(nRet);
}
Sau đó bạn build Project, bạn được tệp MyPHPExt.dll.
+ Triển khai Extension
Để triển khai Extension thì bạn làm như sau:
- Bạn vào thư mục, nơi cài đặt PHP (trong máy tôi là C:WebWampinphpphp5.2.6), sau đó copy tệp MyPHPExt.dll vào thư mục trong ext (Bạn copy thêm tệp MyPHPExt.pdb nếu bạn muốn debug).
- Bạn mở để sửa tệp php.ini. Bạn thêm dòng
Mã: Chọn tất cả
extension=MyPHPExt.dll
vào tệp php.ini và lưu lại. Sau đó bạn restart là server.
- Bạn muốn kiểm tra xem tệp Extension của bạn đã được load hay chưa, bạn tạo một tệp PHP với nội dung nhưa sau:
Mã: Chọn tất cả
<?php
phpinfo();
?>
và chạy. Nếu bạn thấy trong bảng, Additional Modules, trường Module Name có MyPHPExt Module thì okie.
- Sau đó, bạn chạy tệp MyPhpExt.php ở trên, bạn sẽ thấy kết quả trả về trên trình duyệt.
=> Vậy là bạn đã viết xong PHP Extension, để tiện hơn bạn hãy download project tại MyPhpExt Project
Có tham khảo tài liệu tại: myshop4vn.com
Tệp extension cho PHP chính là tệp DLL. Ở đây tôi xin hướng dẫn các bạn một cách chi tiết khi viết tệp này sử dụng bộ Visual Studio 2005 (Với Visual Studio khác bạn cũng làm tương tự thôi).
+ Tạo Project
Để tạo Extension cho PHP, bạn tạo Project DLL cụ thể như sau:
- B1: Bạn New Project, kiểu Project bạn chọn Win32, template thì bạn chọn Win32 Project. Đánh tên project, ở đây tôi lấy tên project là MyPHPExt. Sau đó nhấn OK.
- B2: Tiếp đó bạn chọn Next, bạn chọn kiểu ứng dụng (Application Type) là DLL, rồi nhấn Finish.
+ Cấu hình cho Project
Để tạo DLL cho PHP sử dụng, bạn phải cấu hình lại cho Project này. Bạn mở Properties của Project, rồi bạn cấu hình như sau:
- Đầu tiên bạn download PHP 5 Source tại địa chỉ www.php.net hoặc tại một trong hai địa chỉ:
Download PHP5 Source tại Rapidshare
Download PHP5 Source tại Megaupload
Sau đó bạn giải nén vào ổ C:
- Trong Configuration Properties -> General:
Character Set --> Use Multi-Byte Character Set
- Trong Configuration Properties > C/C++ -> General
Debug Information Format --> Program Database (/Zi)
Detect 64-bit Portability Issues --> No
Additional Include Directories --> C:PHP5Src;C:PHP5Srcmain;C:PHP5Srcend;C:PHP5 SrcTSRM;C:PHP5Src egex
- Trong Configuration Properties > C/C++ -> Preprocessor:
Bạn thêm ZEND_DEBUG=0; ZTS=1; ZEND_WIN32; PHP_WIN32
* Chú ý: Bạn không nên thiết lập ZEND_DEBUG = 1 ngay cả khi bạn dịch Debug.
- Trong Configuration Properties -> Linker -> General:
Additional Include Directories --> C:PHP5Srclib (nơi chứa tệp php5ts.lib)
- Trong Configuration Properties -> Linker -> Input:
Additional Dependencies --> php5ts.lib
+ Viết mã
Ở đây, tôi xin viết một ví dụ đơn giản viết hàm Fib(n) để tính dãy ****nacci: F(n) = F(n-2) + F(n-1), với n>3 và F(1) = F(2) = 1
và hàm SumFib(n1, n2) để tính tổng các ****nacci(n1)+****nacci(n1+1)+...+****nacci(n2).
Tệp MyPhpExt.php sử dụng doạn code PHP để gọi hai hàm này:
Mã: Chọn tất cả
<?php
$n = 10;
$fib = Fib($n);
echo "Fib($n) = $fib<br> ";
$n1 = 5;
$n2 = 10;
$sumfib = SumFib($n1, $n2);
echo "Fib($n1) + ... + Fib($n2) = $sumfib";
?>
Đầu tiên, bạn sửa tệp stdafx.h để include các tệp tiêu đề của PHP Extension:
Mã: Chọn tất cả
#pragma once
/* PHP Zend Extension headers */
/* include zend win32 config first */
#include "zend_config.w32.h"
/* include standard header */
#include "php.h"
Sau đó bạn thêm đoạn code sau vào tệp MyPHPExt.cpp:
Mã: Chọn tất cả
#include "stdafx.h"
/* declaration of functions to be exported */
ZEND_FUNCTION(Fib);
ZEND_FUNCTION(SumFib);
/* compiled function list so Zend knows what's in this module */
zend_function_entry MyPHPExtModule_functions[] = {
ZEND_FE(Fib, NULL)
ZEND_FE(SumFib, NULL)
{NULL, NULL, NULL}
};
/* compiled module information */
zend_module_entry MyPHPExtModule_module_entry = {
STANDARD_MODULE_HEADER,
"MyPHPExt Module",
MyPHPExtModule_functions,
NULL, NULL, NULL, NULL, NULL,
NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
};
/* implement standard "stub" routine to introduce ourselves to Zend */
ZEND_GET_MODULE(MyPHPExtModule)
long ****nacci(long n)
{
long nRet = 0;
if (n>0)
{
if (n<=2)
nRet = 1;
else
nRet = ****nacci(n-1) + ****nacci(n-2);
}
return nRet;
}
ZEND_FUNCTION(Fib){
long n = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &n) == FAILURE) {
RETURN_STRING("Bad parameters!", true);
}
long nRet = ****nacci(n);
RETURN_LONG(nRet);
}
ZEND_FUNCTION(SumFib){
long n1 = 0;
long n2 = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &n1, &n2) == FAILURE) {
RETURN_STRING("Bad parameters!", true);
}
long nRet = 0;
if (n1>n2)
{
long temp = n1;
n1 = n2;
n2 = temp;
}
for (long n=n1; n<=n2; n++)
nRet += ****nacci(n);
RETURN_LONG(nRet);
}
Sau đó bạn build Project, bạn được tệp MyPHPExt.dll.
+ Triển khai Extension
Để triển khai Extension thì bạn làm như sau:
- Bạn vào thư mục, nơi cài đặt PHP (trong máy tôi là C:WebWampinphpphp5.2.6), sau đó copy tệp MyPHPExt.dll vào thư mục trong ext (Bạn copy thêm tệp MyPHPExt.pdb nếu bạn muốn debug).
- Bạn mở để sửa tệp php.ini. Bạn thêm dòng
Mã: Chọn tất cả
extension=MyPHPExt.dll
vào tệp php.ini và lưu lại. Sau đó bạn restart là server.
- Bạn muốn kiểm tra xem tệp Extension của bạn đã được load hay chưa, bạn tạo một tệp PHP với nội dung nhưa sau:
Mã: Chọn tất cả
<?php
phpinfo();
?>
và chạy. Nếu bạn thấy trong bảng, Additional Modules, trường Module Name có MyPHPExt Module thì okie.
- Sau đó, bạn chạy tệp MyPhpExt.php ở trên, bạn sẽ thấy kết quả trả về trên trình duyệt.
=> Vậy là bạn đã viết xong PHP Extension, để tiện hơn bạn hãy download project tại MyPhpExt Project
Có tham khảo tài liệu tại: myshop4vn.com
Bài liên quan
Với ứng dụng có mức độ tính toán quá phức tạp, ví dụ như thuật toán cây khung ngắn nhất trên đồ thị có hướng (Edmond) mà mình đã triển khai cho ứng dụng GIS trên nền PHP, thì việc lập trình với PHP thuần là bất khả thi. Lúc đấy phải bỏ ra vài tuần viết extension cho nó.
Với những ứng dụng lớn, người ta không có cái suy nghĩ "Ít người đủ tiền để thuê host riêng, đa số là shared host nên làm cái này cũng bằng không.".