How can dependency injection be effectively used in PHP to manage dependencies between classes and avoid procedural programming practices?

Dependency injection can be effectively used in PHP by passing dependencies into a class through its constructor or setter methods, rather than creating them within the class itself. This allows for better code reusability, testability, and flexibility by decoupling the classes and managing dependencies externally.

// Dependency injection example
class Database {
    private $connection;

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

    public function query($sql) {
        return $this->connection->query($sql);
    }
}

// External dependency instantiation
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$database = new Database($pdo);

// Usage
$result = $database->query('SELECT * FROM table');