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";
Related
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.
I have a trait that I would like to make so I can easily count and retrieve all the instances of the class.
I know I need to push it to an array, but I don't know how I should "store" the array. Do I use public, private, static, etc?
trait Countable
{
public $all = array();
public function addToObjects()
{
//do stuff
$this->all[] = $this->somekindofproperty;
}
}
I want to be able to something like the following.
$c = new MyClass;
$objects = $c->all();
Pretty much each class with this trait should have it's own array.
Here i defined a trait with name counter and used it in a class for storing objects.
trait Counter
{
public static $all = array();
public static function addToObjects($object)
{
if (is_object($object))
{
self::$all[] = $object;
}
}
}
class CountingClass
{
use Counter;
}
class MyClass
{
public function __construct()
{
CountingClass::addToObjects($this);
}
}
$c = new MyClass;
$c = new MyClass;
$c = new MyClass;
$c = new MyClass;
print_r(CountingClass::$all);
OUTPUT:
Array
(
[0] => MyClass Object
(
)
[1] => MyClass Object
(
)
[2] => MyClass Object
(
)
[3] => MyClass Object
(
)
)
can you initialize a static array of objects in a class in PHP? Like you can do
class myclass {
public static $blah = array("test1", "test2", "test3");
}
but when I do
class myclass {
public static $blah2 = array(
&new myotherclass(),
&new myotherclass(),
&new myotherclass()
);
}
where myotherclass is defined right above myclass.
That throws an error however; is there a way to achieve it?
Nope. From http://php.net/manual/en/language.oop5.static.php:
Like any other PHP static variable, static properties may only be
initialized using a literal or constant; expressions are not allowed.
So while you may initialize a static property to an integer or array
(for instance), you may not initialize it to another variable, to a
function return value, or to an object.
I would initialize the property to null, make it private with an accessor method, and have the accessor do the "real" initialization the first time it's called. Here's an example:
class myclass {
private static $blah2 = null;
public static function blah2() {
if (self::$blah2 == null) {
self::$blah2 = array( new myotherclass(),
new myotherclass(),
new myotherclass());
}
return self::$blah2;
}
}
print_r(myclass::blah2());
While you cannot initialize it to have these values, you can call a static method to push them into its own internal collection, as I've done below. This may be as close as you'll get.
class foo {
public $bar = "fizzbuzz";
}
class myClass {
static public $array = array();
static public function init() {
while ( count( self::$array ) < 3 )
array_push( self::$array, new foo() );
}
}
myClass::init();
print_r( myClass::$array );
Demo: http://codepad.org/InTPdUCT
Which results in the following output:
Array
(
[0] => foo Object
(
[bar] => fizzbuzz
)
[1] => foo Object
(
[bar] => fizzbuzz
)
[2] => foo Object
(
[bar] => fizzbuzz
)
)
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.)
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);