What are some potential pitfalls of using prepared statements in PHP when trying to make table and column names dynamic in a function?

When using prepared statements in PHP, the table and column names are typically hardcoded in the SQL query, making it difficult to dynamically change them within a function. One solution is to use string concatenation to build the SQL query dynamically, but this can introduce the risk of SQL injection if not handled properly. Another approach is to use placeholders for the table and column names and then bind them as parameters to the prepared statement.

function getDataFromTable($tableName, $columnName) {
    $conn = new PDO("mysql:host=localhost;dbname=myDB", "username", "password");
    
    $stmt = $conn->prepare("SELECT :columnName FROM :tableName");
    $stmt->bindParam(':columnName', $columnName);
    $stmt->bindParam(':tableName', $tableName);
    
    $stmt->execute();
    
    return $stmt->fetchAll();
}

$data = getDataFromTable("users", "username");
print_r($data);