Skip to main content
PostgreSQL
CHAPTER 26 Intermediate

Connecting PostgreSQL with PHP

Updated: May 16, 2026
6 min read

# CHAPTER 26

Connecting PostgreSQL with PHP

1. Introduction

A database without an application is like an engine without a car. To make our PostgreSQL database useful to the world, we must connect it to a backend web server. PHP is one of the most popular backend languages in the world, powering nearly 80% of the web. In this chapter, we will bridge the gap between software engineering and database administration by securely connecting PHP to PostgreSQL using the powerful PDO extension.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the difference between pg_connect and PDO.
  • Establish a secure database connection using PHP PDO.
  • Handle connection errors using try...catch blocks.
  • Understand the catastrophic danger of SQL Injection.
  • Prevent SQL Injection using Prepared Statements.

3. Choosing the Connection Method (PDO vs pg_connect)

PHP offers two main ways to connect to PostgreSQL:
  1. 1. pg_connect(): The older, procedural Postgres-specific extension.
  1. 2. PDO (PHP Data Objects): The modern, object-oriented approach. PDO is a universal interface; if you write your code in PDO, you can switch your database from PostgreSQL to MySQL in the future without having to rewrite your entire application!

*The Golden Rule: Always use PDO in modern PHP applications.*

4. Establishing a PDO Connection

To connect, we must provide PDO with a Data Source Name (DSN), which contains the driver (pgsql), host, port, and database name. We also need our restricted web_app role credentials from Chapter 25.
php
1234567891011121314151617181920212223
<?php
$host = &#039;127.0.0.1';
$port = &#039;5432';
$dbname = &#039;university_db';
$user = &#039;web_app';
$password = &#039;AppPassword99!';

// Construct the DSN string
$dsn = "pgsql:host=$host;port=$port;dbname=$dbname";

try {
    // Attempt the connection
    $pdo = new PDO($dsn, $user, $password);
    
    // Tell PDO to throw severe exceptions if a query fails
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    echo "Successfully connected to PostgreSQL!";
} catch (PDOException $e) {
    // If the database is offline, catch the error gracefully instead of crashing
    die("Database Connection Failed: " . $e->getMessage());
}
?>

5. Executing a Simple Query (No Variables)

If a query does not contain any user input (like a simple dashboard statistic), you can execute it directly using the query() method.
php
1234567
// Fetch all department names
$stmt = $pdo->query("SELECT dept_name FROM departments ORDER BY dept_name ASC");

// Loop through the results and print them
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo "Department: " . $row[&#039;dept_name'] . "<br>";
}

6. The Danger: SQL Injection

What happens when a user types their email into a Login form? Beginners often concatenate the string directly into the query:
php
123
// DANGEROUS! NEVER DO THIS!
$email = $_POST[&#039;user_input'];
$pdo->query("SELECT * FROM users WHERE email = &#039;$email'");

If a hacker types ' OR '1'='1 into the email box, the query becomes: SELECT * FROM users WHERE email = '' OR '1'='1' Because 1 always equals 1, the database ignores the email check and logs the hacker in as the first user (usually the Admin)! This is SQL Injection.

7. The Solution: Prepared Statements

To eliminate SQL Injection completely, you MUST use Prepared Statements. Instead of inserting the variable into the SQL, you insert a placeholder (?). You send the raw SQL template to PostgreSQL first. Then, you send the data separately. The database treats the data strictly as a string, completely neutralizing any malicious SQL commands.
php
12345678910
// 1. Prepare the query template with a placeholder (?)
$stmt = $pdo->prepare("SELECT first_name, email FROM users WHERE email = ?");

// 2. Execute the query, passing the user input as a separate array
$userInput = &#039;john@example.com';
$stmt->execute([$userInput]);

// 3. Fetch the secure result
$user = $stmt->fetch(PDO::FETCH_ASSOC);
echo "Welcome, " . $user[&#039;first_name'];

8. Mini Project: Secure User Insertion

Let's build the backend logic for a user registration form, ensuring maximum security via Prepared Statements.
php
1234567891011121314151617181920212223
<?php
// Assume these came from a $_POST form submission
$firstName = &#039;Alice';
$email = &#039;alice@example.com';

// The SQL template with named placeholders
$sql = "INSERT INTO users (first_name, email) VALUES (:fname, :email)";

// Prepare the statement
$stmt = $pdo->prepare($sql);

try {
    // Execute and bind the variables securely
    $stmt->execute([
        &#039;:fname' => $firstName,
        &#039;:email' => $email
    ]);
    echo "User registered successfully!";
} catch (PDOException $e) {
    // Catch errors (e.g., if the UNIQUE email constraint fails)
    echo "Registration failed: " . $e->getMessage();
}
?>

9. Common Mistakes

  • Exposing Credentials in GitHub: Never hardcode $password = 'AppPassword99!' directly in your PHP files if you are pushing code to GitHub. Hackers scan GitHub continuously for exposed database passwords. Always use .env files to store configuration secrets outside of your code repository.
  • Using procedural pg_query(): Avoid legacy functions from older PHP tutorials. Stick strictly to the Object-Oriented PDO class.

10. Best Practices

  • Singleton Database Connection: Opening a connection to PostgreSQL takes a fraction of a second. If your PHP app opens a new connection in 5 different files during a single page load, the site will be incredibly slow. Use a "Singleton" class or Dependency Injection to ensure the PDO connection is opened exactly once per request and reused.

11. Exercises

  1. 1. What is the fundamental difference between $pdo->query() and $pdo->prepare()?
  1. 2. Why is the catch (PDOException $e) block critical when establishing a database connection?

12. SQL Challenges

Write the secure PHP/PDO code to update the salary of an employee to $75000 where the emp_id is 10, using positional placeholders (?).
php
1234
$newSalary = 75000;
$empId = 10;
$stmt = $pdo->prepare("UPDATE employees SET salary = ? WHERE emp_id = ?");
$stmt->execute([$newSalary, $empId]);

13. MCQ Quiz with Answers

Question 1

What is the primary purpose of using PDO Prepared Statements when executing SQL queries containing user input?

Question 2

Which PHP extension is considered the modern, object-oriented standard for connecting to PostgreSQL (and allows for seamless switching to other databases like MySQL if needed)?

14. Interview Questions

  • Q: Explain exactly how a SQL Injection attack works. How do Prepared Statements mechanically neutralize the threat?
  • Q: Describe the architectural purpose of a Data Source Name (DSN) string when instantiating a new PDO object.

15. FAQs

Q: Does PDO support the PostgreSQL RETURNING clause? A: Yes! You simply write your query as INSERT ... RETURNING id, execute the prepared statement, and then immediately call $stmt->fetchColumn() to retrieve the returned ID back into PHP!

16. Summary

You have successfully bridged the gap between the application server and the database. By utilizing PDO, establishing robust error handling, and strictly enforcing the use of Prepared Statements, you guarantee a high-performance, universally secure data pipeline between PHP and PostgreSQL.

17. Next Chapter Recommendation

We know how to connect. We know how to execute a single query. Now it is time to build a complete application architecture. In Chapter 27: Building CRUD Applications with PostgreSQL, we will design the full lifecycle (Create, Read, Update, Delete) of a web application from top to bottom.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·