Hide specific class fields from print_r or var_dump
Is it possible to hide a specific class fields from print_r ?
<?php
class DataManager {
public $data = array();
}
class Data {
public $manager;
public $data = array();
public function Data ($m, $d) {
$this->manager = $m;
$this->data = $d;
}
}
$manager = new DataManager();
for ($a = 0; $a < 10; $a++) {
$manager->data[] = new Data($manager, 'Test ' . md5($a));
}
echo '<pre>';
print_r($manager);
?>
This would print
DataManager Object ( [data] => Array ( [0] => Data Object ( [manager] => DataManager Object RECURSION [data] => Test cfcd208495d565ef开发者_Go百科66e7dff9f98764da )
[1] => Data Object ( [manager] => DataManager Object *RECURSION* [data] => Test c4ca4238a0b923820dcc509a6f75849b ) .......
Is it possible to somehow change the output behavior so it print's like this? Like with DocComment /** @hidden **/
DataManager Object ( [data] => Array ( [0] => Data Object ( [data] => Test cfcd208495d565ef66e7dff9f98764da )
[1] => Data Object ( [data] => Test c4ca4238a0b923820dcc509a6f75849b )
If not, is there some sort of PHP lib that maybe uses Reflection and somehow bypasses stuff?
Thanks
New Magic method __debugInfo() was introduced in PHP 5.6 that will allow you to modify the default behaviour of var_dump() when dumping your objects.
Have a look at the documentation.
Example:
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>
Returns:
object(C)#1 (1) {
["propSquared"]=>
int(1764)
}
Although this question is 4 years old, I'm sure someone will find this useful in the future.
Both print_r() and var_dump() will give you everything.
Various Reflection
classes have a getDocComment()
method to get the /** doc comment */
for classes, methods and properties.
Utilising doc comments to denote what should and should not be output, you can quite easily create a dumping class to achieve what you want.
Add this magic method in your class to hide specific variables while using var_dump()
:
public function __debugInfo(){
$vars = get_object_vars($this);
unset($vars['prop1'],$vars['prop2']);
return $vars;
}
Edit
This alternative uses the ReflectionProperty Class to hide the private variables:
public function __debugInfo(){
$vars = get_object_vars($this);
foreach( $vars as $prop => $value ){
try{
$rp = new ReflectionProperty(__CLASS__,$prop);
}
catch(ReflectionException $e){}
if( $rp->isPrivate() ){
unset($vars[$prop]);
}
}
return $vars;
}
Yes, but only internally. It's just a matter of not exposing the relevant property in the hash table returned by the get_properties
handler.
You can also hide the property behind a __get
handler, but you still have to store the data somewhere and __get
has a performance (and clarity) penalty.
I though of a solution to this, I don't know if it will work for your needs or how efficient it is but it seems to work.
What I did was changed the variable in the class to a function with a single static variable.
Here's a quick example:
<?php
header('Content-type: text');
class myClass {
public $visibleVar;
function hiddenVar($set_to_new_val=null){
static $theVariable;
if(is_null($set_to_new_val))
return $theVariable;
$theVariable = $set_to_new_val;
}
}
$test = new myClass;
$test->visibleVar = range(1,5);
print_r($test);
print_r($test->visibleVar);
$test->hiddenVar(range(100,105));
print_r($test);
print_r($test->hiddenVar());
?>
Output:
myClass Object
(
[visibleVar] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
myClass Object
(
[visibleVar] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
)
Array
(
[0] => 100
[1] => 101
[2] => 102
[3] => 103
[4] => 104
[5] => 105
)
I built upon Meir's solution to extend it to work with multiple objects of the class. Here is my solution:
<?php
header('Content-type: text');
class myClass {
public $visibleVar;
private static $hiddenVarMap = array();
private $hiddenVarKey;
function hiddenVar($set_to_new_val=null){
if(empty($this->hiddenVarKey) {
$this->hiddenVarKey = sha1(rand());
}
if(!empty($set_to_new_val)){
self::$hiddenVarMap[$this->hiddenVarKey] = $set_to_new_val;
}
return self::$hiddenVarMap[$this->hiddenVarKey];
}
}
$test = new myClass;
$test->visibleVar = range(1,5);
print_r($test);
print_r($test->visibleVar);
$test->hiddenVar(range(100,105));
print_r($test);
print_r($test->hiddenVar());
?>
You can use simple closure to hide the sensitive data.
class PrivateValue {
private $val;
public function __construct($val) {
$this->val = function() use ($val) { return $val; };
}
public function getValue() {
return ($this->val)();
}
public fucntion __debugInfo() {
return [ 'val' => '***' ]; // TODO
}
}
Storing the closure rather than value hides the value from everything I can think of. The getter then retrieves the value by invoking the closure. The __debugInfo
method provides some useful but safe representation for developers as var_dump
will show it. Unhandled features like var_export will show 'closure', but not the boud value.
Keep in mind that some tools my try too hard and dig out these data too.
I've got the inspiration from other answers here. — Thank you!
精彩评论