1--TEST-- 2Lazy objects: initializer must return the right type 3--FILE-- 4<?php 5 6class B { 7 public int $b; 8 public function __construct() { 9 $this->b = 1; 10 } 11 public function __destruct() { 12 } 13} 14 15class C extends B { 16} 17 18class D extends C { 19 public int $b; // override 20} 21 22class E extends B { 23 public function __destruct() { // override 24 } 25} 26 27$reflector = new ReflectionClass(C::class); 28 29print "# Ghost initializer must return NULL or no value:\n"; 30 31$obj = $reflector->newLazyGhost(function ($obj) { 32 var_dump("initializer"); 33 $obj->__construct(); 34 return new stdClass; 35}); 36 37var_dump($obj); 38try { 39 var_dump($obj->a); 40} catch (\Error $e) { 41 printf("%s: %s\n", $e::class, $e->getMessage()); 42} 43var_dump($obj); 44 45print "# Proxy initializer must return an instance of a compatible class:\n"; 46print "## Valid cases:\n"; 47 48$tests = [ 49 [C::class, new C()], 50 [C::class, new B()], 51 [D::class, new B()], 52]; 53 54foreach ($tests as [$class, $instance]) { 55 $obj = (new ReflectionClass($class))->newLazyProxy(function ($obj) use ($instance) { 56 var_dump("initializer"); 57 $instance->b = 1; 58 return $instance; 59 }); 60 61 printf("## %s vs %s\n", get_class($obj), is_object($instance) ? get_class($instance) : gettype($instance)); 62 var_dump($obj->b); 63 var_dump($obj); 64} 65 66print "## Invalid cases:\n"; 67 68$tests = [ 69 [C::class, new stdClass], 70 [C::class, new DateTime()], 71 [C::class, null], 72 [C::class, new D()], 73 [E::class, new B()], 74]; 75 76foreach ($tests as [$class, $instance]) { 77 $obj = (new ReflectionClass($class))->newLazyProxy(function ($obj) use ($instance) { 78 var_dump("initializer"); 79 return $instance; 80 }); 81 82 try { 83 printf("## %s vs %s\n", get_class($obj), is_object($instance) ? get_class($instance) : gettype($instance)); 84 var_dump($obj->a); 85 } catch (\Error $e) { 86 printf("%s: %s\n", $e::class, $e->getMessage()); 87 } 88} 89 90$obj = $reflector->newLazyProxy(function ($obj) { 91 var_dump("initializer"); 92 return $obj; 93}); 94 95try { 96 printf("## %s vs itself\n", get_class($obj)); 97 var_dump($obj->a); 98} catch (\Error $e) { 99 printf("%s: %s\n", $e::class, $e->getMessage()); 100} 101 102--EXPECTF-- 103# Ghost initializer must return NULL or no value: 104lazy ghost object(C)#%d (0) { 105 ["b"]=> 106 uninitialized(int) 107} 108string(11) "initializer" 109TypeError: Lazy object initializer must return NULL or no value 110lazy ghost object(C)#%d (0) { 111 ["b"]=> 112 uninitialized(int) 113} 114# Proxy initializer must return an instance of a compatible class: 115## Valid cases: 116## C vs C 117string(11) "initializer" 118int(1) 119lazy proxy object(C)#%d (1) { 120 ["instance"]=> 121 object(C)#%d (1) { 122 ["b"]=> 123 int(1) 124 } 125} 126## C vs B 127string(11) "initializer" 128int(1) 129lazy proxy object(C)#%d (1) { 130 ["instance"]=> 131 object(B)#%d (1) { 132 ["b"]=> 133 int(1) 134 } 135} 136## D vs B 137string(11) "initializer" 138int(1) 139lazy proxy object(D)#%d (1) { 140 ["instance"]=> 141 object(B)#%d (1) { 142 ["b"]=> 143 int(1) 144 } 145} 146## Invalid cases: 147## C vs stdClass 148string(11) "initializer" 149TypeError: The real instance class stdClass is not compatible with the proxy class C. The proxy must be a instance of the same class as the real instance, or a sub-class with no additional properties, and no overrides of the __destructor or __clone methods. 150## C vs DateTime 151string(11) "initializer" 152TypeError: The real instance class DateTime is not compatible with the proxy class C. The proxy must be a instance of the same class as the real instance, or a sub-class with no additional properties, and no overrides of the __destructor or __clone methods. 153## C vs NULL 154string(11) "initializer" 155TypeError: Lazy proxy factory must return an instance of a class compatible with C, null returned 156## C vs D 157string(11) "initializer" 158TypeError: The real instance class D is not compatible with the proxy class C. The proxy must be a instance of the same class as the real instance, or a sub-class with no additional properties, and no overrides of the __destructor or __clone methods. 159## E vs B 160string(11) "initializer" 161TypeError: The real instance class B is not compatible with the proxy class E. The proxy must be a instance of the same class as the real instance, or a sub-class with no additional properties, and no overrides of the __destructor or __clone methods. 162## C vs itself 163string(11) "initializer" 164Error: Lazy proxy factory must return a non-lazy object 165