Default values to static variables - php

Is it possible to use Traits for giving default values to static variables? Consider the following example.
trait Properties {
public static $properties = [];
}
class Base {
use Properties;
}
Base::$properties[0] = 'val1';
Base::$properties[1] = 'val2';
Base::$properties[2] = 'val3';
class Derived extends Base {
use Properties;
}
Derived::$properties[1] = 'changed value';
Derived::$properties[3] = 'new value';
var_dump(Base::$properties);
var_dump(Derived::$properties);
I would like the output to be something like
array (size=3)
0 => string 'val1' (length=4)
1 => string 'val2' (length=4)
2 => string 'val3' (length=4)
array (size=4)
0 => string 'val1' (length=4)
1 => string 'changed value' (length=13)
2 => string 'val3' (length=4)
3 => string 'new value' (length=9)
The example does not work, since Base and Properties define the same property ($properties) in the composition of Derived. If I remove the use Properties from Derived, the $properties variable is the same for both Base and Derived, and any changes applies to both classes. I hoped to get around this by including Properties in both classes. Are there any nice ways to achieve what I want? I don't have to use Traits, I just thought this could help.

I suggest a pretty straightforward object-oriented style.
It goes without traits, but with method-accessors in place of attribute-accessors:
class Base {
private static $properties;
public static function getProperties() {
if (!isset(self::$properties)) {
self::$properties = ['val1', 'val2', 'val3']; // use `array('val1', 'val2', 'val3')` with PHP<5.4
}
return self::$properties;
}
}
class Derived extends Base {
private static $properties; // has nothing to do with parent::$properties!
public static function getProperties() {
if (!isset(self::$properties)) {
self::$properties = parent::getProperties();
self::$properties[1] = 'changed value';
self::$properties[] = 'new value';
}
return self::$properties;
}
}
var_dump(Base::getProperties());
var_dump(Derived::getProperties());
Note that there's no risk of modifying internal arrays from outside with method-accessors, and that there's practically no performance impact of using methods with memoization.

Related

How to modify the way an object is casted into an array? [duplicate]

