How to Connect PHP to a MySQL Database (Beginner Guide)
Learn how to connect PHP to a MySQL database step by step, using PDO and MySQLi, with safe, copy-pasteable code examples for absolute beginners.
Learn how to connect PHP to a MySQL database step by step, using PDO and MySQLi, with safe, copy-pasteable code examples for absolute beginners.
Short answer: to connect PHP to a MySQL database, you open a connection with either PDO or MySQLi, using your database host, username, password, and database name. Once connected, you can run SQL queries from your PHP code to read and write data. This guide walks you through the whole process, step by step, with beginner-friendly examples you can copy and run today.
You do not need any prior database experience to follow along. We will set up a test database, connect to it two different ways, and then insert and read data safely.
PHP gives you two built-in ways to talk to MySQL: MySQLi ("MySQL improved") and PDO ("PHP Data Objects"). Both are safe and both are actively supported. The old mysql_connect() function was removed from PHP years ago, so never use it or any tutorial that teaches it.
| Feature | MySQLi | PDO |
|---|---|---|
| Works with | MySQL only | MySQL, PostgreSQL, SQLite, and more |
| Prepared statements (safe queries) | Yes | Yes |
| Object-oriented and procedural styles | Both | Object-oriented only |
| Good for beginners | Yes | Yes, and easier to switch databases later |
If you only ever plan to use MySQL, either option works fine. This guide shows you both, starting with PDO because its syntax stays the same even if you switch databases later.
Open a MySQL client (phpMyAdmin, the mysql command line, or a GUI like TablePlus) and run this SQL to create something to connect to.
CREATE DATABASE demo_shop;
USE demo_shop;
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(8,2) NOT NULL
);
INSERT INTO products (name, price) VALUES
('Coffee Mug', 9.99),
('Notebook', 4.50);Line by line: CREATE DATABASE makes a new, empty database named demo_shop. USE demo_shop tells MySQL which database the next commands apply to. CREATE TABLE products defines a table with three columns: id (a number that goes up automatically for every new row), name (text up to 100 characters), and price (a decimal number with 2 digits after the point, good for money). The INSERT statement adds two sample rows so we have data to read later.
Create a new file called db.php. This is where your connection code lives, so you can reuse it on every page instead of repeating it.
<?php
$host = '127.0.0.1';
$db = 'demo_shop';
$user = 'root';
$pass = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('Connection failed: ' . $e->getMessage());
}
echo 'Connected successfully!';Line by line: the four variables at the top hold your connection details — change $user and $pass to match your own MySQL setup (many local installs use 'root' with an empty password by default). new PDO(...) opens the connection; the first argument is a "DSN" (data source name) that tells PDO the database type, host, database name, and character set. The try/catch block catches any connection error instead of letting your whole page crash with a raw error message. setAttribute(...ERRMODE_EXCEPTION) makes PDO throw clear exceptions when a query fails, which is much easier to debug than silent failures. Finally, echo prints a message so you know the connection worked.
Run this file from a terminal with php db.php, or open it in a browser if it's inside your local web server folder. You should see "Connected successfully!".
If you prefer MySQLi instead, here is the same connection written with it.
<?php
$host = '127.0.0.1';
$db = 'demo_shop';
$user = 'root';
$pass = '';
$mysqli = new mysqli($host, $user, $pass, $db);
if ($mysqli->connect_error) {
die('Connection failed: ' . $mysqli->connect_error);
}
echo 'Connected successfully!';Line by line: new mysqli(...) takes the host, username, password, and database name, in that order, and opens the connection. $mysqli->connect_error holds an error message if something went wrong, so the if check stops the script early with a clear message instead of continuing with a broken connection. Pick either PDO or MySQLi for your project — mixing the two for the same connection is not needed and adds confusion.
Never insert raw form input directly into a SQL string — that opens the door to SQL injection, a common attack where malicious text is used to run unwanted database commands. Instead, use a prepared statement, which sends your data separately from your SQL command.
<?php
require 'db.php';
$name = 'Desk Lamp';
$price = 14.99;
$stmt = $pdo->prepare('INSERT INTO products (name, price) VALUES (:name, :price)');
$stmt->execute(['name' => $name, 'price' => $price]);
echo 'New product added with ID: ' . $pdo->lastInsertId();Line by line: require 'db.php' reuses the connection you already wrote, so you don't repeat the setup code. :name and :price in the SQL string are placeholders, not real values. $pdo->prepare(...) sends this SQL template to MySQL first. $stmt->execute([...]) then sends the actual values separately — MySQL treats them purely as data, never as executable SQL, which is what makes this safe. lastInsertId() returns the id MySQL just generated for the new row.
<?php
require 'db.php';
$stmt = $pdo->query('SELECT id, name, price FROM products');
$products = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($products as $product) {
echo $product['name'] . ' - $' . $product['price'] . "\n";
}Line by line: $pdo->query(...) runs a simple SELECT (safe here because there is no user input in it). fetchAll(PDO::FETCH_ASSOC) pulls every matching row back as an array of associative arrays, so each row's columns are accessible by name, like $product['name']. The foreach loop walks through every product and prints its name and price. If your query includes any value from a form or URL, switch to prepare() and execute() like in Step 4, even for SELECT queries.
| Error message | Likely cause | Fix |
|---|---|---|
| SQLSTATE[HY000] [1045] Access denied | Wrong username or password | Double-check $user and $pass against your MySQL setup |
| SQLSTATE[HY000] [2002] Connection refused | MySQL server is not running | Start MySQL in XAMPP/MAMP/Laragon, or check your host's service |
| Unknown database 'demo_shop' | Database name is wrong or not created yet | Run the CREATE DATABASE statement from Step 1 |
| could not find driver | PDO's MySQL extension is disabled | Enable pdo_mysql in your php.ini file and restart PHP |
PDO can connect to many database types, including MySQL, PostgreSQL, and SQLite, using the same syntax. MySQLi only works with MySQL. Both support prepared statements and are safe choices; PDO is usually preferred if you might switch databases later.
This means the username or password in your connection code does not match a real MySQL account. Check the $user and $pass values against what you set up in your MySQL server, or reset the MySQL root password if you're not sure what it is.
No. The old mysql_* functions were removed from PHP starting in PHP 7. If you see a tutorial using mysql_connect(), it is outdated — use PDO or MySQLi instead, as shown in this guide.
Store credentials in a separate file outside your public web folder, or use environment variables loaded through a library like vlucas/phpdotenv. Never hardcode real passwords into files you plan to share or commit to a public repository.
Yes, with PDO you only change the DSN string, for example to 'pgsql:host=127.0.0.1;dbname=demo_shop', and PHP needs the pdo_pgsql extension enabled. The prepare() and execute() code stays exactly the same.
Once you're comfortable connecting PHP to a database by hand, see how a framework like Laravel handles connections, migrations, and queries for you automatically.
See how Laravel simplifies thisNeed help building a PHP application with a real database behind it? Our team can help you plan and build it.
Talk to FepiqOccasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.
Keep reading
What is an index in SQL? A plain-English guide with copy-paste examples showing how indexes speed up queries and when you actually need one.
Learn JavaScript DOM manipulation for beginners: select elements, change text and styles, and handle clicks with simple, copy-paste code examples.
Let's build something
Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.