]> granicus.if.org Git - php/commitdiff
- In fetch mode PDO_FETCH_CLASS handle constructor args
authorMarcus Boerger <helly@php.net>
Sun, 13 Feb 2005 17:04:04 +0000 (17:04 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 13 Feb 2005 17:04:04 +0000 (17:04 +0000)
- Add PDOStatement::fetchObject

ext/pdo/pdo_stmt.c

index 07fbedd67351d692e9968e6bfcd7424a2dd9a9c3..8946df12193ef9e6f890b29d15b22589b0c06b1a 100755 (executable)
@@ -573,7 +573,52 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value,
                        case PDO_FETCH_CLASS:
                                object_init_ex(return_value, stmt->fetch.cls.ce);
 
-                               /* TODO: call ctor */
+                               if (stmt->fetch.cls.ce->constructor) {
+                                       zend_fcall_info fci;
+                                       zend_fcall_info_cache fcc;
+                                       zval *retval_ptr; 
+
+                                       fci.size = sizeof(fci);
+                                       fci.function_table = &stmt->fetch.cls.ce->function_table;
+                                       fci.function_name = NULL;
+                                       fci.symbol_table = NULL;
+                                       fci.object_pp = &return_value;
+                                       fci.retval_ptr_ptr = &retval_ptr;
+                                       if (stmt->fetch.cls.ctor_args) {
+                                               HashTable *ht = Z_ARRVAL_P(stmt->fetch.cls.ctor_args);
+                                               Bucket *p;
+               
+                                               fci.param_count = 0;
+                                               fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
+                                               p = ht->pListHead;
+                                               while (p != NULL) {
+                                                       fci.params[fci.param_count++] = (zval**)p->pData;
+                                                       p = p->pListNext;
+                                               }
+                                       } else {
+                                               fci.param_count = 0;
+                                               fci.params = NULL;
+                                       }
+                                       fci.no_separation = 1;
+                       
+                                       fcc.initialized = 1;
+                                       fcc.function_handler = stmt->fetch.cls.ce->constructor;
+                                       fcc.calling_scope = EG(scope);
+                                       fcc.object_pp = &return_value;
+                       
+                                       if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
+                                               zend_throw_exception_ex(pdo_exception_ce, 0 TSRMLS_CC, "Could not execute %s::%s()", stmt->fetch.cls.ce->name, stmt->fetch.cls.ce->constructor->common.function_name);
+                                       } else {
+                                               if (retval_ptr) {
+                                                       zval_ptr_dtor(&retval_ptr);
+                                               }
+                                       }
+                                       if (fci.params) {
+                                               efree(fci.params);
+                                       }
+                               } else if (stmt->fetch.cls.ctor_args) {
+                                       zend_throw_exception_ex(pdo_exception_ce, 0 TSRMLS_CC, "Class %s does not have a constructor, use NULL for parameter ctor_params or omit it", stmt->fetch.cls.ce->name);
+                               }
                                break;
                        
                        case PDO_FETCH_INTO:
@@ -648,6 +693,68 @@ static PHP_METHOD(PDOStatement, fetch)
 }
 /* }}} */
 
+/* {{{ proto mixed PDOStatement::fetchObject(string class_name [, NULL|array ctor_args]])
+   Fetches the next row and returns it as an object. */
+static PHP_METHOD(PDOStatement, fetchObject)
+{
+       long how = PDO_FETCH_CLASS;
+       long ori = PDO_FETCH_ORI_NEXT;
+       long off = 0;
+       char *class_name;
+       int class_name_len;
+       zend_class_entry *old_ce;
+       zval *old_ctor_args, *ctor_args;
+       int error = 0;
+
+       pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       
+       old_ce = stmt->fetch.cls.ce;
+       old_ctor_args = stmt->fetch.cls.ctor_args;
+
+       if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sz", 
+               &class_name, &class_name_len, &ctor_args)) {
+               RETURN_FALSE;
+       }
+
+       switch(ZEND_NUM_ARGS()) {
+       case 0:
+               stmt->fetch.cls.ce = zend_standard_class_def;
+               break;
+       case 2:
+               if (Z_TYPE_P(ctor_args) != IS_NULL && Z_TYPE_P(ctor_args) != IS_ARRAY) {
+                       zend_throw_exception(pdo_exception_ce, "Parameter ctor_args must either be NULL or an array ", 0 TSRMLS_CC);
+                       error = 1;
+                       break;
+               }
+               if (Z_TYPE_P(ctor_args) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(ctor_args))) {
+                       stmt->fetch.cls.ctor_args = ctor_args;
+               } else {
+                       stmt->fetch.cls.ctor_args = NULL;
+               }
+               /* no break */
+       case 1:
+               stmt->fetch.cls.ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
+
+               if (!stmt->fetch.cls.ce) {
+                       zend_throw_exception_ex(pdo_exception_ce, 0 TSRMLS_CC, "Could not find class '%s'", class_name);
+                       error = 1;
+                       break;
+               }
+       }
+
+       PDO_STMT_CLEAR_ERR();
+       if (!error && !do_fetch(stmt, TRUE, return_value, how, ori, off TSRMLS_CC)) {
+               error = 1;
+               PDO_HANDLE_STMT_ERR();
+       }
+       stmt->fetch.cls.ce = old_ce;
+       stmt->fetch.cls.ctor_args = old_ctor_args;
+       if (error) {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
 /* {{{ proto string PDOStatement::fetchSingle()
    Returns a data of the 1st column in the result set. */
 static PHP_METHOD(PDOStatement, fetchSingle)
@@ -977,9 +1084,12 @@ fail_out:
                        }
                        
                        if (argc == 3) {
-                               convert_to_array_ex(args[skip+2]);
-                               stmt->fetch.cls.ctor_args = *args[skip+2];
-                               zval_copy_ctor(stmt->fetch.cls.ctor_args);
+                               if (Z_TYPE_PP(args[skip+2]) != IS_NULL && Z_TYPE_PP(args[skip+2]) != IS_ARRAY) {
+                                       zend_throw_exception(pdo_exception_ce, "Parameter ctor_args must either be NULL or an array ", 0 TSRMLS_CC);
+                               } else if (Z_TYPE_PP(args[skip+2]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_PP(args[skip+2]))) {
+                                       stmt->fetch.cls.ctor_args = *args[skip+2];
+                                       zval_copy_ctor(stmt->fetch.cls.ctor_args);
+                               }
                        }
                        break;
 
@@ -1070,6 +1180,7 @@ function_entry pdo_dbstmt_functions[] = {
        PHP_ME(PDOStatement, rowCount,          NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, fetchSingle,       NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, fetchAll,          NULL,                                   ZEND_ACC_PUBLIC)
+       PHP_ME(PDOStatement, fetchObject,       NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, errorCode,         NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, errorInfo,         NULL,                                   ZEND_ACC_PUBLIC)
        PHP_ME(PDOStatement, setAttribute,      NULL,                                   ZEND_ACC_PUBLIC)