An answer that is very similar to the others, but with one - in my opinion, key - difference: rather than instantiating the dependency/dependencies in the constructor, pass them to the constructor:
class User
{
protected $db;
public function __construct(Db $db)
{
$this->db = $db;
}
public function login($username, $password)
{
$this->db->query("SELECT * FROM users...");
}
}
The benefits to this type of dependency injection include:
- It clearly demonstrates that the client/consumer class (
User) has a dependency (Db).
- Reduces coupling between the
User class and the Db class. This helps significantly when unit-testing the User class. You can create a mock Db that performs as expected. Any test failures are then clearly attributable to the User class.
Of course, in order to instantiate a User object, you need to instantiate a Db object first. With a lot of dependencies for a single object or for a long chain of dependencies, this can be kind of a pain. In that case, it is helpful - but not required - to employ a Factory or a Dependency Injection Container to assist with this object creation.