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.
Related
I have an inheritance issue. Consider I have a parent class A and a derived class B from A and a derived Class C from A again.
Let's say, class B & C both override method seed() from class A. Also clases A & B & C all implement a static function seedAll().
My question is: How do I call seedAll for B & C from the seedAll function of A without explicitly specifying the class B & C, so that in the future, should I have a class D similar to class B & C, I need not modify the seedAll function of class A to call the seedAll functions of classes B, C & D.
abstract class A
{
public static function seedAll() {
//How do I call seedAll of all the derived classes of Seeder?
}
abstract protected function seed();
// // Common method
// public function printOut() {
// print $this->getValue() . "\n";
// }
}
class B extends A
{
private $name;
function __construct($name) {
$this->name = $name;
}
public static function seedAll() {
$seeder1 = new B("name1");
$seeder1 = new B("name2");
}
function seed() {
echo $this->name;
}
}
class C extends A
{
private $name;
function __construct($name) {
$this->name = $name;
}
public static function seedAll() {
$seeder1 = new C("name1");
$seeder1 = new C("name2");
}
function seed() {
echo $this->name;
}
}
See how to obtain all subclasses of a class in php for how to get all the subclasses. You can then loop over them and call their seedAll() methods.
abstract class A
{
public static function seedAll() {
$subclasses = getSubclassesOf("A");
foreach ($subclasses as $class) {
$class::seedAll();
}
}
abstract protected function seed();
// // Common method
// public function printOut() {
// print $this->getValue() . "\n";
// }
}
getSubclassesOf function:
function getSubclassesOf($parent) {
$result = array();
foreach (get_declared_classes() as $class) {
if (is_subclass_of($class, $parent))
$result[] = $class;
}
return $result;
}
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 want to build class that implement a lot of methods based on it's id,
so I want to have one class parent that implement the methods!
and when i want to use this class I will extend it and just override the id variable :
class parent
{
$id = "parent";
private __construct()
{
}
public static function create_instance()
{
$instance = new self();
return $instance;
}
public static function print_id()
{
echo $this->id;
}
}
class child extend parent
{
$id = "child";
}
$instance = child::create_instance();
$instance->print_id();
the result will be "parent", but I want the result to be child ?
How to do that ?
EDIT : I also tried this and got parent instead of child:
class parent1 {
private $id = "parent";
public function __construct() {
}
public static function create_instance() {
$instance = new static ();
return $instance;
}
public function print_id() {
echo $this->id;
}
}
class child extends parent1 {
private $id = "child";
}
$instance = child::create_instance ();
$instance->print_id ();
The problem is that the visibility of $id is private whereas it should be protected because print_id() is only defined on the parent; as such it can only reach its own $id.
class parent1 {
protected $id = "parent";
// ...
}
class child extends parent1 {
protected $id = "child";
}
The alternative is, of course, to override print_id() in the child class.
Currently when you call create_instance method on child class as a result instance of parent class is created not child class as you expect.
Use late static binding in parent class "create_instance" method:
public static function create_instance()
{
$instance = new static();
return $instance;
}
More details http://php.net/manual/en/language.oop5.late-static-bindings.php
we have two class A & B:
class A{
var $settings;
function getinfo(){
$settings['domain']="mydomain";
$settings['pass']="1234";
return $settings;
}
}
class B extends A{
$ads = A::getinfo();
function makeurl(){
return "template/".$ads['domain'];
}
}
now i have an instance of B in my page, but i need "pass" , maybe some code like this:
$theme=new B();
$mypass = $theme->A->getinfo;
echo $mypass[$pass];
I know this code is full of faults , but i could not write a better one. is there any solution to access to password without making an instance of A?
Yes. It is as simple as this:
$theme = new B();
$mypass = $theme->getinfo();
echo $mypass['pass'];
You can also improve your classes a bit:
class A
{
var $settings;
function getinfo()
{
$this->settings['domain'] = "mydomain";
$this->settings['pass'] = "1234";
return $this->settings;
}
}
class B extends A
{
function makeurl()
{
$this->getinfo();
return 'template/' . $this->settings['domain'];
}
}
Why not call the settings variable in A from the B instance since B is a subclass of A?
Try this code:
<?php
class A
{
var $settings;
function getinfo()
{
$settings['domain'] = "mydomain";
$settings['pass'] = "1234";
return $settings;
}
}
class B extends A
{
function makeurl()
{
$ads = $this->getinfo();
return "template/" . $ads['domain'];
}
}
$theme=new B();
$mypass = $theme->getinfo();
echo $mypass['pass'];
What about making settings a public static variable in A? By making it a class variable you won't need an instance of A.
class A {
public static $settings;
// getter and setter methods here
}
// code elsewhere
echo A::$settings['pass'];
Also because your class B extends A it inherits the methods and properties, so you could call
$theme = new B();
$mySettings = $theme->GetInfo();
if B extends A, all protected and public members of A are inherited into B, so you can access them directly.
class A {
protected $foo;
public function __construct() { $this->foo = 1; }
}
class B extends A {
public function bar() {
echo $this->foo;
}
}
$b = B();
$b->bar();
If I understand you correctly, you're pretty close:
$theme=new B();
$settings = $theme->getinfo();
$mypass = $settings['pass'];
echo $mypass;
I want to have a static method in a parent class that creates instances of whatever subclass i call this method on.
An example to make this more clear:
class parent {
public static method make_objects($conditions){
for (...){
// here i want to create an instance
// of whatever subclass i am calling make_objects on
// based on certain $conditions
}
}
}
class sub extends parent{
...
}
$objects = sub::make_objects($some_conditions);
As of php 5.3 you can use the static keyword for this
<?php
class A {
public static function newInstance() {
$rv = new static();
return $rv;
}
}
class B extends A { }
class C extends B { }
$o = A::newInstance(); var_dump($o);
$o = B::newInstance(); var_dump($o);
$o = C::newInstance(); var_dump($o);
prints
object(A)#1 (0) {
}
object(B)#2 (0) {
}
object(C)#1 (0) {
}
edit: another (similar) example
<?php
class A {
public static function newInstance() {
$rv = new static();
return $rv;
}
public function __construct() { echo " A::__construct\n"; }
}
class B extends A {
public function __construct() { echo " B::__construct\n"; }
}
class C extends B {
public function __construct() { echo " C::__construct\n"; }
}
$types = array('A', 'B', 'C');
foreach( $types as $t ) {
echo 't=', $t, "\n";
$o = $t::newInstance();
echo ' type of o=', get_class($o), "\n";
}
prints
t=A
A::__construct
type of o=A
t=B
B::__construct
type of o=B
t=C
C::__construct
type of o=C
I think you want something like this:
class parent {
public static function make_object($conditionns) {
if($conditions == "case1") {
return new sub();
}
}
}
class sub extends parent {
}
Now you can create an instance like this:
$instance = parent::make_object("case1");
or
$instance = sub::make_object("case1");
But why would you want all the sub classes to extend the parent? Shouldn't you much rather have a parent for your models (sub classes) and then a factory class, that creates the instances for this models depending on the conditions given?
Umm, wouldn't that be:
class sub extends parent {
public static function make_objects($conditions) {
//sub specific stuff here
//....
}
}
make the parent class an abstract class and make the parent method also an abstract
abstract static class parent {
abstract function make_method() {
// your process
}
}
class child extends parent {
public function __construct() {
parent::make_method();
}
}