I have an object of class Foo:
class Foo extends Bar {
protected $a;
protected $b;
}
$obj = new Foo();
What I want (and have) to do is cast this object to an array, like this:
$arr = (array)$obj;
Is there any magic (or not magic :)) method that is being called at this moment? Or is there any other way to intercept it? I know I can write a simple method, eg. asArray() in Foo, but I'm looking for some more "native" PHP ways.
No
There is no __toArray magic method in PHP. An enhancement proposal has been rejected in 2006 with the following answer:
[2006-08-20 11:12 UTC] helly#php.net
Why not simply have a method asArray() maybe even as par of an
interface:
interface ArrayConversion { function asArray(); }
See, we have __toString as it is supported in language constructs like
echo, print and other internal functions. But we decided against an
autoconversion for arrays already. So itwill never be supported in any
language construct. That said there is no needed for this and nothing
you would win against the above interface. In fact you would make it
php more complex because you'd add just one more magic feature.
It is thus very unlikely that it will be implemented in any future release (which is a pity, if you ask me).
You can have the class implement the ArrayAccess interface. This will allow you to treat the object like an array without casting and you get total control over how the members are used.
Sadly no, casting to array doesn't trigger any magic method like it is done with:
$s = (string)$obj;
which triggers __toString() method and which you can override.
However, you may write a custom toArray() method.
You may also be interested in the Serializable interface which allows you to write custom serializer strategy.
Not sure if this question still relevant, but php has builtin ArrayObject class, that allows to treat object as array and can be handy when used as container for database record or collection.
It might be not a best practice in regards to strict types, but it allows to treat object as array and both statements are valid.
$obj = new ArrayObject(['a' => 'alpha']);
var_dump($obj['a']); //alpha
var_dump($obj->getOffset('a'));//alpha
However you need to keep in mind behaviour of ArrayObject
$obj = new ArrayObject(['a' => 'alpha']);
//Access Property
var_dump($obj['a']); //alpha
var_dump($obj->offsetGet('a'));//alpha
var_dump($obj->a); //null Notice: Undefined property: ArrayObject::$a
//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!
//Setting Properties
$obj['b'] = 'beta'; //OK
$obj->c = 'gamma'; //value becomes object property!!!
var_dump($obj);
/* OBJECT DUMP
object(ArrayObject)[13]
public 'c' => string 'gamma' (length=5)
private 'storage' =>
array (size=2)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
*/
//Property validation as array
var_dump(isset($obj['a']));//true
var_dump(isset($obj['b']));//true
var_dump(isset($obj['c']));//false
//Property validation as object
var_dump(isset($obj->a));//false
var_dump(isset($obj->b));//false
var_dump(isset($obj->c));//true
//Typecasting
var_dump((array)$obj);
/*
array (size=2)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
*/
//var_dump((string)$obj);// Catchable fatal error: Object of class ArrayObject could not be converted to string
ArrayObject accepts two flags ArrayObject::STD_PROP_LIST as default and ArrayObject::ARRAY_AS_PROPS as alternative.
This would change behaviour for reading values but does not support setting new properties in that way, here is example:
$obj = new ArrayObject(['a' => 'alpha'], ArrayObject::ARRAY_AS_PROPS);
//Access Property
var_dump($obj['a']); //alpha
var_dump($obj->offsetGet('a'));//alpha
var_dump($obj->a);//alpha
//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!
//Setting Properties
$obj['b'] = 'beta'; //OK
$obj->c = 'gamma'; //OK
var_dump($obj);
/* OBJECT DUMP
object(ArrayObject)[14]
private 'storage' =>
array (size=3)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
'c' => string 'gamma' (length=5)
*/
//Property validation as array
var_dump(isset($obj['a']));//true
var_dump(isset($obj['b']));//true
var_dump(isset($obj['c']));//false !!!
//Property validation as object
var_dump(isset($obj->a));//true
var_dump(isset($obj->b));//true
var_dump(isset($obj->c));//true
//Typecasting
var_dump((array)$obj);
/*
array (size=2)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
*/
To make this behaviour more consistent you would have to extend this class and implement magic methods __get(), __set(), __isset() and __unset().
Another tricky part is serialization, default method serialize would return you a copy serialized $storage variable instead of object itself, as workaround to return serialized copy of instance you can implement default serialization in __toString method, this way it's behave correctly.
class FooObject extends ArrayObject
{
public function __get($index)
{
if ($this->offsetExists($index)) {
return $this->offsetGet($index);
} else {
throw new UnexpectedValueException('Undefined key ' . $index);
}
}
public function __set($index, $value)
{
$this->offsetSet($index, $value);
return $this;
}
public function __isset($index)
{
return $this->offsetExists($index);
}
public function __unset($index)
{
return $this->offsetUnset($index);
}
public function __toString()
{
return serialize($this);
}
}
Example of usage
$obj2 = new FooObject(['a' => 'alpha']);
//Access Property
var_dump($obj2['a']); //alpha
var_dump($obj2->offsetGet('a'));//alpha
var_dump($obj2->a); //alpha
//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!
//Setting Properties
$obj2['b'] = 'beta'; //OK
$obj2->c = 'gamma'; //OK
var_dump($obj2);
/* OBJECT DUMP
object(FooObject)[14]
private 'storage' (ArrayObject) =>
array (size=3)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
'c' => string 'gamma' (length=5)
*/
//Property validation as array
var_dump(isset($obj2['a']));//true
var_dump(isset($obj2['b']));//true
var_dump(isset($obj2['c']));//true
//Property validation as object
var_dump(isset($obj2->a));//true
var_dump(isset($obj2->b));//true
var_dump(isset($obj2->c));//true
//Typecasting
var_dump((array)$obj2);
/*
array (size=3)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
'c' => string 'gamma' (length=5)
*/
One way to do this, without changing the original class definition is to use reflection. This allows to you examine the class's properties at runtime.
Taken from the manual: http://www.php.net/manual/en/reflectionclass.getproperties.php
<?php
class Foo {
public $foo = 1;
protected $bar = 2;
private $baz = 3;
}
$foo = new Foo();
$reflect = new ReflectionClass($foo);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
foreach ($props as $prop) {
print $prop->getName() . "\n";
}
var_dump($props);
?>
The above example will output something similar to:
foo
bar
array(2) {
[0]=>
object(ReflectionProperty)#3 (2) {
["name"]=>
string(3) "foo"
["class"]=>
string(3) "Foo"
}
[1]=>
object(ReflectionProperty)#4 (2) {
["name"]=>
string(3) "bar"
["class"]=>
string(3) "Foo"
}
}
You can use get_object_vars($yourObject) that will return an associative array of all property names/values accessible from the context.
See http://php.net/manual/en/function.get-object-vars.php
A you want to access protected or private properties, my advice would be to extend ArrayObject, that implements the method getArrayCopy()

