0

I've seen a few questions with really similar titles but they where irrelevant to my specific problem.

Basically, I want to access the variables from my core class in a class which extends core, but things seem to be quite complicated compared to other examples. I am using a MVC framework. I've simplified the code below to remove anything that was irrelevant.

index.php

// Load the core
include_once('core.php');
$core = new Core($uri, $curpath);
$core->loadController('property');

core.php

class Core
{
    public $uri;
    public $curpath;

    function __construct($uri, $curpath)
    {       
        $this->uri = $uri;
        $this->curpath = $curpath;
    }


    // Load the controller based on the URL
    function loadController($name)
    {       
        //Instantiate the controller
        require_once('controller/'.$name.'.php');
        $controller = new $name();
    }


}

property.php

class Property extends Core
{
    function __construct()
    {
        print $this->curpath;
    }   
}

Printing $this->curpath just returns nothing. The variable has been set but it is empty. If I print $this->curpath inside core.php it prints fine.

How can I access this variable?

10
  • $this means the current object, try base keyword Commented Jun 20, 2012 at 11:24
  • 3
    You need to call parent::__construct($uri, $curpath) in the subclass constructor. It won't be called implicitly. Commented Jun 20, 2012 at 11:24
  • @Michael - Is there no other way of storing the $uri and $curpath varibles in the core class so I can access them in the property class?If I had the values of $uri and $curpath available, your suggesgion would be redudnant because I would already have the variables there for use. Commented Jun 20, 2012 at 11:29
  • 2
    What you're doing here is very strange. You see, you're creating an instance of Core and inside it you're creating a new instance of Property extending Core but it will not "extend" the instance. I'm not sure how to explain this, but I think someone else will notice this and explain it better. Commented Jun 20, 2012 at 11:33
  • 1
    @Tommo Those properties are instance variables of the core class. The subclass knows nothing of the state of its parent class even if it was instantiated from within it. If those properties are to be set in the constructor, they need to be passed to the constructor. Commented Jun 20, 2012 at 11:34

3 Answers 3

6

You are doing it wrong tm

  1. You should be utilizing an autoloader, instead of including files with each class manually. You should learn about spl_autoload_register() and and namespaces, and how to utilize both of them.

  2. Do not generate output in the __construct() methods. That's an extremely bad practice

  3. The variables are still there. That is not the problem. In PHP, when you extend a class, it does not inherit the constructor.

  4. You do not understand how inheritance works. When you call method on instance of extended class it will not execute parent class's method , before calling extended class's methods. They get overwritten , not stacked.

  5. Object variables should not be exposed. You are breaking the encapsulation. Instead og defining them as public you should use protected.

  6. You should extend classes of they are different type same general thing. The extends in PHP means is-a. Which means that, when you write class Oak extends Tree, you mean that all the oaks are trees. The same rule would mean, that in your understanding all Property instances are just a special case of Core instances. Which they clearly ain't.

    In OOP, we have principle. One of which is Liskov substitution principle (shorter explanation). And this is the thing your classes are violating.

Sign up to request clarification or add additional context in comments.

3 Comments

1. I will look into those functions, but my system isn't very complicated so I don't think I need them. 2. I don't, my example was a simplified case (as I said). 3. I know. 4. Don't tell me that I don't understand something, I already knew this. 5. Thanks I will research this further. 6. You're getting too theoretical, the core class is full of functions required by all my other classes so it works just fine. Your post just makes you sound like a rude elitist.
@Tommo Don't ask for help then bristle when someone explains how the things you're currently doing are sub-optimal. Eschewing spl_autoload_register for manual includes all over an application is certainly sub-optimal, but you probably already knew that. This answer is right on.
Other than the fact that most of what was said was irrelevant to my problem and reiterated things that I already knew, there are many ways to provide help without coming across as an elitist snob.
0

The problem, I think, lies here:

If you consider a simple inheritance like this one:

class Dog{
    public $color;

    public function __construct($color){
        $this->color = $color;
    }
}

class TrainedDog extends Dog{
    public $tricks;

    public function __construct($color, $tricks){
        $this->tricks = $tricks;

        parent::__construct($color);
    }
}

//Create Dog:
$alfred = new Dog('brown');

//Create TrainedDog
$lassie = new TrainedDog('golden',array('fetch'));

In this example $alfred is a brown dog and $lassie is a golden dog. The two instances are separate from each other, the only thing they have in common is that they both have a property called $color.

If you want a variable that is available in all Dogs for example, you need a class variable:

class Dog{
    public $color;

    public static $numberOfLegs; //Class variable available in every instance of Dog.

    public function __construct($color, $numberOfLegs){
        $this->color = $color;
        self::$numberOfLegs = $numberOfLegs;
    }
}

class TrainedDog extends Dog{
    public $tricks;

    public function __construct($color, $tricks){
        $this->tricks = $tricks;

        parent::__construct($color);

        echo parent::$numberOfLegs;
    }
}

This does not make much sense in many cases though, because if you have two instances of the parent class (in you're case Core), they also share the class variable.

Unless you can ensure that Core is instanciated only once, this approach will not work. If it does only exist once, you can just as well use constant variables to store the 2 properties.

If there exist multiple instances/objects of Core, I'd recommend using a composition (as suggested by Alvin Wong).

class Core{
      //Just as you programmed it.
}

class Property{
      private $core;

      public function __construct($core){
          $this->core = $core;

          echo $core->curPath;
      }
}

Comments

-1

Try this

include_once('core.php');
$core = new Core('test', 'path');
$core->loadController('property');

class Property extends Core
{
 function __construct($date)
{
    print $date->curpath;
}   
}



class Core
{
public $uri;
public $curpath;

function __construct($uri, $curpath)
{       
    $this->uri = $uri;
    $this->curpath = $curpath;
}


// Load the controller based on the URL
function loadController($name)
{       
    //Instantiate the controller
    require_once($name.'.php');
    $controller = new $name($this);
}


}

1 Comment

Thanks, this solves my problem :) Also thanks @Micheal who suggested the same solution in the comments above.

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.