php: issue with calling the parent method - php

<?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'

Related

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.

Call child method from parent class

I have a Class that is used as an extender by several other Classes, and in one instance, a method from the parent Class needs to call back to a method from the child Class. Is there a way of doing this?
I realise PHP contains abstract Classes and functions, but would require each child Class to have the declared abstract function(s), which I do not require in this case.
For example (these are examples, not real life) -
Class parent{
function on_save_changes(){
some_parent_function();
if($_POST['condition'] === 'A') :
// Call 'child_1_action()'
elseif($_POST['condition'] === 'B') :
// Call 'child_2_action()'
endif
some_other_parent_function();
}
function some_parent_function(){
// Do something here, required by multiple child Classes
}
}
Class child_1 Extends parent{
function __construct(){
$this->on_save_changes();
}
function child_1_action(){
// Do something here, only every required by this child Class
}
}
Class child_2 Extends parent{
function __construct(){
$this->on_save_changes();
}
function child_2_action(){
// Do something here, only every required by this child Class
}
}
You can do this by just simply calling the child method, e.g.:
if($_POST['condition'] === 'A') :
$this->some_parent_function();
$this->child_1_action();
However, you should avoid doing this. Putting checks in the parent that call methods only existing in a child class is a very bad design smell. There is always a way to do things in a more structured manner by utilizing well-known design patterns or simply thinking the class hierarchy through better.
A very simple solution you can consider is implementing all of these methods in the parent class as no-ops; each child class can override (and provide implementation for) the method that it's interested in. This is a somewhat mechanical solution so there's no way to know if it's indeed the best approach in your case, but even so it's much better than cold-calling methods that technically are not guaranteed to exist.
Try this:
class ParentClass{
private $childActionMethod;
public function on_save_changes(){
if(method_exists($this, $this->childActionMethod)) {
call_user_func_array(array($this, $this->childActionMethod), func_get_args());
}
else {
throw new Exception('Child Method has not been set');
}
}
protected function setChildActionMethod($methodName) {
$this->childActionMethod = $methodName;
}
}
class ChildClass1 extends ParentClass{
function __construct(){
$this->setChildActionMethod('child_1_action');
}
function child_1_action(){
echo('Hello First World<br />');
}
}
class ChildClass2 extends ParentClass{
function __construct(){
$this->setChildActionMethod('child_2_action');
}
function child_2_action(){
echo('Hello Second World<br />');
}
}
$child1 = new ChildClass1();
$child1->on_save_changes();
// Hello First World
$child2 = new ChildClass2();
$child2->on_save_changes();
// Hello Second World
The parent class has the protected method setChildActionMethod, callable by the children. When the children are instantiated, they tell the parent the name of the method they would like it to call on save.
If the method exists then it is called with any arguments, or it throws an exception (you can change the error handling).
I'm sure theres a name for this pattern, but I am unsure what it is called.
You may use "Template method" pattern, if you need to create some action sequence in parent that child classes should implement on their own but in some predefined manner. But you should avoid referring to future defined arbitrary methods.
In general: any method you use in your parent should be declared either as abstract or have default implementation. Children will override these methods.
abstract class parent{
function on_save_changes(){
some_parent_function();
some_child_action();
some_other_parent_function(); // added to follow changes of question
}
function some_parent_function(){
// Do something here, required by multiple child Classes
}
abstract public function some_child_action();
}
class child_1 Extends parent{
function some_child__action(){
if($_POST['condition'] === 'A') :
// Do something here, only every required by this child Class
endif;
}
}
class child_2 Extends parent{
function some_child_action(){
if($_POST['condition'] === 'B') :
// Do something here, only every required by this child Class
endif;
}
}

PHP - redefine method and call ancestor version of same method

