Mother class attribute return NULL - php

I am working on a PHP Object and I have a problem, I try to call an attribute (which is an object) from a mother class, and it's null. I'll show you my problem:
Class A {
protected $attribute;
public function __construct() {
$this->attribute = new C();
}
public function foo() {
new B();
}
}
Class B extends A {
public function __construct() {
var_dump($this->attribute) // show "NULL"
}
}

You are overriding A's constructor in B, which means that A's constructor never gets called, and consequently, $attribute never gets set. If you want to execute A's constructor in B, you need to do so explicitly:
class B extends A {
public function __construct() {
parent::__construct(); // This is required if you want to execute A's constructor
var_dump($this->attribute);
}
}

Related

How can I set an object in a parent class and use it in child classes?

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.

Redirecting a request to another class

I have three classes. Class A, Class B, Class C. What I am trying to do, send a request to Class B form Class A, and Class B must redirect that request to Class c.
May be a simple example from below will give a certain idea.
class classa {
public function __construct() {
$obj_classb = new classb;
$obj_classb -> someRequest(); // This request must go to Class B and query the Class C
}
}
class classb {
//This class must do something, which is going to redirect any sorts of request it receives to the next classc
}
class classc {
public function someRequest() {
//do whatever
}
}
Any Idea?
You can create a "redirector" class by overriding the __call method like this:
class classb {
private $obj_classc;
public function __construct() {
$this->obj_classc = new classc;
}
public function __call($name, $arguments) {
return call_user_func_array(array($this->obj_classc, $name), $arguments);
}
}
Of course this will "forward" only method calls; if you are interested in forwarding property getters/setters etc you will have to override more magic methods.
Choosing the forwarding target can also be arranged (in this example it's just an automatically-created classc object; but you can pass it as a parameter in the constructor or provide it in any other way you choose).
Update: Magic functions you need to override to forward property accesses:
public function __set($name, $value) {
$this->obj_classc->$name = $value;
}
public function __get($name) {
return $this->obj_classc->$name;
}
public function __isset($name) {
return isset($this->obj_classc->$name);
}
public function __unset($name) {
unset($this->obj_classc->$name);
}

executing __constructor() in php inheritance

In php, if A extends B, does B's _constrctor() get executed automatically when A is instantiated? or do I have to call parent->_constructor()?
PHP looks for the top-most (closest to the instantiated class) __construct method it can find. It then executes that one only.
Class A {
public function __construct() {
echo "From A";
}
}
Class B extends A {
public function __construct() {
echo "From B";
}
}
Class C extends A {}
Class D extends B {}
Class E extends B {
public function __construct() {
echo "from E";
}
}
new A(); // From A
new B(); // From B
new C(); // From A
new D(); // From B
new E(); // From E
And parent accesses the next one up the list until there are no more (at which point it'll generate an error)...
So, in class E, running parent::__construct() would execute class B's constructor.
In class B, running parent::__construct() would execute class A's constructor.
In class A, running parent::__construct() will generate an error since there is no constructor...
The answer is you have to call it.
A simple test:
class A {
public function __construct() {
echo 'A';
}
}
class B extends A {
public function __construct() {
echo 'B';
}
}
$ab = new B();
Should tell you all you need to know.
You need to call "parent::__construct()" from A's constructor, if A has one. Otherwise you don't need to.
class A {
function __construct() {
echo 5;
}
}
class B_no_Constructor extends A {
}
class B_with_Constructor extends A {
function __construct(){}
}
//try one
//new B_no_Constructor; //outputs 5
//new B_with_Constructor; //outputs nothing

Making a superclass object become a subclass object in PHP5

<?php
class A{
//many properties
protected $myProperty1;
protected $myProperty2;
protected $myProperty3;
public function __construct(){
$this->myProperty1='some value';
$this->myProperty2='some value';
$this->myProperty3='some value';
}
public function getProperty1(){
return $this->myProperty1;
}
public function getProperty2(){
return $this->myProperty2;
}
public function getProperty3(){
return $this->myProperty3;
}
//edited: I added some setters, meaning that the object returned from the functions may already have these properties altered
public function setProperty1($p){
$this->myProperty1=$p;
}
public function setProperty2($p){
$this->myProperty2=$p;
}
public function setProperty3($p){
$this->myProperty3=$p;
}
}
class B extends A{
private $myProperty4;
public function __construct(A $a){
$this=$a; //this line has error,it says $this cannot be re-assigned
$this->myProperty4='some value';
}
public function getProperty4(){
return $this->myProperty4;
}
}
//$a = new A();
$a = someClass::getAById(1234); //edited: $a is returned by a function (I cannot modify it)
$b= new B($a); //error
?>
I'd like to create a B's object by passing an A's object to B's constructor, as you can see, I cannot re-assign the $this variable. I am not allowed to modify class A, when there are many properties in A, it'd be tedious for me to do things like this in B's constructor:
public function __construct(A $a){
parent::__construct();
$this->myProperty1=$a->getProperty1();
$this->myProperty2=$a->getProperty2();
$this->myProperty3=$a->getProperty3();
$this->myProperty4='some value';
}
My question is that, how can I safely create an object of class B using an A's object with minimal amount of coding?
class A
{
public $property = 'Foobar';
}
class B extends A
{
public function __construct()
{
echo $this->property; // Foobar
}
}
Am I missing something? It sounds like you're trying to force OOP to do something it's not intended to do, or you're having trouble understanding inheritance.
Every public or protected method and property from class A is available in class B. Either by directly referencing it (as in my example) or by using the parent:: syntax.
EDIT
(Author clarified question)
If class A's properties are accessible, you could use something like the following to copy them down to class B
class B
{
public function __construct()
{
$a = new A(); // Or however A is instantiated
foreach(get_object_vars($a) as $key => $value)
{
$this->$key = $value;
}
}
}
Since B extends A, why not just create B to begin with? If you need to initialize some extra properties, you can over-ride the constructor like this:
class B extends A {
public function __construct(){
parent::__construct(); //calls A's constructor
$this->Bproperty='somevalue';
}
}
If that's not good enough, then you might want to look at Reflection.

class initiation with php

I have a class which initiates another class, i'm not concerned with having a reference to the object i only need the method and have to pass in new parameters.
class A {
__set .....
}
class B extends A {
$anotherA = new A;
$anotherA->myName = 'stackoverflow';
}
in short i'd like to have class B extend A, init a new instance of A but i don't want to have to type "new" everytime, i've seen the following syntax:
B::A // something like that
but not sure if how to use it or if that would do what i'm trying to do?
What you could do is define a static method on the class that returns the new instance. It's basically a 'shortcut', but it does exactly the same in the background.
class C {
public static function instance()
{
return new C();
}
public function instanceMethod()
{
echo 'Hello World!';
}
}
Now you can call it like:
C::instance()->instanceMethod();
Here are some examples of static functions - they can be called without using 'new A' or 'new B'.
class A {
static function message($msg = 'I am Alpha') {
echo "hi there, $msg\n";
}
}
class B {
static function message() {
A::message("I am Beta");
}
}
A::message();
B::message();
I would create the instance of A in B's constructor, then you can instantiate B using either its constructor or static B::create(), which just acts as a shortcut. You could make the constructor private if you wanted all instantiation go through create().
class A {
// __set .....
}
class B extends A {
public function __construct() {
parent::__construct();
$anotherA = new A;
$anotherA->myName = 'stackoverflow';
}
public static function create() {
return new self();
}
}
new B();
B::create();
Since you are extending A in B, you could call the method of class A:
class B extends A {
public function someMethod() {
parent::someMethodName();
}
}
Alternatively, you could create a static method in the class:
class A {
public static function someStaticMethod() { ... }
}
A::someStaticMethod();
If you really want a new instance of A, you have to use the new operator. That's what it is for.

Categories