Getting properties of an object retrieved from DB by PDO fetchAll (PDO::FETCH_OBJ)

I do have an array of objects retrieved from DB with PDO fetchALL(PDO::FETCH_OBJ). When I var_dump first element of that array:
var_dump($this->stockList[0]);
I get:
object(stdClass)[5]
public 'userId' => string '3' (length=1)
public 'symbol' => string 'ibm' (length=3)
public 'date' => string '2019-01-03' (length=10)
public 'quantity' => string '5' (length=1)
public 'bought' => string '1' (length=1)
public 'observed' => string '0' (length=1)
public 'dividendRate' => string '6.28' (length=4)
public 'exDividendDate' => string '2018-11-08' (length=10)
public 'forwardDividend' => string '31.400000000000002' (length=18)
I would like to use reflection on this object to get all of it's properties:
$r = new ReflectionClass($this->stockList[0]);
$objProperties = $r->getProperties();
I get proper class:
var_dump($r);
produces:object(ReflectionClass)[16]
public 'name' => string 'stdClass' (length=8)
but I can't get properties of that object:
var_dump($objProperties);
gives an empty array:
array (size=0)
empty
So, the question is how do I get a list of properties of that object?
My full code:
$sql = "query";
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_OBJ);
var_dump($this->stockList[0]);
$r = new ReflectionClass($this->stockList[0]);
$objProperties = $r->getProperties();
var_dump($r);
var_dump($objProperties);
Reflection with an StdClass will not work. The call to ReflectionClass(), parameter one uses the ::class of the instance to determine its properties. Since StdClass has no properties at default and are given dynamically, Reflection can not find any properties since by default they do no exist.
You can see the above in a demo. However, for even more simplicity, this would work fine:
var_dump(array_keys((array) new Foo('bar'))); # Based on above demo
However, do not panic. You do not need to use reflection to do this: \PDO::FETCH_ASSOC will give you a multidimensional array. You can use array_keys() to get the parameters. Then, later, if you prefer to use the result as an object, cast the array as an object.
# Fetch Query
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_ASSOC);
# Get properties which will be, in this case, ['id', 'symbol', 'date', 'quantity', 'bought', 'observed', 'dividendRate', 'exDividentDate', 'forwardDivident']
$properties = array_keys($this->stockList[0]);
# Revert all back to StdClass instances by casting the array to object
foreach($this->stockList as &$stockItem) {
$stockItem = (object) $stockItem;
}
Alternativly, as suggested in the comments by #Quasimodosclone. You can use get_object_vars() which will return the array equivalent of the object. Then, like before, use array_keys() to get the properties.
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_OBJ);
$properties = array_keys(get_object_vars($this->stockList[0]));
After testing this out of curiosity, the object can be casted to an array to achieve more simplicity.
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_OBJ);
$properties = array_keys( (array) $this->stockList[0] );

