通过多个类的PHP Mysqli连接

So, I'm old to PHP, but most of the time I've used procedural style. I've always tried to follow a MVC pattern, even though I was doing stuff procedurally. Also, I'm used to some frameworks like CakePHP and CodeIgniter. However, I've not yet done anything from scratch using OOP. Today I was doing so for a college work, and I got to a few questions.

Usually, in frameworks, we just do $this->database->query(), on any controller class, and it works. On procedural, the $link to the database goes global scope, so you don't have to worry. I was looking for a way to do that with every class on my code, but to no success. The best I could get was using a Singleton class to instantiate the database, however, I needed to retrieve the database link in every single class. So for instance, in class Users I'd have to get it in the constructor, and at the Main class, and in every other one.

My questions is fairly simple. How do I use the database connection link through multiple classes, without having to instantiate the db in all of them. And, if doing so is the best simpler way, is there any other way to do so than the Singleton method?

I'm using Mysqli lib, by the way.

Here's the class I've been using.

class DB extends Mysqli {
    protected static $instance;

    private function __construct() {
        global $config;

        parent::__construct($config['db']['host'], $config['db']['user'], $config['db']['password'], $config['db']['database']);

        if($this->connect_error)
            die('Connect Error ('. $mysqli->connect_errno .') '. $mysqli->connect_error);
    }

    public static function getInstance() {
        if( !self::$instance ) {
            self::$instance = new self(); 
        }
        return self::$instance;
    }
}

Here is a class usage example.

class Main {
    protected $db;

    public function __construct() {
        $this->db = DB::getInstance(); // <-- having to do that in every class is the problem
    }

    protected function start() {
        $this->db->query(something...); // works
    }
}

If you create a superclass with the magic __get method you can check if the name of the property requested is db and if so then automatically get the instance from your DB class and if not error out as usual:

<?php
class Super
{
    public function __get($name)
    {
           if($name=="db") {
                     return DB::getInstance();
           } else {
                     trigger_error("Undefined property", E_USER_NOTICE);
           }
    }
}
?>

Better approach would be using dependency injection instead of initiating connection in each class:

$db = DB::getInstance(); // or any other way to initiate it
$obj1 = new MyClass1($db);
$obj2 = new MyClass2($db);

This way you always decide what DB you want to pass to each class. Furthermore this gives some advantages if you do unit testing as well - then you can test each class by providing link to test DB or even mocking/stubbing it.

So, I came up with my own answer. I'm not sure if this is the optimal way, but here it is. Using the same DB class as of the question, I created a "Super" class to "hold" the database link upon construct. That way, as long as I don't use a constructor on the other classes, I can extend the "Super" class, and get access to $this->db without having to define it in every class. If a constructor is indeed needed, I can call parent::__construct() from it, and it will work as well.

class Super {
    protected $db;

    public function __construct() {
        $this->db = DB::getInstance();
    }
}

class Main extends Super {

    /* No constructor, 
       otherwise it will overwrite the Super 
       constructor and lack what we've done there. */

    public function start() {
        $this->db->query(something...); // works
    }

}

I also injected some other variables and functions that were needed in several classes. From there, I can choose where to extend or not the "Super" class, when needed.