ElearningWorld.org

For the online learning world

MoodleTechnical

PHP Accessing Protected / Private Properties

I was reviewing some code from a colleague of mine the other day and I came across a technique for accessing protected / private properties that I had not considered before — bound closures.

Generally I would use reflection to do this so I was intrigued as to what the advantages / disadvantages would be.

Here’s some code which shows both methods:

<?php// Demo code – using closure / reflection to expose private properties.class HasPrivate {
// Public members.
public $a;

// Restricted members.
private $b;
private $c;
private function square($val) {
return $val * $val;
}
public function __construct() {
$this->a = 123;
$this->b = 999;
$this->c = 2;
}
}// Create instance of class with a private property “b”.
$hp = new HasPrivate();// Use closure bound to scope of class to access private property.
// see https://www.php.net/manual/en/closure.bind.php
$closuremethod = Closure::bind(function($hp) {
return $hp->b;
}, null, get_class($hp));// Here is the property recovered by the closure.
$byclosure = $closuremethod($hp);echo “nn Value recovered by closure “.$byclosure;// Use reflection to access private property.
// see https://www.php.net/manual/en/reflectionproperty.getvalue.php
$rc = new ReflectionClass($hp);
$prop = $rc->getProperty(‘b’);
$prop->setAccessible(true);
$byreflection = $prop->getValue($hp);echo “nn Value recovered by reflection “.$byreflection;// CLOSURE BENEFITS – can do more at once with less code!
// Use closure bound to scope of class to access multiple private members!
// see https://www.php.net/manual/en/closure.bind.php
$multiply = Closure::bind(function($hp) {
// Call private method to calculate multiple private properties.
return $hp->square($hp->b * $hp->c);
}, null, get_class($hp));// Calculation based on private stuff in $hp object.
$calculated = $multiply($hp);echo “nn Calculated value recovered by closure “.$calculated;

Here’s a link to the code on php sandbox so you can execute it and play with it:

http://sandbox.onlinephpfunctions.com/code/2e6cabff2616f29c2ed0b0fcf4919f7e11890ef8

Closures Pros/Cons

The first thing that I like about this technique is that you can do much more in one go than you can with reflection. Because we are binding a function to the scope of a class it acts almost like a method within that class, which means that if I wanted to access multiple private members in one go, or process them in some way, I can do so with less code. Say for example I want to multiply a private property by a private property I can do that all in one go inside the closure:

$closuremethod = Closure::bind(function($hp) {
return $hp->b * $hp->c;
}, null, get_class($hp));// Here is the property recovered by the closure.
$byclosure = $closuremethod($hp);

Another advantage of this technique is that you can do things with all member types, for example, I can also call private methods which is super cool — e.g:

$multiply = Closure::bind(function($hp) {
// Call private method to calculate multiple private properties.
return $hp->square($hp->b * $hp->c);
}, null, get_class($hp));

What I don’t like about this technique is readability. I have to run this through my mental PHP interpreter a few times to understand what it’s doing. So I recommend if you are going to use this technique, it may be worth adding a comment explaining what you are doing.

Reflection Pros/Cons

What I really like about this technique is readability. It takes minimal mental effort for me to understand what it’s doing and I don’t need any comments to explain it. However, for the sake of those new to reflection, here’s some comments added explaining what it’s doing:

// Create a reflection class of the $hp instance.
$rc = new ReflectionClass($hp);// Get the reflection property for the private property b.
$prop = $rc->getProperty(‘b’);// Make this property accessible so we can read its value.
$prop->setAccessible(true);// Get the value of the property now we’ve made it accessible.
$value = $prop->getValue($hp);

The disadvantage of using this technique is that I will end up writing much more code than with a closure if I need to access more than one private / protected property or method.

Conclusion

So there you have it! Binding a closure to a class gives you the ability to do more with restricted members in one go but sacrifices readability to a degree. Going forward, I will definitely be using this technique where appropriate instead of reflection.

Oh, and never underestimate the value of code reviews. When you have talented colleagues working with you, you never know what you might learn!

Source: https://brudinie.medium.com/feed

blank
Follow me

blank

ElearningWorld Admin

Site administrator

Add a reply or comment...