Php: How to list static fields/properties through reflection? - php

Let's say I have this class:
class Example {
public static $FOO = array('id'=>'foo', 'length'=>23, 'height'=>34.2);
public static $BAR = array('id'=>'bar', 'length'=>22.5, 'height'=>96.223);
}
How could I use reflection to get a list of the static fields? (Something like array('$FOO', '$BAR')?)

You'll want to use [ReflectionClass][1]. The getProperties() function will return an array of ReflectionProperty objects. The ReflectionProperty object have a isStatic() method which will tell you whether the property is static or not and a getName() method that return the name.
Example:
<?php
class Example {
public static $FOO = array('id'=>'foo', 'length'=>23, 'height'=>34.2);
public static $BAR = array('id'=>'bar', 'length'=>22.5, 'height'=>96.223);
}
$reflection = new ReflectionClass('Example');
$properties = $reflection->getProperties();
$static = array();
if ( ! empty($properties) )
foreach ( $properties as $property )
if ( $property->isStatic() )
$static[] = $property->getName();
print_r($static);

Related

Access parent and child variables in method defined in parent - PHP

I have a child object that inherits from a parent. Both have a static variable which has a different value in each object; I want to add that variable from both parent and child to an array when I instantiate the child. To save duplicating code, I've written a method (addFoo) in the parent which is called from both the parent and the child constructors. However, I can't seem to find a way to distinguish between the calls when the parent constructor is called from the child constructor (as you can see below, the output from the method is the same in both cases whether using $this, self or static).
class A {
public static $foo = 'foo';
public $thisvars = array();
public $selfvars = array();
public $staticvars = array();
public function __construct() {
$this->addFoo();
}
public function addFoo() {
$this->selfvars[] = self::$foo;
$this->staticvars[] = static::$foo;
$this->thisvars[] = $this::$foo;
}
}
class B extends A {
public static $foo = 'bar';
public function __construct() {
parent::__construct();
$this->addFoo();
}
}
$b = new B;
print_r($b->selfvars);
print_r($b->staticvars);
print_r($b->thisvars);
Output:
Array
(
[0] => foo
[1] => foo
)
Array
(
[0] => bar
[1] => bar
)
Array
(
[0] => bar
[1] => bar
)
I can workaround this by passing the calling class through to the addFoo function (see below), but is there a better (correct?) way?
class C {
public static $foo = 'foo';
public $vars = array();
public function __construct() {
$this->addFoo(__CLASS__);
}
public function addFoo($class) {
$this->vars[] = $class::$foo;
}
}
class D extends C {
public static $foo = 'bar';
public function __construct() {
parent::__construct();
$this->addFoo(__CLASS__);
}
}
$d = new D;
print_r($d->vars);
Output:
Array
(
[0] => foo
[1] => bar
)
Demo on 3v4l.org
Instead of having addFoo be called by every sub-constructor, one way would be to have a single addFoos method in the base class that is called by the base constructor, that would append all the $foo values starting from the late static binding class:
class A
{
public static $foo = 'foo';
public $vars = [];
public function __construct()
{
$this->addFoos();
}
private function addFoos()
{
$class = static::class;
do {
$this->vars[] = $class::$foo;
} while ($class = get_parent_class($class));
}
}
class B extends A
{
public static $foo = 'bar';
}
class C extends B
{
public static $foo = 'baz';
}
$a = new A;
print_r($a->vars); // ['foo']
$b = new B;
print_r($b->vars); // ['bar', 'foo']
$c = new C;
print_r($c->vars); // ['baz', 'bar', 'foo']
That method is marked private as it's not supposed to be extended in this scenario (nor called from the outside).
Demo
I would alternatively consider another, more straightforward approach:
class A
{
public static $foo = 'foo';
public function getVars()
{
return [self::$foo];
}
}
class B extends A
{
public static $foo = 'bar';
public function getVars()
{
return array_merge(parent::getVars(), [self::$foo]);
}
}
class C extends B
{
public static $foo = 'baz';
public function getVars()
{
return array_merge(parent::getVars(), [self::$foo]);
}
}
$a = new A;
print_r($a->getVars()); // ['foo']
$b = new B;
print_r($b->getVars()); // ['foo', 'bar']
$c = new C;
print_r($c->getVars()); // ['foo', 'bar', 'baz']
You do have to redefine getVars on each subclass in this case, but after all, it makes sense for each class to decide which variables should be exposed. Your code becomes a bit less obscure / easier to maintain in the process.
And if a class doesn't need/want to "contribute", you can simply omit both the static property and the getVars extension for that class.
Demo
Notes:
you can easily cache the variables into a $vars property inside A if needed,
order is swapped from the other answer but you can obviously swap the array_merge if needed,
in both this sample and the one from the other answer, I'm not sure if the $foo static properties need to be public, but I've left them like they were in your question.

How to get ReflectionObject object from ReflectionProperty in PHP

