Search code examples
phpoopparentextend

PHP OOP best practices or how to code right?


I'm trying to learn how to properly code PHP OOP. This is where I'm running into issues.

I created several classes that extend main Application class and I want to make things work properly.

I have main file that's index.php that looks like this:

include_once('classes/Application.php');
include_once('classes/Configuration.php');
include_once('classes/Database.php');

$app = new Application;
$config = new Configuration;
$db = new Database;

var_dump($app->db_connected);
var_dump($db->db_connected);

$db->connect($config->dbhost, $config->dbuser, $config->dbpass, $config->dbname);

var_dump($app->db_connected);
var_dump($db->db_connected);

The output is:

1. bool(false)
2. bool(false)
3. bool(false)
4. bool(true)

My main application file looks like this:

class Application {
    public $db_connected = false;
}

And my Database class looks like this:

class Database extends Application {
    function connect($dbhost, $dbuser, $dbpass, $dbname) {
        if(!$this->db_connected) {
            mysql_connect($dbhost, $dbuser, $dbpass) or die(mysql_error());
            mysql_select_db($dbname) or die(mysql_error());
            $this->db_connected = true;
        }
    }
}

So the question is, why would line #3 of the output of index.php display false? The db_connected property has been overridden in Database class and set to TRUE, but it still returns false.

Although when accessed directly from Database class instance it shows TRUE correctly. What's the deal here?

Also when does the class EXTEND command occurs? Whenever parent class' instance is created or I have to manually create instance of the child class?


Solution

  • It seems you are reaching for the concept of of a static variable all instances of a class share the same static variable so using the new twice will not be an issue.

    You can see the code on ideaone.

    // your code goes here
    
    class Application {
        static $db_connected = false;
    }
    
    class Database extends Application {
        function connect() {
            if(!static::$db_connected) {
                static::$db_connected = true;
            }
        }
    }
    
    $app = new Application;
    $db = new Database;
    
    var_dump(Application::$db_connected);
    var_dump(Database::$db_connected);
    
    $db->connect();
    
    var_dump(Application::$db_connected);
    var_dump(Database::$db_connected); 
    

    Your comment make me think you are looking for a better pattern all together. I would like to throw out some key principles namely OCP and LSP SOLID.

    In this case you would avoid having Application being an instance of Database but instead use dependency injection. Here is the refactored code.

    class Database {
       private $db_connect = false;
       public function connect () {
          if(!$this->db_connect) { /* do connection */ }
       }
    }
    class Application {
       private $db;
       public function setDatabse(Database $db) {
          $this->db = $db;
       }
    
       public function getDatabase() {
          return $this->db;
       }
    }
    
    $db = new Database;
    $app = new Application;
    $app->setDatabase($db);
    $app->getDatabase()->connect();