How to get an object property->property from a stdClass with a string representing it

My situation is quite simple, but i'm still looking for a nice and short solution for it.
Here is my case:
I receive a soap response object which is my be different from a call to another.
Sometimes, these properties are objects themselves and may have properties we have to get. For this, an array is set for each type of call to select the data wanted and discard the rest.
By example, in a call we receive an object like this:
(I made a code easy to test by mocking the received object)
$objTest = new stdClass();
$objTest->Content1 = "";
$objTest->Content2 = new stdClass();
$objTest->Content2->prop1=1;
$objTest->Content2->prop2=2;
$objTest->Content2->prop3=3;
$objTest->Content3 = 3;
$objTest->Content4 = array('itm1'=>1, 'itm2'=>'two');
i want to check if $objTest->Content2->prop3 exist, but i don't know at the right moment i am looking for this because what i'm looking for is in the associative array.
The array for the call look like:
$map = array('Content3','Content2->prop3');
From now i am able to get the content of the Content3 property by doing this:
foreach ($map as $name => $value) {
if (isset($object->$name)) {
echo "$value: ". json_encode($object->$name)."\n";
}
}
But not for the other because of the reference "->".
Now my question:
Is there a way to get an unknown property of an unknown object as displayed above?
This is a result of the previous test:
Dump of objTests:
object(stdClass)[1]
public 'Content1' => string '' (length=0)
public 'Content2' => object(stdClass)[2]
public 'prop1' => int 1
public 'prop2' => int 2
public 'prop3' => int 3
public 'Content3' => int 3
public 'Content4' => array (size=2)
'itm1' => int 1
'itm2' => string 'two' (length=3)
Trying to access the proprerty prop3 of the content2 of the object with a string:
Standard way to get the value : $objTest->Content2->prop3
Result : 3
Test string: "Content3"
Result: 3
Test astring: "Content2->prop3"
( ! ) Notice: Undefined property: stdClass::$Content2->prop3
Hope i put everything to help understand my situation!
Thanks!
I don't know of a built-in PHP function that does this, but a function could be used to break up the string of properties and iterate through them to find the value of the last one in the string.
function get_property($object, $prop_string, $delimiter = '->') {
$prop_array = explode($delimiter, $prop_string);
foreach ($prop_array as $property) {
if (isset($object->{$property}))
$object = $object->{$property};
else
return;
}
return $object;
}

Array lookup value from dynamic string

I'm trying to build a dynamic associative array value lookup function (within a class):
class Family
{
public static $members = array(
'one' => array(
'child' => 0,
'children' => 5
),
'two' => array(
'child' => 2,
'children' => null
)
);
public static function resolveMemberValue()
{
$chain = func_get_args();
$lookup = 'members' . '[\'' . implode('\'][\'', $chain) . '\']';
var_dump( $lookup );
return static::$$lookup;
}
}
Family::resolveMemberValue('one', 'child');
But this results in:
string(23) "members['one']['child']"
Fatal error: Access to undeclared static property: Family::$members['one']['child'] in /family.php on line 23
PHP Fatal error: Access to undeclared static property: Family::$members['one']['child'] in /family.php on line 23
Though, copying the dumped value, and pasting inside the script + appending dollar sign, it returns what's expected:
var_dump( Family::$members['one']['child'] );
int(0)
Reason why I need this is, because it will be used with multiple variables, and called from generator functions.
What is wrong with the snippet?
Variable variables only substitutes in a string for the name of the variable. It can't evaluate the content of that string (in this case the string members['one']['child'])
Your code is looking for a static property literally with the named $members['one']['child'] not an element of the static array $members.
Try this instead:
$member = static::$members[$chain[0]];
return $member[$chain[1]];
Also, I'd recommend not using func_get_args(), but explicitly naming your parameters in the method declaration. Some features of PHP a best left behind....
Oh, had to just tinker a little - managed to make a helper function.
The function replaces the implode() and the explicit key definition.
function array_lookup()
{
$chain = func_get_args();
$array = array_shift($chain);
foreach ($chain as $key) $array = $array[$key];
return $array;
}
$test = array(
'one' => array(
'child' => 0,
'children' => 5
),
'two' => array(
'child' => 2,
'children' => null
)
);
var_dump($test, 'one', 'child'); // int(0)
I have left out any kind of error checking for this example, but it does what I was looking for.
And yes, for my example, it nails it.