I have a ReflectionProperty object using the following code:
$service = new \ReflectionClass($this);
$properties = $service->getProperties();
$property = $properties[0];
I want to get the ReflectionObject object from the $property variable to get some extra information about the property (like what is its class and which classes is its class inherited from). How can I achieve this?
e.g.
class A {
/**
* #var \Utils\WebService
*/
public $prop;
}
now, I get the ReflectionClass (which actually refers to 'A') and I need to get the ReflectionClass/ReflectionObject for the $prop property. I need to later check what is the type of $prop and what supertypes it extends.
Thanks
class WebCrawler {
}
class WebService extends WebCrawler {
}
class A {
/**
* #var \WebService
*/
public $prop;
public $variable = 'hello';
function __construct()
{
$this->prop = new WebService();
}
}
// reflection
$obj = new A();
$reflectionObject = new \ReflectionObject($obj);
// get all public and protected properties
$properties = $reflectionObject->getProperties(\ReflectionProperty::IS_PUBLIC);
$properties = \array_merge($properties, $reflectionObject->getProperties(\ReflectionProperty::IS_PROTECTED));
\var_dump($properties);
// create the array similar to what you asked for
$data = [];
foreach ($properties as $property) {
$name = $property->name;
$data[$name] = $obj->{$name};
}
\var_dump($data);
// get info which class was inherited to the class defined in A::prop property
$reflectedObjectFromProperty = new \ReflectionObject($data['prop']);
\var_dump($reflectedObjectFromProperty->getParentClass());

Easiest way to get all static properties of a Class in php

I have a static class Foo (this isn't a real class, so static fields are just for example)
class Foo{
public static $name = "foo";
public static $age = "18";
public static $city = "Boston";
}
In my code I want to build an array of all the public static properties and their current values.
Is there a quick/easy way anyone can suggest to do this without instantiating a Foo?
Use a ReflectionClass instance like this to get an array of the property names and values:
$class = new ReflectionClass('Foo');
$staticProperties = $class->getStaticProperties();
foreach ($staticProperties as $propertyName => $value) {
// Your code here
}
Use the Reflection
<?php
require_once "Foo.php";
$reflection = new ReflectionClass("Foo");
$staticProperties = $reflection->getStaticProperties();
print_r($staticProperties)
http://php.net/manual/en/reflectionclass.getstaticproperties.php
http://ca2.php.net/manual/en/reflectionclass.getstaticpropertyvalue.php

How to get all the methods of a subclass?

I'm programming an object instance to other objects.
Now I need to validate an object instantiated.
The code i'm using is correct, but the objects are children of another object, so further back methods of parents.
Code:
<?php
class MyParentClass
{
...
$objectName = "subClassExample";
$obj = new $objectName();
print_r( get_class_methods( $obj ) );
...
}
?>
Return :
Array ( [0] => __construct [1] => myMethod )
The SubClass:
<?php
class subClassExample extends parentClass
{
public function myMethod()
{
return null;
}
}
?>
I need to return:
Array ( [0] => myMethod )
The parent Class:
<?php
class parentClass
{
function __construct ()
{
return null;
}
}
?>
I hope I can help, I really appreciate it.
Greetings!
P.S.: Excuse my English is not my language, I speak Spanish and Norwegian Bokmal.
You can do this with PHP's Reflection­Docs:
class Foo
{
function foo() {}
}
class Bar extends Foo
{
function bar() {}
}
function get_class_methodsA($class)
{
$rc = new ReflectionClass($class);
$rm = $rc->getMethods(ReflectionMethod::IS_PUBLIC);
$functions = array();
foreach($rm as $f)
$f->class === $class && $functions[] = $f->name;
return $functions;
}
print_r(get_class_methodsA('Bar'));
Output:
Array
(
[0] => bar
)
You may do this check inside a child or a parent class if you need only UNIQUE child's methods:
$cm = get_class_methods($this); //Get all child methods
$pm = get_class_methods(get_parent_class($this)); //Get all parent methods
$ad = array_diff($cm, $pm); //Get the diff
Keep in mind: get_class_methods returns all types of methods (public, protected etc.)

php magic method __set

I'm trying to set an ambiguous variable on a class. Something along these lines:
<?php
class MyClass {
public $values;
function __get($key){
return $this->values[$key];
}
function __set($key, $value){
$this->values[$key]=$value;
}
}
$user= new MyClass();
$myvar = "Foo";
$user[$myvar] = "Bar";
?>
Is there a way of doing this?
As has been stated $instance->$property (or $instance->{$property} to make it jump out)
If you really want to access it as an array index, implement the ArrayAccess interface and use offsetGet(), offsetSet(), etc.
class MyClass implements ArrayAccess{
private $_data = array();
public function offsetGet($key){
return $this->_data[$key];
}
public function offsetSet($key, $value){
$this->_data[$key] = $value;
}
// other required methods
}
$obj = new MyClass;
$obj['foo'] = 'bar';
echo $obj['foo']; // bar
Caveat: You cannot declare offsetGet to return by reference. __get(), however, can be which permits nested array element access of the $_data property, for both reading and writing.
class MyClass{
private $_data = array();
public function &__get($key){
return $this->_data[$key];
}
}
$obj = new MyClass;
$obj->foo['bar']['baz'] = 'hello world';
echo $obj->foo['bar']['baz']; // hello world
print_r($obj);
/* dumps
MyClass Object
(
[_data:MyClass:private] => Array
(
[foo] => Array
(
[bar] => Array
(
[baz] => hello world
)
)
)
)
Like so: http://ideone.com/gYftr
You'd use:
$instance->$dynamicName
You access member variables with the -> operator.
$user->$myvar = "Bar";

Categories