2012-12-20 40 views
1

我想在我的php擴展中使用PDO MySQL(在c語言中使用c語言,不是簡單的pdo包裝類),但我不知道這種情況,任何人都可以幫助我?謝謝。如何在我自己的php擴展中使用PDO支持?

+1

我已經php5.4安裝 – DotDash

+0

你到底打算在擴展與PDO辦?它主要用作PHP代碼的服務,而不是用於其他擴展。 – duskwuff

+0

檢查http://devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/ –

回答

4

我的問題是由谷歌解決的,按照本指南可以解決你的問題,它可以在其他Zend類使用。

注意:有關如何在c中創建php擴展的基本概念是必需的。

1.You需要修補的起源zend_call_method,因爲產地zend_call_method 只能支持不到3參數,和PDO的構造函數中使用1-4 ARGS。

PDO :: __結構()(字符串$ DSN [,字符串$用戶名[,字符串$密碼[,數組$ driver_options]]])

查找你的PHP 「zend_interfaces.c」源目錄(也許在 「PHP-5.xx的-SRC \ Zend的\ zend_interfaces.c」),目標 「zend_call_method」 的一部分,將其複製粘貼到你的代碼,這樣做:

/* {{{ zend_call_method 
Only returns the returned zval if retval_ptr != NULL */ 
ZEND_API zval* zend_call_method_n_params(
    zval **object_pp, zend_class_entry *obj_ce, 
    zend_function **fn_proxy, const char *function_name, 
    int function_name_len, zval **retval_ptr_ptr, 
    int param_count, zval *** params TSRMLS_DC) 
// ↑↑↑new function definition 
// only change "zval* arg1, zval* arg2" to "zval *** params" 
// make a new function name "zend_call_method_n_params" 
{ 
     ... 

    //zval **params[2];   ← delete it! 
    //params[0] = &arg1;   ← delete it! 
    //params[1] = &arg2;   ← delete it! done. 

     ... 
} 
/* }}} */ 

注意:您可以n eed一些宏:

#define call_method(obj, obj_ce, fn_proxy, function_name, retval, param_count, params) \ 
    zend_call_method_n_params(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, param_count, params TSRMLS_CC) 

#define call_function(function_name, retval, param_count, params) \ 
    zend_call_method(NULL, NULL, NULL, function_name, retval, param_count, params) 

#define call_construct(obj, obj_ce, param_count, params) \ 
    call_method(obj, obj_ce, &obj_ce->constructor, obj_ce->constructor->common.function_name, NULL, param_count, params) 

2.hello world!

設置你的代碼,我們需要一個屬性 「PDO」

PHP_MINIT_FUNCTION(yourextension) 
{ 
    ... 
    zend_declare_property_null(you_class_entry, ZEND_STRL("pdo"), 
           ZEND_ACC_PUBLIC TSRMLS_CC); 
    ... 
} 
PHP_METHOD(foo, bar) 
{ 
    char * dsn = "mysql:dbname=yourdb;host=127.0.0.1;port=3306"; 
    char * usr = "username"; 
    char * pwd = "password"; 
    zval * zdsn = NULL; 
    zval * zusr = NULL; 
    zval * zpwd = NULL; 

    zval ** params[3]; 
    zend_class_entry * pdo_class_entry; 

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 
     RETURN_FALSE; 
    } 

    // get class entry for PDO 
    pdo_class_entry = zend_fetch_class(ZEND_STRL("PDO"), 
            ZEND_FETCH_CLASS_AUTO TSRMLS_CC); 

    // initial PDO instance 
    MAKE_STD_ZVAL(pdo_inst); 
    object_init_ex(pdo_inst, pdo_class_entry); 

    // arg1: dns string 
    ALLOC_INIT_ZVAL(zdns); 
    ZVAL_STRINGL(zdsn, dsn, sizeof(dsn)-1, 1); 

    // arg2: username 
    ALLOC_INIT_ZVAL(zusr); 
    ZVAL_STRINGL(zusr, usr, sizeof(usr)-1, 1); 

    // arg3: password 
    ALLOC_INIT_ZVAL(zpwd); 
    ZVAL_STRINGL(zpwd, pwd, sizeof(pwd)-1, 1); 

    // put them in params array 
    params[0] = &zdsn; 
    params[1] = &zusr; 
    params[2] = &zpwd; 

    // call PDO::__construct(zdns, zusr, zpwd) 
    zend_call_method_n_params(&pdo_inst, 
     pdo_class_entry, 
     &pdo_class_entry->constructor, 
     ZEND_STRL(pdo_class_entry->constructor->common.function_name), 
     NULL, 3, // 3 params 
     params TSRMLS_CC); 
    // or simply use macro instead() 
    //call_construct(&pdo_inst, pdo_class_entry,3,params); 
    if (pdo_inst && Z_TYPE_P(pdo_inst) == IS_OBJECT) { 
     zend_update_property(your_class_entry, getThis(), 
          ZEND_STRL("pdo") , pdo_inst TSRMLS_CC); 
     zend_printf("Success.\n"); 
    } else { 
     zend_printf("Failure.\n"); 
    } 
} 

在PHP可以這樣調用:

$foo = new foo(); 
$foo->bar(); // connect by PDO and update $foo->pdo 
// you can use pdo property now 
var_dump($foo->pdo->query("select * from table")->fetchAll()); 

它工作正常。乾杯!