Trait that counts instances of class - php

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
(
)
)

Related

php: property inheritance on nested class structure

It's not clear to me how class inheritance is implemented in php 5.4.7 (almost old! I know!).
Consider this example:
Class ClassA {
public $property = array();
function __construct() {
$this->property[] = "ClassA.construct";
}
public function SetA() {
$this->property[] = "ClassA.Set";
}
}
Class ClassB extends ClassA {
function __construct() {
$this->property[] = "ClassB.construct";
}
function SetB() {
$this->property[] = "ClassB.Set";
}
}
If I call in sequence
$classA = new ClassA();
$classA->SetA();
$classB = new ClassB();
$classB->SetB();
print_r($classB->property);
My expected behavior is to have...
Array
(
[0] => ClassA.construct
[1] => ClassA.Set
[2] => ClassB.construct
[3] => ClassB.Set
)
...but I obtain instead...
Array
(
[0] => ClassB.construct
[1] => ClassB.Set
)
So, what's wrong on my side?
How can I add element from a Child to an array defined on Parent object?
You misunderstand how inheritance works in general: $classA is an instance of ClassA and has nothing to do with the instance $classB of ClassB you have generated.
An instance of ClassB inherits all public and protected properties and methods of ClassA but as long as you don't use them, you will not see them.
And all instances, whether from ClassA or from ClassB, are unrelated to each other, they only have the same "template" but each has its own property values.
In PHP, parent constructors aren't called automatically, to get your behaviour you need to do the following:
Class ClassB extends ClassA {
function __construct() {
parent::__construct();
$this->property[] = "ClassB.construct";
}
function SetB() {
$this->property[] = "ClassB.Set";
}
}
And, at most, you'll get this
Array
(
[0] => ClassA.construct
[2] => ClassB.construct
[3] => ClassB.Set
)
as SetA() is never invoked
When you invoked the sequence you described, $classA and $classB are two different instances, so you will never get what you expect.
To get what you want, you need to do this:
$classB = new ClassB();
$classB->SetB();
$classB->SetA();
print_r($classB->property);
That's really simple: why did you expect the parent constructor to run if you forgot to call it in ClassB? According to https://3v4l.org/keJ2a, this has not changed since PHP 5.0.0 and still works the same in recent PHP 7 versions
If you want to get the expected result then you need to change the code as per the PHP oops concept this will not work as you want.
You Updated Code
Class ClassA {
public $property = array();
function __construct() {
$this->property[] = "ClassA.construct";
$this->SetA();
}
public function SetA() {
$this->property[] = "ClassA.Set";
}
}
Class ClassB extends ClassA {
function __construct() {
parent::__construct();//invoke parent constructor
$this->property[] = "ClassB.construct";
}
function SetB() {
$this->property[] = "ClassB.Set";
}
}
$classB = new ClassB();
$classB->SetB();
print_r($classB->property);
Expected result:
Array
(
[0] => ClassA.construct
[1] => ClassA.Set
[2] => ClassB.construct
[3] => ClassB.Set
)
When parent::__construct(); invokes then it maintains $property array variable for child class also.
Note: As we know OOPS concept, every object has a different instance.

PHP - define static array of objects

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
)
)

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: How to list static fields/properties through reflection?

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);

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