3

I have the following three classes:

class a
{ public $test; }

class b extends a { }
class c extends a
{
    function return_instance_of_b() { }
}

As you can see, both classes b and c derive from a. In the return_instance_of_b() function in c, I want to return an instance of the class b. Basically return new b(); with one additional restriction:

I need the data from the base class (a) to be copied into the instance of b that is returned. How would I go about doing that? Perhaps some variant of the clone keyword?

5
  • Perhaps this question about How to Cast Objects in PHP5 would be of interest to you. Commented Sep 22, 2011 at 5:49
  • When you do return new b();, the variables from base class a are available, since they inherit from class a, but there will be no data set in them (unless they're set in the constructor of class a or b. Where is the data supposed to come from? Should the new object for class b have the data copied from the current c object? Commented Sep 22, 2011 at 6:17
  • @nickb: Yeah, I would like the data from the base class copied from the current instance of c to the new instance of b. Commented Sep 22, 2011 at 6:43
  • @GeorgeEdison: See my answer below, I believe it achieves what you are looking for. Commented Sep 22, 2011 at 6:53
  • @GeorgeEdison this seems to be a bit smelly design. Why does c need to know that b exists? They should be substitutable (LSP). Commented Sep 22, 2011 at 8:08

2 Answers 2

2

You can use the get_class_vars function to retrieve the names of the variables you want to copy, and just loop to copy them.

The variables that are defined are protected so they are visible to get_class_vars in its scope (since c extends a), but not directly accessible outside the class. You can change them to public, but private will hide those variables from get_class_vars.

<?php
class a
{ 
    protected $var1;
    protected $var2;
}

class b extends a 
{
}

class c extends a
{
    function __construct()
    {
        $this->var1 = "Test";
        $this->var2 = "Data";
    }
    
    function return_instance_of_b() 
    {
        $b = new b();
        // Note: get_class_vars is scope-dependant - It will not return variables not visible in the current scope
        foreach( get_class_vars( 'a') as $name => $value) {
            $b->$name = $this->$name;
        }
        return $b;
    }
}

$c = new c();
$b = $c->return_instance_of_b();
var_dump( $b); // $b->var1 = "Test", $b->var2 = "Data
Sign up to request clarification or add additional context in comments.

Comments

0

I believe you can achieve this with some reflection. Not very pretty code, I'm sure there is a much more succinct method to achieve this but here you go.

class a
{ 
    public $foo;
    public $bar;

    function set($key, $value) {
        $this->$key = $value;
    }

    function get($key) {
        return $this->$key;
    }
}

class b extends a 
{ 
    function hello() {
        printf('%s | %s', $this->foo, $this->bar);
    }
}
class c extends a
{   
    public $ignored;

    function return_instance_of_b() {
    $b = new b();
    $reflection = new ReflectionClass($this);
    $parent = $reflection->getParentClass();
    foreach($parent->getProperties() as $property) {
        $key = $property->getName();
        $value = $property->getValue($this);
        $b->$key = $value;
    }

    return $b;
    }
}

$c = new c();
$c->set('foo', 'bar');
$c->set('bar', 'bar2');
$c->set('ignored', 'should be!');

$b = $c->return_instance_of_b();
$b->hello();
// outputs bar | bar2

Additionally you could use nickb's answer but instead of hard coding the class you could use get_parent_class

function return_instance_of_b() 
    {
        $b = new b();
        foreach(get_class_vars(get_parent_class(__CLASS__)) as $name => $value) {
            $b->$name = $this->$name;
        }
        return $b;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.