@@ -49,10 +49,9 @@ public static function ripAll(object $object): array
4949 // We also shouldn't cache, as individual objects may have variable field names (e.g. with public vars)
5050 // that are not present on other instances of the same class
5151
52- $ props = (\Closure:: bind (
52+ $ props = (self :: bindScopedClosure (
5353 fn () => \get_object_vars ($ object ),
54- NULL ,
55- $ object
54+ $ object ,
5655 ))();
5756
5857 // Safety check - the method above is efficient but can't return private props from parent classes
@@ -92,21 +91,35 @@ public static function ripOne($object, $property)
9291 */
9392 protected static function getRipper ($ class )
9493 {
95- if ( ! isset (static ::$ rippers [$ class ])) {
96- static ::$ rippers [$ class ] = \Closure::bind (
97- function ($ object , $ properties ) {
98- $ values = [];
99- foreach ($ properties as $ property ) {
100- $ values [$ property ] = $ object ->$ property ;
101- }
94+ static ::$ rippers [$ class ] ??= self ::bindScopedClosure (
95+ function ($ object , $ properties ) {
96+ $ values = [];
97+ foreach ($ properties as $ property ) {
98+ $ values [$ property ] = $ object ->$ property ;
99+ }
102100
103- return $ values ;
104- },
105- NULL ,
106- $ class
107- );
108- }
101+ return $ values ;
102+ },
103+ $ class ,
104+ );
109105
110106 return static ::$ rippers [$ class ];
111107 }
108+
109+ /**
110+ * @param object|class-string<object> $scope
111+ */
112+ private static function bindScopedClosure (callable $ callback , object |string $ scope ): \Closure
113+ {
114+ $ scope_class = \is_object ($ scope ) ? $ scope ::class : $ scope ;
115+ if ($ scope_class === \stdClass::class) {
116+ // Cannot bind to the scope of an internal class (e.g. stdClass), and there is no need to do so since
117+ // all stdClass properties are public.
118+ // Note that this is the *not* the case for a user-defined class that extends stdClass, hence checking
119+ // for the exact class name rather than `instanceof`.
120+ $ scope = null ;
121+ }
122+
123+ return \Closure::bind ($ callback , newThis: null , newScope: $ scope );
124+ }
112125}
0 commit comments