1--TEST--
2MySQL PDO: PDOStatement->fetchObject()
3--EXTENSIONS--
4pdo_mysql
5--SKIPIF--
6<?php
7require_once __DIR__ . '/inc/mysql_pdo_test.inc';
8MySQLPDOTest::skip();
9$db = MySQLPDOTest::factory();
10
11try {
12    $query = "SELECT '', NULL, \"\" FROM DUAL";
13    $stmt = $db->prepare($query);
14    $ok = $stmt->execute();
15} catch (PDOException $e) {
16    die("skip: Test cannot be run with SQL mode ANSI");
17}
18if (!$ok)
19    die("skip: Test cannot be run with SQL mode ANSI");
20?>
21--FILE--
22<?php
23require_once __DIR__ . '/inc/mysql_pdo_test.inc';
24$db = MySQLPDOTest::factory();
25$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
26
27$table = 'pdo_mysql_stmt_fetchobject';
28MySQLPDOTest::createTestTable($table, $db);
29
30try {
31
32    $query = "SELECT id, '', NULL, \"\" FROM {$table} ORDER BY id ASC LIMIT 3";
33    $stmt = $db->prepare($query);
34
35    #[AllowDynamicProperties]
36    class myclass {
37
38        private $set_calls = 0;
39        protected static $static_set_calls = 0;
40
41        // NOTE: PDO does not care about protected
42        protected $grp;
43
44        // NOTE: PDO does not care about private and calls __construct() after __set()
45        private function __construct($param1, $param2) {
46            printf("myclass::__construct(%s, %s): %d / %d\n",
47                $param1, $param2,
48                self::$static_set_calls, $this->set_calls);
49        }
50
51        // NOTE: PDO will call __set() prior to calling __construct()
52        public function __set($prop, $value) {
53            $this->not_a_magic_one();
54            printf("myclass::__set(%s, -%s-) %d\n",
55                $prop, var_export($value, true), $this->set_calls, self::$static_set_calls);
56            if ("" != $prop)
57                $this->{$prop} = $value;
58        }
59
60        // NOTE: PDO can call regular methods prior to calling __construct()
61        public function not_a_magic_one() {
62            $this->set_calls++;
63            self::$static_set_calls++;
64        }
65
66    }
67    $stmt->execute();
68    $rowno = 0;
69    $rows[] = array();
70    while (is_object($rows[] = $stmt->fetchObject('myclass', array($rowno++, $rowno))))
71        ;
72
73    var_dump($rows[$rowno - 1]);
74
75    try {
76        $stmt->fetchObject('class_does_not_exist');
77    } catch (TypeError $e) {
78        echo $e->getMessage(), "\n";
79    }
80} catch (PDOException $e) {
81    // we should never get here, we use warnings, but never trust a system...
82    printf("[001] %s, [%s} %s\n",
83        $e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo()));
84}
85
86print "done!";
87?>
88--CLEAN--
89<?php
90require_once __DIR__ . '/inc/mysql_pdo_test.inc';
91$db = MySQLPDOTest::factory();
92$db->exec('DROP TABLE IF EXISTS pdo_mysql_stmt_fetchobject');
93?>
94--EXPECTF--
95myclass::__set(id, -'1'-) 1
96myclass::__set(, -''-) 2
97myclass::__set(null, -NULL-) 3
98myclass::__set(, -''-) 4
99myclass::__construct(0, 1): 4 / 4
100myclass::__set(id, -'2'-) 1
101myclass::__set(, -''-) 2
102myclass::__set(null, -NULL-) 3
103myclass::__set(, -''-) 4
104myclass::__construct(1, 2): 8 / 4
105myclass::__set(id, -'3'-) 1
106myclass::__set(, -''-) 2
107myclass::__set(null, -NULL-) 3
108myclass::__set(, -''-) 4
109myclass::__construct(2, 3): 12 / 4
110object(myclass)#%d (4) {
111  ["set_calls":"myclass":private]=>
112  int(4)
113  ["grp":protected]=>
114  NULL
115  ["id"]=>
116  string(1) "3"
117  ["null"]=>
118  NULL
119}
120PDOStatement::fetchObject(): Argument #1 ($class) must be a valid class name, class_does_not_exist given
121done!
122