All posts
PHPAugust 16, 20268 min read

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.

F
Fepiq Team
Fepiq

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.

What you need before you start

  • PHP installed on your computer (version 8 or newer is best). You can check this by running php -v in a terminal.
  • A MySQL server running locally or on a host. Tools like XAMPP, MAMP, or Laragon install PHP and MySQL together in one click.
  • A basic code editor, such as VS Code.
  • Very basic PHP syntax knowledge helps, but is not required — we explain every line.

MySQLi vs PDO: which one should you use?

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.

FeatureMySQLiPDO
Works withMySQL onlyMySQL, PostgreSQL, SQLite, and more
Prepared statements (safe queries)YesYes
Object-oriented and procedural stylesBothObject-oriented only
Good for beginnersYesYes, 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.

Step 1: Create a test database and table

Open a MySQL client (phpMyAdmin, the mysql command line, or a GUI like TablePlus) and run this SQL to create something to connect to.

sql
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.

Step 2: Connect using PDO (recommended)

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
<?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!".

Step 3: Connect using MySQLi (alternative)

If you prefer MySQLi instead, here is the same connection written with it.

php
<?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.

Step 4: Insert data safely with prepared statements

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
<?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.

Step 5: Fetch and display data

php
<?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.

Common connection errors and how to fix them

Error messageLikely causeFix
SQLSTATE[HY000] [1045] Access deniedWrong username or passwordDouble-check $user and $pass against your MySQL setup
SQLSTATE[HY000] [2002] Connection refusedMySQL server is not runningStart MySQL in XAMPP/MAMP/Laragon, or check your host's service
Unknown database 'demo_shop'Database name is wrong or not created yetRun the CREATE DATABASE statement from Step 1
could not find driverPDO's MySQL extension is disabledEnable pdo_mysql in your php.ini file and restart PHP

Security tips for beginners

  • Always use prepared statements for any query that includes user input — never build SQL by joining strings together.
  • Never commit real database passwords to a public code repository; keep them in a separate config or .env file.
  • Use a dedicated MySQL user with limited permissions for your app, instead of the root account, once you go beyond local testing.
  • Turn on PDO::ERRMODE_EXCEPTION (shown in Step 2) so failed queries are easy to spot during development.

Frequently asked questions

What is the difference between PDO and MySQLi in 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.

Why do I get 'Connection failed: SQLSTATE[HY000] [1045] Access denied'?+

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.

Is mysql_connect() still usable in PHP?+

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.

How do I keep my database password safe in PHP code?+

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.

Can I use this same approach to connect PHP to PostgreSQL instead of MySQL?+

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 this

Need help building a PHP application with a real database behind it? Our team can help you plan and build it.

Talk to Fepiq

Get new posts in your inbox

Occasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.

Keep reading

Related posts

All posts

Let's build something

Ready to ship your next product with Fepiq?

Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.