I want to redefine a method, and call my ancestor's version of it, not my parent's.
Here is a short example:
// This class is autogenerated and I am not supposed to modify it.
class myParent extends myGrandparent {
function doSomething() {
doA();
doB();
doC();
parent::doSomething();
}
}
// Here is my code
class myClass extends myParent {
function doSomething() {
// doA(); // I don't want to do A anymore.
// doB(); // Neither B.
doC(); // But I want to keep doing C.
parent::doSomething(); // OOPS!! This does A and B (and C again)!
}
}
How can I call myGrandparent's method directly, instead of myParent's?
I disagree with the "you cannot do this" argument - You can do this with Reflection.
Consider the following class structure:
class A {
function foo() {
echo 'A';
}
}
class B extends A {
function foo() {
parent::foo();
echo 'B';
}
}
class C extends B {
function foo() {
parent::foo();
echo 'C';
}
}
When initialized with this:
$o = new C;
$o->foo();
Will print (as expected, seen in this demo):
ABC
The challenge is to remove the B from the output, effectively only executing A's foo() and C's foo(). So, lets drop into Reflection and grab A's foo() method, and invoke that on C's object. Now consider this alternative definition for C:
class C extends B {
function foo() {
$ref = new ReflectionClass( $this);
$parent = $ref->getParentClass()->getParentClass();
$parent->getMethod( 'foo')->invoke( $this);
echo 'C';
}
}
Now, you'll only get as output (as seen in this demo):
AC
Whether or not this is a "good practice", is up to the OP. I think I've demonstrated that it is possible to "skip" the implementation of B's function and call the grandparent function from the grandchild class.
Not sure what the use cases are, but unless I misunderstand the question/issue (quite possible), you can totally call any arbitrary ancestor (public or protected) method, irrespective of how many times it's been overridden in between, and even the default value of any ancestor member attribute (public or protected), even if that's been overridden too. For example, with the class hierarchy:
Papa > Mama > Baby > Infant, where both the method sayWhat() & instance variable $el are overridden in each descendent class, you can call any ancestor sayWhat method from Infant, and access a different ancestor default attribute value:
class Papa {
protected $el = 'PapaEl';
protected function sayWhat($className = null) {
if (!$className) {
$className = get_class($this);
}
$classVars = get_class_vars($className);
$localEl = $classVars['el'];
echo "<h2>What is PAPA!. El: [$localEl]</h2>";
}
}
class Mama extends Papa {
protected $el = 'MamaEl';
protected function sayWhat() {
echo "<h2>What is MAMA! El: [$this->el]</h2>";
}
}
class Baby extends Mama {
protected $el = 'BabyEl';
protected function sayWhat() {
echo "<h2>What is Lil' Baby!! El: [$this->el]</h2>";
}
}
class Infant extends Baby {
protected $el = 'InfantEl';
protected function sayWhat($className) {
Papa::sayWhat($className);
}
public function mySayWhat($className) {
$this->sayWhat($className);
}
}
$i = new Infant();
$i->mySayWhat('Mama');
Output:
What is PAPA!. El: [MamaEl]
Not sure what value it has, but if someone has the requirement, it seems very doable...
You really can't. You would either need to extend from myGrandParent directly, or you would need to rework the logic in MyParent to provide "pass-through" access to the myGrandParents method. For example, you could make a method on myParent like this:
function doSomethingGrandparent() {
parent::doSomething();
}
and then change your doSomething method in myClass like this:
function doSomething() {
parent::doSomethingGrandparent();
}
The answer is no, you cannot. The children redeclare the parent functionality of the method and completely override it.
I think static methods would be required, since you can't chain the parent:: keyword to work back to a "grandparent" class, so, parent::parent::foo( ) doesn't work.

Is there any polymorphism in PHP?

