c - 如何在我自己的 php 扩展中使用 PDO 支持?

标签 c pdo php-extension

我想在我的 php 扩展中使用 PDO MySQL(使用 c 语言,而不是 php 中的简单 pdo 包装类),但我不知道这种情况,有人可以帮助我吗?谢谢。

最佳答案

我的问题已被谷歌解决,按照本指南可能会解决您的问题,它可以用于其他 zend 类。

注意:需要有关如何在c 中创建php 扩展 的基本概念。

1.需要给origin zend_call_method打补丁,因为origin zend_call_method 只支持少于 3 个参数,PDO 的构造函数使用 1-4 个参数。

PDO::__construct() ( string $dsn [, string $username [, string $password [, array $driver_options ]]] )

在您的 php 源目录中找到“zend_interfaces.c”(可能在“php-5.x.x-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.

        ...
}
/* }}} */

注意:您可能需要一些宏:

#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.你好,世界!

设置你的代码,我们需要一个属性“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());

它工作正常。干杯!

关于c - 如何在我自己的 php 扩展中使用 PDO 支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13966423/

相关文章:

c - 在 C 中释放局部定义的变量

c - 是什么导致我的二十一点程序在执行任何操作之前崩溃?

php - 如何为 Laravel 安装所有必需的 PHP 扩展?

php - OS X Homebrew 的 PHP 扩展位置

php - 运行 phpize 命令时出错

c++ - 多维数组中的数组偏移计算(列与行主要)

c - 给定任何 epoll TCP 套接字事件,如果 EPOLLRDHUP=0 且 EPOLLIN=1;后续调用 read()/recv() 是否保证返回不等于 0 的读取大小?

PHP MySQL 联接两个表查询

php - 多次使用 LastInsertId,PHP PDO

php - PDO 和 CodeIgniter - 安全吗?