Why I am able to use properties in constructor function without being defined in the class, Please read my code below.
<?php
class TV
{
public function __construct($m, $v)
{
$this->model = $m;
$this->volume = $v;
}
}
$tv_one = new TV("Samsung", 6);
echo $tv_one->model."<br><br>";
echo $tv_one->volume;
?>
Have a look at this code also. I am able to share private property outside the class. Just go throuh this code-
<?php
class TV
{
private $model = "Samsung";
private $volume = 2;
public function volumeUp()
{
return $this->volume++;
}
public function volumeDown()
{
return $this->volume--;
}
public function __construct($m, $v)
{
$this->model = $m;
$this->volume = $v;
}
}
class PlasmaTv extends TV
{
public $plasma = true;
public function hello()
{
return "I am new " . $this->model . " and my default volume is " . $this->volume . ".";
}
public function __construct($m, $v, $p)
{
$this->model = $m;
$this->volume = $v;
$this->plasma = $p;
}
}
$plasma = new PlasmaTv("Soni", 6, true);
echo $plasma->model."<br><br>";
echo $plasma->volume."<br><br>";
echo $plasma->plasma;
echo $plasma->hello();
?>
PHP doesn't require you to declare properties. Just assigning to a property will create it as a public property. So when the first constructor does:
$this->model = $m;
that creates a model property in the object.
In your PlasmaTv class, the model and volume properties are not the same as the ones in the parent class TV, because the properties in the parent are private and can't be accessed in the child. If you do:
$plasma->volumeUp();
echo $plasma->volume;
it will print 6, not 7, because volumeUp() incremented a different property than the public property in PlasmaTv.
If you want to share the properties between the child and parent, declare them protected. But then you won't be able to use $plasma->volume from outside the classes.
Related
In PHP (Symfony 3);
I want to reference an existing object A in another object B which class extends the one of object A, like this:
class A {
private $property1;
private $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
}
class B extends A {
private $property3;
public function __construct($objectA,$p3){
$this = $objectA;
$this->property3 = $p3;
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
This does not work and throw the following error at the statement $this = $objectA:
Compile Error: Cannot re-assign $this
Which are documented and explain there and there. I am looking for a workaround.
You must call parent constructor and also make property1 and property2 visible in class B
<?php
class A {
private $property1;
private $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
public function getProperty1()
{
return $this->property1;
}
public function getProperty2()
{
return $this->property2;
}
}
class B extends A {
private $property3;
public function __construct($objectA,$p3){
parent::__construct($objectA->getProperty1(), $objectA->getProperty2());
$this->property3 = $p3;
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
See it live here: http://sandbox.onlinephpfunctions.com/code/705bf1827da2bdf10f8d961ee1cb6fbdd88bc663
As an alternative, you could use __call magic method to forward all cals to class A:
<?php
class A {
private $property1;
private $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
}
class B extends A {
private $property3;
private $a;
public function __construct($objectA,$p3){
$this->a = $objectA;
$this->property3 = $p3;
}
public function __call($name, $arguments)
{
return call_user_func_array(array($this->a, $name), $arguments);
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
Based on how to clone object to child class in php
Using get_object_vars on the parent object, you can get an array of properties keys and values. You can then loop through them and assign them to the child object:
<?php
class A {
protected $property1;
protected $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
}
class B extends A {
private $property3;
public function __construct($objectA,$p3){
//$this = $objectA;
$objValues = get_object_vars($objectA); // return array of object values
foreach($objValues AS $key=>$value)
{
$this->$key = $value;
}
$this->property3 = $p3;
echo $this->property1;
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
This does not work with private properties, they need to be at least of protected level.
I ended up managing it like that:
class B extends A{
public function __construct($objectA){
foreach($this as $k => $v){
if(isset($objectA->{$k})){
$this->{$k} = &$objectA->{$k};
}
}
}
}
Compare to #Antony answer, notice it has & in front of $objectA->{$k}: $this->{$k} = &$objectA->{$k};. As I understood it, with &, any change on $objectB of properties belonging to the extended class A applies to $objectA.
I am aware it is not perfect and quite hacky but it does the job I need. Thanks for the input given by everybody.
I have this class
class TableInvoices extends WP_List_Table {
function prepare_items() {
$sumOwed = 'Anything';
$sumTotal = 'Something';
}
}
How can I echo $sumTotal outside the class ?
Thanks
EDIT:
#Eisa Adil solutions worked very well, also this worked:
class TableInvoices extends WP_List_Table {
public $sumOwed;
public $sumTotal;
function prepare_items() {
$sumOwed = 'Anything';
$sumTotal = 'Something';
$this->sumOwed = $sumOwed;
$this->sumTotal = $sumTotal;
}
}
$sum = new TableInvoices();
$sum->prepare_items();
echo $sum->sumOwed . '<br>';
echo $sum->sumTotal;
class TableInvoices extends WP_List_Table {
public static $sumTotal;
public function prepare_items() {
sumOwed = 'Anything';
self::sumTotal = 'Something';
}
}
echo TableInvoices::$sumTotal;
Use static variables. This would help you access methods and properties without instantiating an object.
Obviously it'll give undefined so you'll need to instantiate an object and run prepare_items() or statically access that too.
class TableInvoices extends WP_List_Table {
public static $sumTotal;
public static function prepare_items() {
self::sumTotal = 'Something';
}
}
TableInvoices::prepare_items();
echo TableInvoices::$sumTotal;
I created a parent class (A) and modified some of its public and protected properties.
I created a child class (B) that extends A.
I can see the parent properties at B instance after creating it.
Problem is: The inherited properties of B have the default values of A, from before I modified them.
I want B to hold the modified values of the inherited properties.
How?
class Dashboard {
protected $testBusinessesIds = '';
public function test_bids($a){
$this->testBusinessesIds = $a;
}
}
class DashboardDBHelper extends Dashboard{
protected $withoutTestBids = '';
public function __construct(){
if($this->testBusinessesIds != '')
$this->withoutTestBids = " AND B.`id`";
}
}
$d = new Dashboard();
$d->test_bids(23);
$dh = new DashboardDBHelper();
print_r($dh->withoutTestBids);
I see: '' instead of 'AND B.id'
You may need to put your property as static. Here's an example:
class A {
protected $value = 1;
protected static $staticValue = 1;
public function printStatic() {
self::$staticValue++;
echo self::$staticValue;
}
public function printNonStatic() {
$this->value++;
echo $this->value;
}
}
class B extends A {
public function printStatic() {
echo self::$staticValue;
}
public function printNonStatic() {
echo $this->value;
}
}
$a = new A();
$b = new B();
/* Class A */
$a->printStatic(); // 2
$a->printNonStatic(); // 2
/* Class B */
$b->printStatic(); // 2
$b->printNonStatic(); // 1
Static variables does not share the same class/object so if you modify the value it will be changed everywhere.
Consider following example:
<?php
class p{
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknow properties here ..
function test(){
echo $this->name;
}
function get_p_as_json(){
// how can i get json of this class which contains only public properties ?
// {"name":"jimmy","sex":"male"}
}
}
$p = new p();
$json = $p->get_p_as_json();
echo $json;
Question: How to get all public properties of a class as JSON?
You just create another class q extends from p. And then the code looks like following:
class p {
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknown properties here ..
function test(){
echo $this->name;
}
}
class q extends p {
function get_p_as_json($p) {
return json_encode(get_object_vars($p));
}
}
$q = new q();
$p = new p();
$json = $q->get_p_as_json($p);
echo $json;
$a = array();
$reflect = new ReflectionClass($this /* $foo */);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
/* here you can filter for spec properties or you can do some recursion */
$a[ $prop->getName() ] = $a[ $prop->getValue()];
}
return json_encode($a);
Since the public members can also be accessed outside of the class..
Accessing members outside of the class
$p = new p();
foreach($p as $key => $value) {
$arr[$key]=$value;
}
Demo
Accessing the public members within the class by making use of ReflectionClass
<?php
class p{
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknow properties here ..
function test(){
echo $this->name;
}
function get_p_as_json(){
static $arr;
$reflect = new ReflectionClass(p);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
$arr[$prop->getName()]=$prop->getValue($this); //<--- Pass $this here
}
return json_encode($arr);
}
}
$p = new p();
echo $json=$p->get_p_as_json();
Demo
The best way to do this would not be to call a method of the class, per se.
However, you could initiate the following:
$myPublicMethodsInJson = json_encode(get_class_methods($p));
However, you would not be able to call get_class_methods from within the class because it will return ALL of your methods, private and public. When you call it from outside of the class it will only return the public methods.
I am using Reflections to adjust various values in objects, and I have an object who's parent I need to adjust.
For example:
class Ford extends Car
{
private $model;
}
class Car
{
private $color;
}
I can easily use Reflection to change the model, but how can I separate the parent from the child, so that I can use Reflection on the parent?
Some psuedo code for what I'm hoping is possible:
$ford = new Ford();
$manipulator = new Manipulator($ford);
$manipulator->set('model','F-150');
$manipulator->setParentValue('color','red');
class Manipulator
{
public function __construct($class) {
$this->class = $class;
$this->reflection = new \ReflectionClass($class);
}
public function set($property,$value) {
$property = $this->reflection->getProperty($property);
$property->setAccessible(true);
$property->setValue($this->class,$value);
}
public function setParentValue() {
$parent = $this->reflection->getParent();
$property = $this->reflection->getProperty($property);
$property->setAccessible(true);
// HOW DO I DO THIS?
$property->setValue($this->class::parent,$value);
}
}
Gist of the question:
In this case, how can I change the $color from outside the object altogether?
Is there something like Ford::parent() or get_parent_object($ford) available?
Note
The objects used above are not the exact scenario, but just used to illustrate the concept. In the real world case, I have a parent/child relationship, and I need to be able to access/change values in each from the outside.
ANSWER
Please check my answer below...I figured it out.
After extensive review, I have found that I can't access the parent of an object AS AN OBJECT outside of the object itself.
However, using Reflections, I was able to solve the example posted above:
<?php
class Car
{
private $color;
public function __construct()
{
$this->color = 'red';
}
public function color()
{
return $this->color;
}
}
class Ford extends Car
{
}
$ford = new Ford();
echo $ford->color(); // OUTPUTS 'red'
$reflection = new ReflectionClass($ford);
$properties = $reflection->getProperties();
foreach($properties as $property) {
echo $property->getName()."\n>";
}
$parent = $reflection->getParentClass();
$color = $parent->getProperty('color');
$color->setAccessible(true);
$color->setValue($ford,'blue');
echo $ford->color(); // OUTPUTS 'blue'
See it in action here: http://codepad.viper-7.com/R45LN0
See get_parent_class(): http://php.net/manual/en/function.get-parent-class.php
function getPrivateProperty(\ReflectionClass $class, $property)
{
if ($class->hasProperty($property)) {
return $class->getProperty($property);
}
if ($parent = $class->getParentClass()) {
return getPrivateProperty($parent, $property);
}
return null;
}
Here is the static version of the function I answered your other question with:
function getProperties($object) {
$properties = array();
try {
$rc = new \ReflectionClass($object);
do {
$rp = array();
/* #var $p \ReflectionProperty */
foreach ($rc->getProperties() as $p) {
$p->setAccessible(true);
$rp[$p->getName()] = $p->getValue($object);
}
$properties = array_merge($rp, $properties);
} while ($rc = $rc->getParentClass());
} catch (\ReflectionException $e) { }
return $properties;
}