Suppose both base and son class have a method method_1,
and there's another method method_2 of base.
inside base::method_2,how can I point $this->method_1 to base::method_1 no matter whether $this is a instance of base or son?
If I understand you correctly, you want something like this:
<?php
class base {
public function method1() {
echo "base:method1\n";
}
public function method2() {
if(get_class($this) == 'base') {
$this->method1();
}
else {
parent::method1();
}
echo "base:method2\n";
}
}
class son extends base {
public function method1() {
echo "son:method1\n";
}
}
$obj = new son();
$obj->method2();
where the call to method2 would always use the base version of the method1.
The best way I could do it is as above, but this code won't work since base has no parent. I'm pretty sure what you're trying to do isn't possible.
This is the error you will get:
PHP Fatal error: Cannot access parent:: when current class scope has no parent in
This will do what you want. Props to dbers for the example code (even if his didn't quite work).
<?php
class base {
public function method1() {
echo "base::method1\n";
}
public function method2() {
if (get_parent_class($this) === FALSE) {
echo get_class($this)." has no parent\n";
$this->method1();
} else {
echo get_class($this)." has parent\n";
call_user_func(array(get_parent_class($this), 'method1'));
}
}
}
class son extends base {
public function method1() {
echo "son::method1\n";
}
}
$b = new base();
$b->method2();
$s = new son();
$s->method2();
?>
Outputs:
base has no parent
base::method1
son has parent
base::method1
Make the function private:
<?php
class A
{
public function __construct()
{
$this->foo();
$this->bar();
}
private function foo() { echo "A::foo()\n"; }
public function bar() { echo "A::bar()\n"; }
}
class B extends A
{
public function foo() { echo "B::foo()\n"; }
public function bar() { echo "B::bar()\n"; }
}
new B();
?>
The output is:
A::foo()
B::bar()
Yes it does. It's singular (one parent).
son->method_1 can add to or override ALL of base->method_1 functionality.
son->method_1 can simply add an additional function, and utilize the rest of the functionality of it's parent's instance of method_1
So calling $this->method_1 would use base->method_1, and son->method_1 as long as what you want to use from base isn't overridden in son.
If you call a method that doesn't exist in your subclass, PHP will traverse the class hierarchy until it finds an ancestor class which implements the function you want. This means that if your son class doesn't implement method_2, PHP will automatically look for the nearest ancestor which does. In your case, it will call method_2 of base as you want.
If you are overriding the method_2 in your son class, and you want to do your own implementation of method_2 and also call the base::method_2 implementation then you can use the parent keyword:
class son extends base {
public function method_2() {
parent::method_2();
//do son::method_2()-specific stuff here
}
}
You can't chain parent calls together, so if base was a subclass of GrandparentClass you couldn't do something like this:
parent::parent::method_2(); // trying to call grandparent::method_2
// but this call will fail
But you can directly refer to ancestor classes by name, so this would work:
GrandparentClass::method_2();
And just to take it a little further, there is also a function called class_parents() which returns an array of every ancestor class your class inherits from. This could help if you wanted to go back, say, two ancestors, but you didn't know its specific name for some reason, you could still call the function using eval().
For example, this code would call GrandparentClass::method_2() without directly referencing the class by name in your code:
$parents = class_parents($this);
eval(end($parents) . "::method_2();");
Hope that helps.

Is it proper for a parent class to reference a property that exists only in the child?

In the project my team is currently working on, we're modifying a commercial PHP application. The app is strewn with code where a parent class checks for and works with a property that doesn't exist in the parent class, like so:
class A
{
function doSomething()
{
if (property_exists($this, 'some_property'))
{
$this->some_property = $_REQUEST['val'];
}
}
}
class B extends A
{
protected $some_property;
function doSomething()
{
parent::doSomething();
}
}
We feel vaguely dirty having to modify this code; is this proper design? What are the ways (other than the obvious) something like this can be avoided?
You might consider abstracting the parent class. So the methods that the children must have are declared in the parent, but not implemented.
Relying upon methods that must exist in a subclass is not dirty, as long as you can declare them as abstract.
However, it is not good practice to rely on and manipulate properties outside of a class. It's best to use abstract setters, like this:
abstract class A
{
abstract protected function setSomeProperty($data);
public function doSomething()
{
$this->setSomeProperty($_REQUEST['val']);
}
}
class B extends A
{
private $some_property;
public function doSomething()
{
parent::doSomething();
}
protected function setSomeProperty($data)
{
$this->some_property = $data;
}
}
More info here: PHP Class Abstraction
However, since you said you're not allowed to modify the parent class, I would suggest making a subclass that acts as an Adapter to what the parent class "expects", and a class that you're able to design "properly".
You can create a virtual method hook in the parent class which can later be overridden by children.
I think it's more neat to create a sub-class, where all members have function doSomething(). In that case you don't create a not-working function in a parent class (with eventual hacks), but still have the general "super-function".
class A
{
}
class C extends A {
protected $some_property;
function doSomething()
{
$this->some_property = $_REQUEST['val'];
}
}
class B extends C
{
protected $some_property;
function doSomething()
{
parent::doSomething();
}
}

Categories