1--TEST-- 2PDO Common: serializing 3--SKIPIF-- 4<?php # vim:ft=php 5if (!extension_loaded('pdo')) die('skip'); 6$dir = getenv('REDIR_TEST_DIR'); 7if (false == $dir) die('skip no driver'); 8require_once $dir . 'pdo_test.inc'; 9PDOTest::skip(); 10?> 11--FILE-- 12<?php 13if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/'); 14require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; 15$db = PDOTest::factory(); 16 17class TestBase implements Serializable 18{ 19 public $BasePub = 'Public'; 20 protected $BasePro = 'Protected'; 21 private $BasePri = 'Private'; 22 23 function serialize() 24 { 25 $serialized = array(); 26 foreach($this as $prop => $val) { 27 $serialized[$prop] = $val; 28 } 29 $serialized = serialize($serialized); 30 echo __METHOD__ . "() = '$serialized'\n"; 31 return $serialized; 32 } 33 34 function unserialize($serialized) 35 { 36 echo __METHOD__ . "($serialized)\n"; 37 foreach(unserialize($serialized) as $prop => $val) { 38 $this->$prop = '#'.$val; 39 } 40 return true; 41 } 42} 43 44class TestDerived extends TestBase 45{ 46 public $BasePub = 'DerivedPublic'; 47 protected $BasePro = 'DerivdeProtected'; 48 public $DerivedPub = 'Public'; 49 protected $DerivedPro = 'Protected'; 50 private $DerivedPri = 'Private'; 51 52 function serialize() 53 { 54 echo __METHOD__ . "()\n"; 55 return TestBase::serialize(); 56 } 57 58 function unserialize($serialized) 59 { 60 echo __METHOD__ . "()\n"; 61 return TestBase::unserialize($serialized); 62 } 63} 64 65class TestLeaf extends TestDerived 66{ 67} 68 69$db->exec('CREATE TABLE classtypes(id int NOT NULL PRIMARY KEY, name VARCHAR(20) NOT NULL UNIQUE)'); 70$db->exec('INSERT INTO classtypes VALUES(0, \'stdClass\')'); 71$db->exec('INSERT INTO classtypes VALUES(1, \'TestBase\')'); 72$db->exec('INSERT INTO classtypes VALUES(2, \'TestDerived\')'); 73 74switch ($db->getAttribute(PDO::ATTR_DRIVER_NAME)) { 75 case 'dblib': 76 // environment settings can influence how the table is created if specifics are missing 77 // https://msdn.microsoft.com/en-us/library/ms174979.aspx#Nullability Rules Within a Table Definition 78 $sql = 'CREATE TABLE test(id int NOT NULL PRIMARY KEY, classtype int NULL, val VARCHAR(255) NULL)'; 79 break; 80 default: 81 $sql = 'CREATE TABLE test(id int NOT NULL PRIMARY KEY, classtype int, val VARCHAR(255))'; 82 break; 83} 84$db->exec($sql); 85 86$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 87 88var_dump($db->query('SELECT COUNT(*) FROM classtypes')->fetchColumn()); 89var_dump($db->query('SELECT id, name FROM classtypes ORDER by id')->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE)); 90 91$objs = array(); 92$objs[0] = new stdClass; 93$objs[1] = new TestBase; 94$objs[2] = new TestDerived; 95$objs[3] = new TestLeaf; 96 97$stmt = $db->prepare('SELECT id FROM classtypes WHERE name=:cname'); 98$stmt->bindParam(':cname', $cname); 99 100$ctypes = array(); 101 102foreach($objs as $obj) 103{ 104 $cname = get_class($obj); 105 $ctype = NULL; /* set default for non stored class name */ 106 $stmt->execute(); 107 $stmt->bindColumn('id', $ctype); 108 $stmt->fetch(PDO::FETCH_BOUND); 109 $ctypes[$cname] = $ctype; 110} 111 112echo "===TYPES===\n"; 113var_dump($ctypes); 114 115unset($stmt); 116 117echo "===INSERT===\n"; 118$stmt = $db->prepare('INSERT INTO test VALUES(:id, :classtype, :val)'); 119$stmt->bindParam(':id', $idx); 120$stmt->bindParam(':classtype', $ctype); 121$stmt->bindParam(':val', $val); 122 123foreach($objs as $idx => $obj) 124{ 125 $ctype = $ctypes[get_class($obj)]; 126 if (method_exists($obj, 'serialize')) 127 { 128 $val = $obj->serialize(); 129 } 130 else 131 { 132 $val = ''; 133 } 134 $stmt->execute(); 135} 136 137unset($stmt); 138 139echo "===DATA===\n"; 140$res = $db->query('SELECT test.val FROM test')->fetchAll(PDO::FETCH_COLUMN); 141 142switch ($db->getAttribute(PDO::ATTR_DRIVER_NAME)) { 143 case 'dblib': 144 // map whitespace (from early TDS versions) to empty string so the test doesn't diff 145 if ($res[0] === ' ') { 146 $res[0] = ''; 147 } 148 break; 149 150 case 'oci': 151 // map NULL to empty string so the test doesn't diff 152 if ($res[0] === null) { 153 $res[0] = ''; 154 } 155 break; 156} 157var_dump($res); 158 159echo "===FAILURE===\n"; 160try 161{ 162 $db->query('SELECT classtypes.name AS name, test.val AS val FROM test LEFT JOIN classtypes ON test.classtype=classtypes.id')->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE|PDO::FETCH_SERIALIZE, 'TestLeaf', array()); 163} 164catch (PDOException $e) 165{ 166 echo 'Exception:'; 167 echo $e->getMessage()."\n"; 168} 169 170echo "===COUNT===\n"; 171var_dump($db->query('SELECT COUNT(*) FROM test LEFT JOIN classtypes ON test.classtype=classtypes.id WHERE (classtypes.id IS NULL OR classtypes.id > 0)')->fetchColumn()); 172 173echo "===DATABASE===\n"; 174$stmt = $db->prepare('SELECT classtypes.name AS name, test.val AS val FROM test LEFT JOIN classtypes ON test.classtype=classtypes.id WHERE (classtypes.id IS NULL OR classtypes.id > 0)'); 175 176$stmt->execute(); 177var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); 178 179echo "===FETCHCLASS===\n"; 180$stmt->execute(); 181var_dump($stmt->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_CLASSTYPE|PDO::FETCH_SERIALIZE, 'TestLeaf')); 182 183 184?> 185--EXPECTF-- 186string(1) "3" 187array(3) { 188 [0]=> 189 string(8) "stdClass" 190 [1]=> 191 string(8) "TestBase" 192 [2]=> 193 string(11) "TestDerived" 194} 195===TYPES=== 196array(4) { 197 ["stdClass"]=> 198 string(1) "0" 199 ["TestBase"]=> 200 string(1) "1" 201 ["TestDerived"]=> 202 string(1) "2" 203 ["TestLeaf"]=> 204 NULL 205} 206===INSERT=== 207TestBase::serialize() = 'a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}' 208TestDerived::serialize() 209TestBase::serialize() = 'a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}' 210TestDerived::serialize() 211TestBase::serialize() = 'a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}' 212===DATA=== 213array(4) { 214 [0]=> 215 string(0) "" 216 [1]=> 217 string(91) "a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}" 218 [2]=> 219 string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}" 220 [3]=> 221 string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}" 222} 223===FAILURE=== 224Exception:SQLSTATE[HY000]: General error: cannot unserialize class 225===COUNT=== 226string(1) "3" 227===DATABASE=== 228array(3) { 229 [0]=> 230 array(2) { 231 ["name"]=> 232 string(8) "TestBase" 233 ["val"]=> 234 string(91) "a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}" 235 } 236 [1]=> 237 array(2) { 238 ["name"]=> 239 string(11) "TestDerived" 240 ["val"]=> 241 string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}" 242 } 243 [2]=> 244 array(2) { 245 ["name"]=> 246 NULL 247 ["val"]=> 248 string(172) "a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}" 249 } 250} 251===FETCHCLASS=== 252TestBase::unserialize(a:3:{s:7:"BasePub";s:6:"Public";s:7:"BasePro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}) 253TestDerived::unserialize() 254TestBase::unserialize(a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}) 255TestDerived::unserialize() 256TestBase::unserialize(a:5:{s:7:"BasePub";s:13:"DerivedPublic";s:7:"BasePro";s:16:"DerivdeProtected";s:10:"DerivedPub";s:6:"Public";s:10:"DerivedPro";s:9:"Protected";s:7:"BasePri";s:7:"Private";}) 257array(3) { 258 [0]=> 259 object(TestBase)#%d (3) { 260 ["BasePub"]=> 261 string(7) "#Public" 262 ["BasePro":protected]=> 263 string(10) "#Protected" 264 ["BasePri":"TestBase":private]=> 265 string(8) "#Private" 266 } 267 [1]=> 268 object(TestDerived)#%d (6) { 269 ["BasePub"]=> 270 string(14) "#DerivedPublic" 271 ["BasePro":protected]=> 272 string(17) "#DerivdeProtected" 273 ["DerivedPub"]=> 274 string(7) "#Public" 275 ["DerivedPro":protected]=> 276 string(10) "#Protected" 277 ["DerivedPri":"TestDerived":private]=> 278 string(7) "Private" 279 ["BasePri":"TestBase":private]=> 280 string(8) "#Private" 281 } 282 [2]=> 283 object(TestLeaf)#%d (6) { 284 ["BasePub"]=> 285 string(14) "#DerivedPublic" 286 ["BasePro":protected]=> 287 string(17) "#DerivdeProtected" 288 ["DerivedPub"]=> 289 string(7) "#Public" 290 ["DerivedPro":protected]=> 291 string(10) "#Protected" 292 ["DerivedPri":"TestDerived":private]=> 293 string(7) "Private" 294 ["BasePri":"TestBase":private]=> 295 string(8) "#Private" 296 } 297} 298