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