I have been searching for this since a couple of days but found no solution.
Here's my code:
// Main class
class My_Parent {
private $foo = '';
// The constructor is set. Now all extended classes will get it.
function __construct() {
var_dump( $foo );
}
function set_val( $value ) {
$this->foo = $value;
}
}
// Extended class
class My_Child extends My_Parent {
// Here's the problem. I've modified the constructor
function __construct() {
parent::set_val( 'bar' );
parent::__construct(); // I don't want to call the parent costructor again
}
}
new My_Child();
This just work fine but not as I expect. I don't want to modify the constructor so I need to call it again from the parent. Which looks weird. I'm going to make an extendable framework for my projects. So, this thing is annoying.
I do want something like this:
class My_Child extends My_Parent {
// Just set the value somehow. do not modify the constructor
$this::set_val( 'bar' );
}
new My_Child();
So that, I don't have to call the constructor again. But the code above throws a syntax error.
Any hope about this?
Just found a tricky solution.
First I've set up an empty function and called it in the constructor of parent class. Then I modified the variable through that function in extended class. The code looks like this:
// Main class
class My_Parent {
private $foo = '';
// The constructor is set. Now all extended classes will get it.
function __construct() {
// We open the portal so that the value can change
$this->portal();
// Then we use the value as we want
var_dump( $foo );
}
function set_val( $value ) {
$this->foo = $value;
}
// This function will play the role of constructor of extended classes
function portal() {
}
}
// Extended class
class My_Child extends My_Parent {
// We just use portal to set the value. Constructor is still untouched!
function portal() {
parent::set_val( 'bar' );
}
}
new My_Child();
This is working perfectly as I wanted. Everything is explained in comments.
Maybe you're over-thinking this. If you want to initialize the property with a constant value, you can simply declare it protected and override it in the subclass:
class MyParent {
protected $foo = 'bar';
// ...
public function getFoo() {
return $this->foo;
}
}
class MyChild extends MyParent {
protected $foo = 'baz';
}
echo (new MyParent())->getFoo(); // "bar"
echo (new MyChild())->getFoo(); // "baz"
Related
class Foo {
protected static $a = 1;
protected $b = 2;
public function func() { return 'foo' . static::$a . $this->b; }
}
class Bar extends Foo {
protected static $a = 3;
protected $b = 4;
public function func() { return 'bar' . static::$a . $this->b; }
}
$obj = new Bar();
$obj->func(); // returns of course 'bar34'
Is there any option in PHP to call func() from Foo class?
In C++ I would cast $obj to Foo and simply call func()
Bar* obj = new Bar();
Foo* obj2 = (Bar*) obj;
obj2->func(); // returns 'foo14';
If you want to get down and dirty with Reflection then it's possible, but I'd strongly argue that this shouldn't be used anywhere near any production code. If you've got an instance of a child class, then you've got it for a reason, and if it's overridden a parent method then that has also happened for a reason.
Assuming you already know all this, then with that disclaimer out of the way, this should work in any remotely recent version of PHP:
class Foo { public function func() { echo 'I am the parent'; } }
class Bar extends Foo { public function func() { echo 'I am the child'; } }
// Create instance of child class
$bar = new Bar;
// Create reflection class
$reflected = new ReflectionClass(get_class($bar));
// Get parent method
$method = $reflected->getParentClass()->getMethod('func');
// Invoke method on child object
$method->invokeArgs($bar, []);
// I am the parent
See https://3v4l.org/NP6j8
This to me looks like a design issue more than anything else.
However if I were to handle this in a way that were easily readable and without rethinking my design I would do:
<?php
class Foo {
public function func() { return 'foo'; }
}
class Bar extends Foo {
public function func() { return 'bar'; }
public function parentFunc() { return parent::func(); }
}
$obj = new Bar();
$obj->parentFunc(); // returns of course 'foo'
Loek's answer also works, but doesn't call the method on the objects parent. It just calls the method on the classes parent. It all depends on the functionality you are looking for.
You could also do something like:
<?php
class Foo {
public function func() { return 'foo'; }
}
class Bar extends Foo {
public function func($parent = false) {
if ($parent) {
return parent::func();
}
return 'bar';
}
}
$obj = new Bar();
$obj->func(true); // returns of course 'foo'
Which is similar but without the need for the extra method.
Personally though I feel this issue likely requires a rethink in code design more than a coding solution.
-- edit --
To elaborate on 'a rethink in code design', I would ask myself "Why do I need an object that has two methods with the same name, but different functionalities? Is this not a job for two different objects? Trace the issue backwards until you find the design issue. Or the point at which the decision needs to be made as to which object your framework requires.
This isn't exactly what I'd call pretty, but it works and is relatively similar to what you described for C++; It works by calling get_parent_class() and then abusing PHP's ability to create objects from strings.
<?php
class Foo {
public function func() { echo 'foo'; }
}
class Bar extends Foo {
public function func() { echo 'bar'; }
}
$obj = new Bar();
$obj->func(); // Prints 'bar'
$parentClassString = get_parent_class($obj);
$newObj = new $parentClassString; // Gotta love PHP for magic like this
$newObj->func(); // Prints 'foo'
See this snippet to see it in action.
EDIT
It's a lot of work, but you could use so called Late Static Binding, perhaps more clearly explained in Jokerius's answer here. This requires you to write a crapload of custom code though, which I don't think is preferential. Overall the short answer seems to be: it isn't really possible.
I don't know should it help you but try to add this function in Bar class
public function callParent($function){
return parent::$function();
}
and call
echo $obj->callParent("func");
[UPDATED]
Also you can write cast function yourself
something like this
public function castAs($newClass) {
$obj = new $newClass;
foreach (get_object_vars($this) as $key => $name) {
$obj->$key = $name;
}
return $obj;
}
I have 2 classes where parent is inherited by child.
class parentClass
{
private $table_name='';
public function __construct($argument)
{
$this->table_name=$argument;
echo $this->table_name;
}
}
class child extends parentClass
{
private $table="student";
public function __construct()
{
parent::__construct($this->table);
}
}
There is some thing like this below that has to be used but I am unable to understand how and why.
$args = func_get_args();
call_user_func_array(array($this, 'parent::__construct'), $args);
Help me as
What should be the correct code to achieve the correct logic
and please support it with a reference to gain a better understanding.
Not a direct answer, but if I read the code correctly, you don't really want to pass a variable / value to the constructor. Instead you want to pass a fixed class property like a table name.
In that case you could use a constant in the child class and set that in the parent's constructor. The child class would not need a separate constructor if that is all you want to do.
So something like:
class parentClass
{
private $table_name;
function __construct() {
$this->table_name = static::TABLE;
echo $this->table_name;
}
}
class childClass extends parentClass
{
const TABLE = "student";
}
$obj = new childClass();
I'm absolutely sure this has been asked before, but I cannot find it anywhere.
So I have two classes. A and B
class classA
{
public $var1;
public $classbVar;
public function init()
{
// This is here because other script is run before it is called
// in the live code.
// it basically checks that the file exists. There is a reason for this.
if (file_exists('classB.php'))
{
require_once('classB.php');
}
else
{
echo "An error has occurred loading the second class.";
}
$this->var1 = "something";
$this->classbVar = new classB
echo $this->classbVar->doSomething();
}
}
In a separate file
class classB extends classA
{
public function doSomething()
{
echo $this->var1;
}
}
In a third file, I'm calling classA and running the init function. This is not real code, but identical to what I have written.
So why doesn't this work. if I VAR_DUMP I get null.... What have I done wrong or misunderstood?
LET ME BE MORE CLEAR:
There is a third file which calls classA as below;
require_once('classA.php')
$classA = new classA;
$classA->init();
My apologies for any confusion, I did this on the fly a little bit, as I am sure I am missing something simple here. Surely the way I am trying to do this will work somehow.
There are 2 problems here that cause your output to be null:
You are generating a new $classA object and any values you set on that, will not automatically be set on the $classbVar object as that is a completely different object of a class that just extends the A class, not the $classA object you have just generated. With the exception of a static property of course...
If you want to set the value of a property in an object, you need $this->var1 instead of $var1. Note if you set the value in your $classA object, it is still not set for the $classbVar object.
Put require_once above class declaration (this is not big issue but it's more clear)
Assign variables to class properties because they way you did the scope of them is only within the method.
$var1 = "something";
should be changed to
$this->var1 = "something";
Also the class values are not shared unless they are declared as static. So to access the properties from parent class you can do following:
class classA
{
public $var1;
public function init()
{
$this->var1 = "something";
}
}
// other file
require_once("A class location");
class classB extends classA
{
public function doSomething()
{
echo $this->var1;
}
}
$b = new classB();
$b->init();
$b->doSomething();
or more clean way:
class A
{
protected $var1;
public function __construct()
{
$this->var1 = "something";
}
}
// other file
require_once("A class location");
class B extends A
{
public function doSomething()
{
return $this->var1;
}
}
$b = new B();
echo $b->doSomething();
// or shorter syntax
echo {new B()}->doSomething();
Instead of using require_once() it's better to use PSR-4 autoloader.
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.
Here's some working code:
class A {
public $Foo;
public function GetFoo() {
$this->Foo = 'Bar';
}
}
class B extends A {
function __construct() {
$this->GetFoo();
echo $this->Foo;
}
}
$b = new B(); // Outputs "Bar"
Is there any way I can make this "prettier" (i.e. without the A::GetFoo() method)? I would've thought that wrapping the population of the $this->Foo inside a A::__construct() would work, but it doesn't.
Just to wrap it up, here's what I want: class A instantiates my DB object and that object is usable for every child class of A.
Perhaps you're overriding the parent's constructor without calling in from B?
class A {
protected $Foo = null;
public function __construct() {
$this->Foo = 'Bar';
}
}
class B extends A {
public function __construct() {
parent::__construct();
echo $this->Foo;
}
}
From the PHP manual:
"Class properties must be defined as
public, private, or protected. If
declared using var without an explicit
visibility keyword, the property will
be defined as public."
So, your class B can see $this->Foo. You don't have to call GetFoo() first. You must, however, call the parent constructor first if you need to reference $this->Foo inside of your constructor for class B.