Casting object to array - any magic method being called?

I have an object of class Foo:
class Foo extends Bar {
protected $a;
protected $b;
}
$obj = new Foo();
What I want (and have) to do is cast this object to an array, like this:
$arr = (array)$obj;
Is there any magic (or not magic :)) method that is being called at this moment? Or is there any other way to intercept it? I know I can write a simple method, eg. asArray() in Foo, but I'm looking for some more "native" PHP ways.
No
There is no __toArray magic method in PHP. An enhancement proposal has been rejected in 2006 with the following answer:
[2006-08-20 11:12 UTC] helly#php.net
Why not simply have a method asArray() maybe even as par of an
interface:
interface ArrayConversion { function asArray(); }
See, we have __toString as it is supported in language constructs like
echo, print and other internal functions. But we decided against an
autoconversion for arrays already. So itwill never be supported in any
language construct. That said there is no needed for this and nothing
you would win against the above interface. In fact you would make it
php more complex because you'd add just one more magic feature.
It is thus very unlikely that it will be implemented in any future release (which is a pity, if you ask me).
You can have the class implement the ArrayAccess interface. This will allow you to treat the object like an array without casting and you get total control over how the members are used.
Sadly no, casting to array doesn't trigger any magic method like it is done with:
$s = (string)$obj;
which triggers __toString() method and which you can override.
However, you may write a custom toArray() method.
You may also be interested in the Serializable interface which allows you to write custom serializer strategy.
Not sure if this question still relevant, but php has builtin ArrayObject class, that allows to treat object as array and can be handy when used as container for database record or collection.
It might be not a best practice in regards to strict types, but it allows to treat object as array and both statements are valid.
$obj = new ArrayObject(['a' => 'alpha']);
var_dump($obj['a']); //alpha
var_dump($obj->getOffset('a'));//alpha
However you need to keep in mind behaviour of ArrayObject
$obj = new ArrayObject(['a' => 'alpha']);
//Access Property
var_dump($obj['a']); //alpha
var_dump($obj->offsetGet('a'));//alpha
var_dump($obj->a); //null Notice: Undefined property: ArrayObject::$a
//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!
//Setting Properties
$obj['b'] = 'beta'; //OK
$obj->c = 'gamma'; //value becomes object property!!!
var_dump($obj);
/* OBJECT DUMP
object(ArrayObject)[13]
public 'c' => string 'gamma' (length=5)
private 'storage' =>
array (size=2)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
*/
//Property validation as array
var_dump(isset($obj['a']));//true
var_dump(isset($obj['b']));//true
var_dump(isset($obj['c']));//false
//Property validation as object
var_dump(isset($obj->a));//false
var_dump(isset($obj->b));//false
var_dump(isset($obj->c));//true
//Typecasting
var_dump((array)$obj);
/*
array (size=2)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
*/
//var_dump((string)$obj);// Catchable fatal error: Object of class ArrayObject could not be converted to string
ArrayObject accepts two flags ArrayObject::STD_PROP_LIST as default and ArrayObject::ARRAY_AS_PROPS as alternative.
This would change behaviour for reading values but does not support setting new properties in that way, here is example:
$obj = new ArrayObject(['a' => 'alpha'], ArrayObject::ARRAY_AS_PROPS);
//Access Property
var_dump($obj['a']); //alpha
var_dump($obj->offsetGet('a'));//alpha
var_dump($obj->a);//alpha
//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!
//Setting Properties
$obj['b'] = 'beta'; //OK
$obj->c = 'gamma'; //OK
var_dump($obj);
/* OBJECT DUMP
object(ArrayObject)[14]
private 'storage' =>
array (size=3)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
'c' => string 'gamma' (length=5)
*/
//Property validation as array
var_dump(isset($obj['a']));//true
var_dump(isset($obj['b']));//true
var_dump(isset($obj['c']));//false !!!
//Property validation as object
var_dump(isset($obj->a));//true
var_dump(isset($obj->b));//true
var_dump(isset($obj->c));//true
//Typecasting
var_dump((array)$obj);
/*
array (size=2)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
*/
To make this behaviour more consistent you would have to extend this class and implement magic methods __get(), __set(), __isset() and __unset().
Another tricky part is serialization, default method serialize would return you a copy serialized $storage variable instead of object itself, as workaround to return serialized copy of instance you can implement default serialization in __toString method, this way it's behave correctly.
class FooObject extends ArrayObject
{
public function __get($index)
{
if ($this->offsetExists($index)) {
return $this->offsetGet($index);
} else {
throw new UnexpectedValueException('Undefined key ' . $index);
}
}
public function __set($index, $value)
{
$this->offsetSet($index, $value);
return $this;
}
public function __isset($index)
{
return $this->offsetExists($index);
}
public function __unset($index)
{
return $this->offsetUnset($index);
}
public function __toString()
{
return serialize($this);
}
}
Example of usage
$obj2 = new FooObject(['a' => 'alpha']);
//Access Property
var_dump($obj2['a']); //alpha
var_dump($obj2->offsetGet('a'));//alpha
var_dump($obj2->a); //alpha
//Serialization
var_dump(serialize($obj));// string 'C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}' (length=65)
var_dump($obj->serialize());// string 'x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'
var_dump(serialize($obj) === $obj->serialize());// false !!!
//Setting Properties
$obj2['b'] = 'beta'; //OK
$obj2->c = 'gamma'; //OK
var_dump($obj2);
/* OBJECT DUMP
object(FooObject)[14]
private 'storage' (ArrayObject) =>
array (size=3)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
'c' => string 'gamma' (length=5)
*/
//Property validation as array
var_dump(isset($obj2['a']));//true
var_dump(isset($obj2['b']));//true
var_dump(isset($obj2['c']));//true
//Property validation as object
var_dump(isset($obj2->a));//true
var_dump(isset($obj2->b));//true
var_dump(isset($obj2->c));//true
//Typecasting
var_dump((array)$obj2);
/*
array (size=3)
'a' => string 'alpha' (length=5)
'b' => string 'beta' (length=4)
'c' => string 'gamma' (length=5)
*/
One way to do this, without changing the original class definition is to use reflection. This allows to you examine the class's properties at runtime.
Taken from the manual: http://www.php.net/manual/en/reflectionclass.getproperties.php
<?php
class Foo {
public $foo = 1;
protected $bar = 2;
private $baz = 3;
}
$foo = new Foo();
$reflect = new ReflectionClass($foo);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
foreach ($props as $prop) {
print $prop->getName() . "\n";
}
var_dump($props);
?>
The above example will output something similar to:
foo
bar
array(2) {
[0]=>
object(ReflectionProperty)#3 (2) {
["name"]=>
string(3) "foo"
["class"]=>
string(3) "Foo"
}
[1]=>
object(ReflectionProperty)#4 (2) {
["name"]=>
string(3) "bar"
["class"]=>
string(3) "Foo"
}
}
You can use get_object_vars($yourObject) that will return an associative array of all property names/values accessible from the context.
See http://php.net/manual/en/function.get-object-vars.php
A you want to access protected or private properties, my advice would be to extend ArrayObject, that implements the method getArrayCopy()

Categories