Parent Object in php - php

is there a way to traverse an object to get the parent object data?
With "parent object" I don't mean the parent class, but literally object.
Here an example, in a javascripty world :-) :
$parent->test = "hello world!";
$parent->child = new B();
It would be great If I could access all the data from parent in the child object:
class B{
//I know this doesn't exists, but it's what I wanted do do
function B(){
$this->parent = $this->parent();
echo $this->parent->test; //it would ouput "hello world"
}
}
For now my solution is to pass the parent object to the child (as a reference) or to make the parent global.
Do you have any better solution?
Thanks!

There is no way to invoke
$parent->test = "hello world!";
$parent->child = new B();
and automatically have a reference to $parent in B.
Generally, there is four ways to structure your classes:
1. Aggregate the parent object via Injection, e.g.
class B
{
private $parent;
public function __construct($parent)
{
$this->parent = $parent;
}
public function setParent($parent)
{
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Use constructor injection when the object has to have a parent when it's created. This is a has-a relationship and it creates a very loose coupling. There is no hardcoded dependencies in B, so you can easily swap out the Parent instance, for instance with a Mock when UnitTesting. Using Dependency Injection will make your code more maintainable.
In your UseCase, you'd pass $parent to B when creating B:
$parent->child = new B($parent);
2. Use Composition
class B
{
private $parent;
public function __construct()
{
$this->parent = new Parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
This is also a has-a relationship, but couples the Parent class to B. It's also not an existing Parent instance, but a new instance. From the wording I find it somewhat odd to have a parent created by the child. Use this, when dependency is a class that is not considered to exist outside of the root class, but is part of the whole thing it represents.
For your UseCase, there is no way of doing $parent->child = new B(); and know what parent is when using this approach, unless $parent is a Singleton. If so, you could get the Singleton instance, e.g. Parent::getInstance() to achieve what you want, but note that Singletons are not everyone's favorite pattern, e.g. hard to test.
3. Use Inheritance
class B extends Parent
{
public function accessParent()
{
$this->someMethodInParent();
}
}
This way you create an is-a relationship. All public and protected methods and properties from the Parent class, (but not of a specific instance) will be available in B and you can access them via the $this keyword of the B instance.
For your UseCase, this approach is not working, as you don't have to have an instance of Parent at all, but B would encapsulate everything of Parent when it's created
$b = new B;
4. Use global keyword
class B extends Parent
{
private $parent;
public function __construct()
{
global $parent;
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
The global keyword imports global variables into the current scope. In general, you should avoid using the global keyword in an OO context, but use one of the other three methods above, preferably the first one. While it's a language feature, it's frowned upon - although it is the next closest thing to the first one, e.g.
$parent->child = new B();
Anyway, hope that helps.

Passing the parent to the child is the better solution. Though it's a somewhat undesirable symbiotic relationship.
Should B() have any knowledge of the object it's an attribute of? More than likely not. These are only loosely related via composition.
Why does B() need to be an attribute of it's parent? Do you need to have this implementation in B() or should it be part of the parent?

Maybe it can be useful in some case: it doesn't bring parent object to ChildClass very early in constructor, but a one step later. It plays with ability to intercept non-existing method:
class ParentClass
{
const CHILD_PROPERTY_NAME = 'child';
public $data = 'Some data';
public function
__set($property_name, $property_value)
{
if ($property_name == self::CHILD_PROPERTY_NAME)
{
$property_value->set_parent_object($this);
}
}
}
class ChildClass
{
private $parent_object = null;
public function
set_parent_object($object)
{
$this->parent_object = $object;
echo $this->parent_object->data;
}
}
$p = new ParentClass();
$p->child = new ChildClass();
This will output Some data

I'm pretty sure, that PHP does not have something like that.
Your solution of passing the parent-object to the child is the best solution, I think. You should consider to set your Parent-property only in the constructor of the child to prevent multiple parents from having the same child.

No.
You can access variables from the superclass using $this:
<?php
class A {
public function __construct()
{
$this->foo = 'hello';
}
}
class B extends A {
public function printFoo()
{
echo $this->foo;
}
}
$b = new B();
$b->printFoo();
?>

You can create collections of object children when you create the children. you create it trough the parent this way they cannot reference each other but you can access both parents and children trough the parent and trough the children...
class ChildObject
{
public $name;
}
class ParentObject
{
public $children = array();
public function new_child($text = 'my name is data')
{
$child = new ChildObject; // create a new child
$child->name = $text; // assign the name
$this->children[] = $child; // store it as part of this object
return $child; // return the new instance of Child
}
public function print_everything ()
{
foreach($this->children as $child) {
echo $child->name;
}
}
}
$parent = new ParentObject;
$child1 = $parent->new_child(); // this is a ChildObject not a ParentObject
$child2 = $parent->new_child('i am not data');
echo $child1->name; // 'my name is data'
echo $child2->name; // 'i am not data'
$child1->name = 'something else';
echo $child1->name; // 'something else'
$parent->print_everything(); // 'something else' and 'i am not data'
Therefore if you want to access a parent method or property, you should put that in the parent and not in the child. Remember that the parent is also an "instance" of its own class.

Related

How to pass properties between parent and child classes?

Ok, I know there are similar questions, but they don't quite answer my question. I have a rather long class and decided to break it up. The bulk of it is a set of functions determining whether or not to change a certain value (both in the parent class and the database). The issue I'm having is inheritance and I'm clearly not understanding.
The problem is that the properties in the parent class aren't determined until after certain functions have executed. I need those properties in the child class in order to update the properties in the parent class once the child has finished doing its thing. Because of this, a simple "new Child" won't work (or will it?), because the properties haven't been determined in the new parent created.
I'm trying NOT to instantiate another instance of the parent class in order to repopulate the properties again. But at the same time, I don't need to always instantiate the child class when the parent is instantiated.
Here's what I'm trying to do...
class parentClass
{
public $value1;
public $value2;
public $value3;
public function getValues()
{
$this->curValues();
$chi = new childClass();
$chi->updValues();
echo var_dump($this->value1, $this->value2, $this->value3);
}
public function curValues()
{
$this->value1 = 'first value';
$this->value2 = 'second value';
}
}
class childClass extends parentClass
{
public function updValues()
{
if (2 > 1) {
$this->value2 = 'blue value';
$this->value3 = 'third value';
}
}
}
$hmm = new ParentClass();
$hmm->getValues();
The output is
first value
second value
The intended output is
first value
blue value
third value
I feel like I'm overlooking something painfully simple. How can I achieve this? Or is my thought process completely left field?
You can't call a child's method from its parent, but you can call a parent method from a child.
Depending on what final outcome you are trying to achieve, you might try overriding one of the parent methods in the child class. For example:
class childClass extends parentClass
{
public function curValues()
{
$this->value1 = 'first value';
if (2 > 1) {
$this->value2 = 'blue value';
$this->value3 = 'third value';
}
}
}
And then create an instance of the child class instead of the parent class:
$hmm = new childClass();
$hmm->getValues();

PHP Sibling Class Inheritance

I'm a bit confused on whether or not this is possible. I've checked a couple of posts here on SO and they don't really explain what I'm looking for.
I have 3 classes. One main class and two classes extending that main class. (see code below). Is it possible to run a method in one of the two extended classes from it's sibling (the other extended class)?
If it's not possible, how can I change my code to accomplish what I'm doing in the example below?
DECLARATION
class A {
public function __construct() {
//do stuff
}
}
class B extends A {
private $classb = array();
public function __construct() {
parent::__construct();
//do stuff
}
public function get($i) {
return $this->classb[$i];
}
public function set($i, $v) {
$this->classb[$i] = $v;
}
}
class C extends A {
public function __construct() {
parent::__construct();
//do stuff
}
public function display_stuff($i) {
echo $this->get($i); //doesn't work
echo parent::get($i); //doesn't work
}
}
USAGE
$b = new B();
$c = new C();
$b->set('stuff', 'somestufftodisplay');
$c->display_stuff('stuff'); // <----- Displays nothing.
Your code shows an additional problem apart from the main question so there are really two answers:
No, you cannot run a method from a sibling class in another sibling class. If you need that, the method should be in the parent class. The same applies to properties.
You cannot use the value of a property from one object in another object, even if they are both of the same class. Setting a property value in one object sets its value only there as different objects can have the same properties with completely different values. If you need to share the value of a property between the objects and also be able to modify it, you should use a static property. In this case you would have to define that in the parent class, see my previous point.
So to make it work, you would need something like
class A {
private static $var = array();
public function get($i) {
return self::$var[$i];
}
public function set($i, $v) {
self::$var[$i] = $v;
}
}
class B extends A {
}
class C extends A {
public function display_stuff($i) {
echo $this->get($i); // works!
}
}
$b = new B();
$c = new C();
$b->set('stuff', 'somestufftodisplay');
$c->display_stuff('stuff');
An example.

php: issue with calling the parent method

<?php
class HTML
{
protected $name;
public $id;
private $with;
protected function basicAttribute()
{
return "name='$this->name' id='$this->id'";
}
}
Class HTML_div extends HTML
{
public function __construct($id , $name)
{
$this->id = $id;
$this->name = $name;
}
public function getDiv($content)
{
$basicAttribute = $this->basicAttribute();
echo "<div $basicAttribute >$content</div>";
}
}
$objDiv = new HTML_div("bloc_main" , 'avc');
$objDiv->getDiv('this is and example of inheritance in php');
Question:
If I change $basicAttribute = $this->basicAttribute(); to $basicAttribute = parent::basicAttribute();, It also works. So I wonder what is the difference between them? and which is the better way to call parent method?
In this exact circumstance, they do the same thing. However, it's generally better to use $this->basicAttribute().
What each of those calls does is this:
$this->basicAttribute() -- calls child's implementation of basicAttribute() if one exists, otherwise looks to the closest ancestor for an implementation (in this case there is only a parent and child, so it calls the parent)
parent::basicAttribute() -- calls closest ancestor's implementation (in this case again, the parent). This will ignore an implementation of basicAttribute() in the child class, so it is advisable to only use it if you override a parent function and want to explicitly call the parent.
It is quite simple, really. When you extend a class, the new class inherits all the attributes and methods from that class (with the exception of properties and methods that are private). The class that is extended is called the parent class, and the class that is extending is called the child class.
So, if we have a class that looks something like this:
HTML
basicAttribute()
and we extend it:
HTML_div extends HTML
basicAttribute() // This method is automatically inherited from HTML
// which means that you do not have to create it yourself
So, when you call parent::basicAttribute() from HTML_div you are really calling HTML's method.
I believe this example should explain it in a way that is easy to understand:
class A {
function test() {
echo 'A';
}
}
class B extends A {
function test() {
echo 'B';
}
function parentTest() {
parent::test();
}
}
$b = new B;
$b->test(); // 'B'
$b->parentTest(); // 'A'

Properties shared between child and parents class in php

class parents{
public $a;
function __construct(){
echo $this->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
parent::__construct();
}
}
$new = new child();//print 1
This code above print 1,which means whenever we create an instance of a child class,and assign value to properties inherited from its parent,the property in its parent class also has been assigned.But the code below shows different:
class parents{
public $a;
function test(){
$child = new child();
echo $this->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();//print nothing
Where I assign value to its child class and the parent apprently didn't have the value it assigned to its child class,why?
Thanks!
In the top example, since the construct function is being called from the child class, it is treating the object being used as if it were the child object that is just using a function in the parent class as if it were it's own.
In the bottom example you have two separate objects acting independently. The parent object has it's $a and so does the child, but they are not the same $a since they are contained in separate objects. so when you print $this->a in the parent class, it is referring to the parent's instance of $a whereas if you echo $a after setting $this->a =1 in the child class it would display the child's instance of $a.
Hope this cleared some stuff up for you.
You are mixing object composition and class inheritance.
Inheritance (realized through the extends keyword) defines an is a relationship.
Composition defines a has a relationship.
To illustrate this concept we will start with inheritance.
class Person {
public $name;
public function talk(){};
public function poop(){};
}
class Parent extends Person {
public function __construct($name) {
$this->name = $name;
}
}
class Child extends Person {
public function __construct($name){
$this->name = $name;
}
}
In this example we are defining a class of things called People. From that definition we are deriving two different subtypes of People, Parent and Child. When we subtype a class then the subtype gains it's own copy of all of the properties and has access to all of the methods defined in the base type, so without defining it a Child and Parent have a name and can both talk and poop by virtue of also being a person.
For example:
$parent = new Parent("Homer");
$child = new Child("Bart");
$parent->talk();
$child->poop();
Composition is used when you want to implement a has a relation ship. Lets revise our type definition of Parent.
class Parent extends Person {
public $children = array();
public function __construct($name) {
$this->name = $name;
}
public function addChild(Child $child){
$this->children[] = $child;
}
}
What we have now allowing if for a Parent to have a child.
$parent = new Parent("Homer");
$child = new Child("Bart");
$parent->addChild($child);
// now I can access homers first child
echo $parent->children[0]->name;
When you instantiate parent, the instance of child created extends the parent class with to test() function. However, that doesn't change the value of $a.
That happens, because you have two different instances, which have nothing in common(except the the inheritance..)
The behavior you except could be generated with inner classes - which php don't support.
If you want to share an var accros every instance, you have to make it static
class parents{
public static $a;
function test(){
$child = new child();
echo self::$a;
}
}
class child extends parents{
function __construct(){
self::$a = 1;
}
}
$new = new parents();
$new->test();
which isn't probably what you want. Or you tell exactly, where you want to change your var
class parents{
public $a;
function test(){
$child = new child();
echo $child->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();
It's because in the first example you instantiate child
$new = new child();//print 1
and in the second you instantiate parents
$new = new parents();
The second works the same as the first using $new = new child();
If you want to access $a by instantiating child() you need to do it like this:
class parents{
public $a;
function test(){
$child = new child(); //CHANGE HERE
echo $child->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();

PHP new static($variable)

$model = new static($variable);
All these are within a method inside a class, I am trying to technically understand what this piece of code does. I ran around in the Google world. But can't find anything that leads me to an answer. Is this just another way of saying.
$model = new static $variable;
Also what about this
$model = new static;
Does this mean I'm initializing a variable and settings it's value to null but I am just persisting the variable not to lose the value after running the method?
static in this case means the current object scope. It is used in late static binding.
Normally this is going to be the same as using self. The place it differs is when you have a object heirarchy where the reference to the scope is defined on a parent but is being called on the child. self in that case would reference the parents scope whereas static would reference the child's
class A{
function selfFactory(){
return new self();
}
function staticFactory(){
return new static();
}
}
class B extends A{
}
$b = new B();
$a1 = $b->selfFactory(); // a1 is an instance of A
$a2 = $b->staticFactory(); // a2 is an instance of B
It's easiest to think about self as being the defining scope and static being the current object scope.
self is simply a "shortcut name" for the class it occurs in. static is its newer late static binding cousin, which always refers to the current class. I.e. when extending a class, static can also refer to the child class if called from the child context.
new static just means make new instance of the current class and is simply the more dynamic cousin of new self.
And yeah, static == more dynamic is weird.
You have to put it in the context of a class where static is a reference to the class it is called in. We can optionally pass $variable as a parameter to the __construct function of the instance you are creating.
Like so:
class myClass {
private $variable1;
public function __construct($variable2) {
$this->variable1 = $variable2;
}
public static function instantiator() {
$variable3 = 'some parameter';
$model = new static($variable3); // <-this where it happens.
return $model;
}
}
Here static refers to myClass and we pass the variable 'some parameter' as a parameter to the __construct function.
You can use new static() to instantiate a group of class objects from within the class, and have it work with extensions to the class as well.
class myClass {
$some_value = 'foo';
public function __construct($id) {
if($this->validId($id)) {
$this->load($id);
}
}
protected function validId($id) {
// check if id is valid.
return true; // or false, depending
}
protected function load($id) {
// do a db query and populate the object's properties
}
public static function getBy($property, $value) {
// 1st check to see if $property is a valid property
// if yes, then query the db for all objects that match
$matching_objects = array();
foreach($matching as $id) {
$matching_objects[] = new static($id); // calls the constructor from the class it is called from, which is useful for inheritance.
}
return $matching_objects;
}
}
myChildClass extends myClass {
$some_value = 'bar'; //
}
$child_collection = myChildClass::getBy('color','red'); // gets all red ones
$child_object = $child_collection[0];
print_r($child_object); // you'll see it's an object of myChildClass
The keyword new is used to make an object of already defined class
$model = new static($variable);
so here there is an object of model created which is an instance of class static

Categories