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