1--TEST-- 2PDO::ATTR_STATEMENT_CLASS 3--EXTENSIONS-- 4pdo_mysql 5--SKIPIF-- 6<?php 7require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 8MySQLPDOTest::skip(); 9?> 10--FILE-- 11<?php 12 require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 13 $db = MySQLPDOTest::factory(); 14 $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); 15 16 $table = 'pdo_mysql_attr_statement_class'; 17 18 MySQLPDOTest::createTestTable($table, $db); 19 20 $default = $db->getAttribute(PDO::ATTR_STATEMENT_CLASS); 21 var_dump($default); 22 23 try { 24 $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'foo'); 25 } catch (\TypeError $e) { 26 echo $e->getMessage(), \PHP_EOL; 27 } 28 try { 29 $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname']); 30 } catch (\TypeError $e) { 31 echo $e->getMessage(), \PHP_EOL; 32 } 33 // unknown class 34 try { 35 $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['classname', []]); 36 } catch (\TypeError $e) { 37 echo $e->getMessage(), \PHP_EOL; 38 } 39 40 // class not derived from PDOStatement 41 class myclass { 42 function __construct() { 43 printf("myclass\n"); 44 } 45 } 46 47 try { 48 $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['myclass', []]); 49 } catch (\TypeError $e) { 50 echo $e->getMessage(), \PHP_EOL; 51 } 52 53 // public constructor not allowed 54 class mystatement extends PDOStatement { 55 public function __construct() { 56 printf("mystatement\n"); 57 } 58 } 59 60 try { 61 if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['mystatement', []]))) 62 printf("[006] Expecting boolean/false got %s\n", var_export($tmp, true)); 63 } catch (\Error $e) { 64 echo get_class($e), ': ', $e->getMessage(), \PHP_EOL; 65 } 66 67 68 // ... but a public destructor is allowed 69 class mystatement2 extends PDOStatement { 70 public function __destruct() { 71 printf("mystatement\n"); 72 } 73 } 74 75 if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement2', array())))) 76 printf("[007] Expecting boolean/true got %s\n", var_export($tmp, true)); 77 78 // private constructor 79 class mystatement3 extends PDOStatement { 80 private function __construct($msg) { 81 printf("mystatement3\n"); 82 var_dump($msg); 83 } 84 } 85 if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement3', array('param1'))))) 86 printf("[008] Expecting boolean/true got %s\n", var_export($tmp, true)); 87 88 // private constructor 89 class mystatement4 extends PDOStatement { 90 private function __construct($msg) { 91 printf("%s\n", get_class($this)); 92 var_dump($msg); 93 } 94 } 95 if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement4', array('param1'))))) 96 printf("[008] Expecting boolean/true got %s\n", var_export($tmp, true)); 97 98 var_dump($db->getAttribute(PDO::ATTR_STATEMENT_CLASS)); 99 $stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2"); 100 101 class mystatement5 extends mystatement4 { 102 public function fetchAll($fetch_style = 1, ...$fetch_args): array { 103 return []; 104 } 105 } 106 107 if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement5', array('mystatement5'))))) 108 printf("[009] Expecting boolean/true got %s\n", var_export($tmp, true)); 109 $stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2"); 110 var_dump($stmt->fetchAll()); 111 112 if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement')))) 113 printf("[010] Expecting boolean/true got %s\n", var_export($tmp, true)); 114 115 $stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 1"); 116 var_dump($stmt->fetchAll()); 117 118 // Yes, this is a fatal error and I want it to fail. 119 abstract class mystatement6 extends mystatement5 { 120 } 121 try { 122 $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['mystatement6', ['mystatement6']]); 123 $stmt = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 1"); 124 } catch (\Error $e) { 125 echo get_class($e), ': ', $e->getMessage(), \PHP_EOL; 126 } 127?> 128--CLEAN-- 129<?php 130require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 131$db = MySQLPDOTest::factory(); 132$db->query('DROP TABLE IF EXISTS pdo_mysql_attr_statement_class'); 133?> 134--EXPECT-- 135array(1) { 136 [0]=> 137 string(12) "PDOStatement" 138} 139PDO::ATTR_STATEMENT_CLASS value must be of type array, string given 140PDO::ATTR_STATEMENT_CLASS class must be a valid class 141PDO::ATTR_STATEMENT_CLASS class must be a valid class 142PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement 143TypeError: User-supplied statement class cannot have a public constructor 144array(2) { 145 [0]=> 146 string(12) "mystatement4" 147 [1]=> 148 array(1) { 149 [0]=> 150 string(6) "param1" 151 } 152} 153mystatement4 154string(6) "param1" 155mystatement5 156string(12) "mystatement5" 157array(0) { 158} 159array(1) { 160 [0]=> 161 array(4) { 162 ["id"]=> 163 string(1) "1" 164 [0]=> 165 string(1) "1" 166 ["label"]=> 167 string(1) "a" 168 [1]=> 169 string(1) "a" 170 } 171} 172Error: Cannot instantiate abstract class mystatement6 173