تقریباً هر برنامه وب واقعی به محلی برای ذخیره و مدیریت اطلاعات نیاز دارد. کاربران، محصولات، سفارشها، مقالات، تنظیمات، تراکنشها و بسیاری از اطلاعات دیگر معمولاً در پایگاه داده ذخیره میشوند.
اگر با PHP کار میکنید، یکی از مهمترین مهارتهایی که باید یاد بگیرید، اتصال PHP به MySQL است.
PHP بهصورت مستقیم اطلاعات را در MySQL ذخیره نمیکند؛ بلکه از ابزارهایی مانند PDO و MySQLi برای برقراری ارتباط با MySQL استفاده میکند.
در این آموزش، ابتدا یک دیتابیس MySQL ایجاد میکنیم، سپس PHP را با PDO و MySQLi به آن متصل میکنیم و در ادامه روش اجرای Query، دریافت اطلاعات، مدیریت خطا و استفاده از Prepared Statement را بررسی خواهیم کرد.
اتصال PHP به MySQL چگونه انجام میشود؟
ارتباط بین PHP و MySQL را میتوان به شکل زیر تصور کرد:
کاربر
↓
مرورگر
↓
PHP
↓
PDO / MySQLi
↓
MySQL
↓
Database
برای مثال، وقتی کاربر در سایت ثبتنام میکند:
فرم ثبتنام
↓
PHP
↓
اعتبارسنجی اطلاعات
↓
PDO / MySQLi
↓
MySQL
↓
users table
PHP مسئول اجرای منطق برنامه است و MySQL اطلاعات را ذخیره و مدیریت میکند.
# پیشنیازهای اتصال PHP به MySQL
برای اجرای مثالهای این مقاله به موارد زیر نیاز دارید:
- PHP
- MySQL
- یک Web Server مانند Apache یا Nginx
- یک دیتابیس MySQL
- Extension مربوط به PDO یا MySQLi
اگر از محیطهایی مانند XAMPP یا Laragon استفاده میکنید، معمولاً PHP و MySQL از قبل در اختیار شما هستند.
# ساخت دیتابیس MySQL
ابتدا باید یک دیتابیس ایجاد کنیم.
برای مثال میتوانیم دیتابیسی با نام زیر بسازیم:
php_mysql
در MySQL میتوانید Query زیر را اجرا کنید:
CREATE DATABASE php_mysql
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
سپس وارد دیتابیس شویم:
USE php_mysql;
حالا یک جدول ساده برای کاربران ایجاد میکنیم:
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
جدول ما اکنون دارای ستونهای زیر است:
| ستون | کاربرد |
|---|---|
| id | شناسه کاربر |
| name | نام کاربر |
| ایمیل کاربر | |
| created_at | زمان ایجاد کاربر |
# اطلاعات مورد نیاز برای اتصال PHP به MySQL
برای برقراری اتصال معمولاً به این اطلاعات نیاز داریم:
Host
Port
Database Name
Username
Password
مثلاً:
Host: localhost
Port: 3306
Database: php_mysql
Username: root
Password:
البته این اطلاعات در هر سرور ممکن است متفاوت باشند.
در محیط توسعه محلی، نام کاربری root و رمز عبور خالی ممکن است استفاده شود، اما در محیط Production نباید به این شکل عمل کرد.
# اتصال PHP به MySQL با PDO
یکی از روشهای اصلی برای اتصال PHP به MySQL استفاده از PDO است.
یک اتصال ساده:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=php_mysql;charset=utf8mb4',
'root',
''
);
در این کد:
mysql:
مشخص میکند که میخواهیم از Driver مربوط به MySQL استفاده کنیم.
قسمت:
host=localhost
آدرس سرور دیتابیس را مشخص میکند.
قسمت:
dbname=php_mysql
نام دیتابیسی است که میخواهیم به آن متصل شویم.
و:
charset=utf8mb4
Encoding ارتباط با دیتابیس را مشخص میکند.
# تست اتصال PHP به MySQL
میتوانیم اتصال را در یک فایل PHP آزمایش کنیم.
برای مثال فایلی به نام:
database-test.php
ایجاد کنید:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=php_mysql;charset=utf8mb4',
'root',
''
);
echo 'اتصال به MySQL با موفقیت انجام شد.';
اگر PHP و MySQL بهدرستی اجرا شده باشند، پیام زیر نمایش داده میشود:
اتصال به MySQL با موفقیت انجام شد.
# مدیریت خطا در اتصال PDO
در پروژه واقعی نباید فرض کنیم که اتصال همیشه موفق خواهد بود.
ممکن است:
- MySQL خاموش باشد.
- نام دیتابیس اشتباه باشد.
- نام کاربری اشتباه باشد.
- رمز عبور اشتباه باشد.
- Host اشتباه باشد.
- کاربر اجازه دسترسی به دیتابیس را نداشته باشد.
به همین دلیل بهتر است خطاها را مدیریت کنیم.
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=php_mysql;charset=utf8mb4',
'root',
''
);
$pdo->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
);
echo 'اتصال موفق بود.';
} catch (PDOException $e) {
echo 'اتصال به دیتابیس انجام نشد.';
}
در این مثال از try و catch استفاده کردهایم.
اگر اتصال با مشکل مواجه شود، Exception گرفته میشود و برنامه میتواند رفتار مناسبی داشته باشد.
# نمایش خطای واقعی PDO
در محیط توسعه میتوانیم جزئیات خطا را مشاهده کنیم:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=php_mysql;charset=utf8mb4',
'root',
''
);
$pdo->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
);
} catch (PDOException $e) {
echo $e->getMessage();
}
اما در محیط Production بهتر است پیام داخلی Exception را مستقیماً به کاربر نمایش ندهیم.
اطلاعاتی مانند نام سرور، مسیر فایل، Query یا جزئیات اتصال میتوانند اطلاعات حساسی در اختیار مهاجم قرار دهند.
# تنظیمات بهتر برای PDO
میتوان اتصال را با تنظیمات مناسبتری ایجاد کرد:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=php_mysql;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
در این مثال:
PDO::ATTR_ERRMODE
نحوه مدیریت خطاها را مشخص میکند.
PDO::ATTR_DEFAULT_FETCH_MODE
نحوه دریافت نتایج Query را مشخص میکند.
و:
PDO::ATTR_EMULATE_PREPARES
برای تنظیم رفتار Prepared Statement استفاده میشود.
# اتصال PHP به MySQL با MySQLi
روش دوم، استفاده از MySQLi است.
یک اتصال ساده با MySQLi:
<?php
$mysqli = new mysqli(
'localhost',
'root',
'',
'php_mysql'
);
if ($mysqli->connect_error) {
die('خطا در اتصال به دیتابیس.');
}
echo 'اتصال به MySQL با موفقیت انجام شد.';
در اینجا:
new mysqli()
برای ایجاد اتصال استفاده شده است.
# تنظیم Charset در MySQLi
برای پشتیبانی صحیح از UTF-8 بهتر است Charset را مشخص کنیم:
<?php
$mysqli = new mysqli(
'localhost',
'root',
'',
'php_mysql'
);
if ($mysqli->connect_error) {
die('خطا در اتصال به دیتابیس.');
}
$mysqli->set_charset('utf8mb4');
echo 'اتصال موفق بود.';
استفاده از utf8mb4 برای پروژههایی که محتوای فارسی و چندزبانه دارند اهمیت زیادی دارد.
# اجرای Query با PDO
حالا که اتصال ایجاد شده است، میتوانیم Query اجرا کنیم.
برای مثال، چند کاربر ایجاد کنیم:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=php_mysql;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
$pdo->exec("
INSERT INTO users (name, email)
VALUES
('Ali', 'ali@example.com'),
('Sara', 'sara@example.com')
");
در این مثال از exec() استفاده شده است.
اما برای اطلاعاتی که از کاربر دریافت میشوند، بهتر است از Prepared Statement استفاده کنیم.
# Prepared Statement چیست؟
Prepared Statement یکی از مهمترین مفاهیمی است که هنگام کار با PHP و MySQL باید یاد بگیرید.
فرض کنید کاربر ایمیل خود را وارد میکند:
$email = $_POST['email'];
نباید به شکل زیر Query بسازیم:
$sql = "SELECT * FROM users WHERE email = '$email'";
قرار دادن مستقیم ورودی کاربر در SQL میتواند باعث ایجاد آسیبپذیری SQL Injection شود.
روش صحیح استفاده از پارامترهای Query است.
# Prepared Statement با PDO
با PDO میتوانیم بنویسیم:
<?php
$email = $_POST['email'];
$stmt = $pdo->prepare(
'SELECT * FROM users WHERE email = :email'
);
$stmt->execute([
'email' => $email
]);
$user = $stmt->fetch();
در اینجا مقدار $email مستقیماً داخل Query قرار نگرفته است.
به جای آن از Placeholder زیر استفاده کردهایم:
:email
و مقدار آن را هنگام اجرای Query ارسال کردهایم.
# دریافت اطلاعات از MySQL با PDO
فرض کنید میخواهیم تمام کاربران را دریافت کنیم:
<?php
$stmt = $pdo->query(
'SELECT id, name, email FROM users'
);
$users = $stmt->fetchAll();
foreach ($users as $user) {
echo $user['name'];
echo '<br>';
}
در این مثال:
fetchAll()
تمام نتایج را دریافت میکند.
# دریافت یک رکورد با PDO
اگر فقط یک رکورد نیاز داشته باشیم، میتوانیم از fetch() استفاده کنیم:
<?php
$stmt = $pdo->prepare(
'SELECT id, name, email
FROM users
WHERE id = :id'
);
$stmt->execute([
'id' => 1
]);
$user = $stmt->fetch();
if ($user) {
echo $user['name'];
} else {
echo 'کاربر پیدا نشد.';
}
# INSERT با PDO
برای ایجاد رکورد جدید:
<?php
$name = 'Reza';
$email = 'reza@example.com';
$stmt = $pdo->prepare(
'INSERT INTO users (name, email)
VALUES (:name, :email)'
);
$stmt->execute([
'name' => $name,
'email' => $email
]);
پس از اجرای Query میتوان شناسه رکورد ایجادشده را نیز دریافت کرد:
$id = $pdo->lastInsertId();
echo $id;
# UPDATE با PDO
برای تغییر اطلاعات:
<?php
$id = 1;
$name = 'Reza Ahmadi';
$stmt = $pdo->prepare(
'UPDATE users
SET name = :name
WHERE id = :id'
);
$stmt->execute([
'name' => $name,
'id' => $id
]);
# DELETE با PDO
برای حذف اطلاعات:
<?php
$id = 1;
$stmt = $pdo->prepare(
'DELETE FROM users
WHERE id = :id'
);
$stmt->execute([
'id' => $id
]);
# اتصال PHP به MySQL با MySQLi و Prepared Statement
MySQLi نیز از Prepared Statement پشتیبانی میکند.
مثلاً:
<?php
$mysqli = new mysqli(
'localhost',
'root',
'',
'php_mysql'
);
$mysqli->set_charset('utf8mb4');
$stmt = $mysqli->prepare(
'SELECT id, name, email
FROM users
WHERE email = ?'
);
$email = 'ali@example.com';
$stmt->bind_param('s', $email);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
if ($user) {
echo $user['name'];
}
در MySQLi از ? بهعنوان Placeholder استفاده شده است.
سپس مقدار با:
bind_param()
به Query متصل میشود.
# تفاوت Prepared Statement در PDO و MySQLi
در PDO معمولاً میتوانیم از نام پارامتر استفاده کنیم:
:name
مثلاً:
$stmt = $pdo->prepare(
'SELECT * FROM users WHERE name = :name'
);
اما در MySQLi معمولاً از:
?
استفاده میشود:
$stmt = $mysqli->prepare(
'SELECT * FROM users WHERE name = ?'
);
هر دو روش میتوانند برای اجرای Queryهای پارامتری استفاده شوند.
# آیا باید PDO یاد بگیریم یا MySQLi؟
هر دو ابزار مهم هستند، اما برای بسیاری از پروژههای جدید PHP میتوانید تمرکز اصلی خود را روی PDO قرار دهید.
PDO امکاناتی مانند:
- Prepared Statement
- Transaction
- مدیریت Exception
- API یکپارچهتر
را در اختیار شما قرار میدهد.
با این حال، شناخت MySQLi نیز مهم است؛ زیرا ممکن است در پروژههای قدیمی یا کدهای موجود با آن مواجه شوید.
# استفاده از فایل جدا برای اتصال دیتابیس
یکی از اشتباهات رایج این است که کد اتصال دیتابیس را در تمام فایلهای PHP تکرار کنیم.
برای مثال بهتر است ساختار پروژه را به شکل زیر ایجاد کنیم:
project/
│
├── config/
│ └── database.php
│
├── public/
│ └── index.php
│
└── src/
فایل:
config/database.php
میتواند اتصال را ایجاد کند:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=php_mysql;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
سپس در فایل دیگر:
<?php
require_once __DIR__ . '/../config/database.php';
$stmt = $pdo->query(
'SELECT * FROM users'
);
$users = $stmt->fetchAll();
این روش از تکرار کد جلوگیری میکند.
# اطلاعات دیتابیس را داخل کد قرار ندهیم
در پروژههای واقعی بهتر است اطلاعات حساس اتصال دیتابیس مستقیماً داخل فایل PHP قرار نگیرد.
برای مثال:
DB_HOST
DB_NAME
DB_USER
DB_PASSWORD
میتوانند از Environment Variables خوانده شوند.
در پروژههایی که از .env استفاده میکنند، ممکن است چنین ساختاری داشته باشیم:
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=php_mysql
DB_USERNAME=my_user
DB_PASSWORD=secret
فایل .env نباید در دسترس عمومی وب قرار داشته باشد و بهتر است اطلاعات آن نیز وارد Git Repository نشود.
# خطاهای رایج هنگام اتصال PHP به MySQL
هنگام اتصال PHP به MySQL ممکن است با خطاهای مختلفی مواجه شوید.
۱. Access denied
اگر نام کاربری یا رمز عبور اشتباه باشد، ممکن است با خطایی مانند:
Access denied for user
مواجه شوید.
اطلاعات Username و Password را بررسی کنید.
۲. Unknown database
اگر نام دیتابیس اشتباه باشد، خطایی مانند:
Unknown database
ممکن است نمایش داده شود.
نام دیتابیس را بررسی کنید.
۳. Connection refused
اگر MySQL اجرا نشده باشد یا Host/Port اشتباه باشد، ممکن است اتصال برقرار نشود.
در این حالت وضعیت MySQL Server و مقدار Host و Port را بررسی کنید.
۴. مشکل Charset
اگر Encoding بهدرستی تنظیم نشده باشد، ممکن است حروف فارسی یا Emoji بهدرستی ذخیره یا نمایش داده نشوند.
در اتصال MySQL بهتر است از:
utf8mb4
استفاده شود.
# امنیت اتصال PHP به MySQL
اتصال موفق فقط اولین مرحله است. در یک پروژه واقعی باید امنیت ارتباط و اطلاعات دیتابیس را نیز در نظر گرفت.
مهمترین موارد عبارتاند از:
استفاده از Prepared Statement
برای Queryهایی که شامل داده کاربر هستند از Prepared Statement استفاده کنید.
استفاده از کاربر دیتابیس محدود
برای برنامه بهتر است یک Database User با دسترسیهای موردنیاز ایجاد شود و لزوماً از کاربر مدیریتی MySQL استفاده نشود.
نگهداری امن رمز عبور
رمز دیتابیس را داخل کد عمومی یا Repository قرار ندهید.
استفاده از HTTPS
اطلاعات بین مرورگر و سرور باید از طریق HTTPS منتقل شوند.
عدم نمایش خطاهای حساس
جزئیات Exception دیتابیس نباید در Production به کاربر نمایش داده شود.
جلوگیری از SQL Injection
ورودی کاربر را مستقیماً داخل SQL قرار ندهید.
# یک مثال کامل اتصال PHP به MySQL
در نهایت میتوانیم یک فایل کامل برای اتصال ایجاد کنیم:
<?php
$host = 'localhost';
$dbname = 'php_mysql';
$username = 'root';
$password = '';
try {
$pdo = new PDO(
"mysql:host={$host};dbname={$dbname};charset=utf8mb4",
$username,
$password,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
echo 'اتصال به MySQL با موفقیت انجام شد.';
} catch (PDOException $e) {
echo 'خطا در اتصال به دیتابیس.';
}
این نمونه برای یادگیری مناسب است، اما در پروژه واقعی بهتر است اطلاعات اتصال از Environment Variables دریافت شوند.
# ساخت یک نمونه CRUD ساده
اکنون که اتصال را یاد گرفتیم، میتوانیم عملیات اصلی دیتابیس را نیز انجام دهیم.
ایجاد
$stmt = $pdo->prepare(
'INSERT INTO users (name, email)
VALUES (:name, :email)'
);
$stmt->execute([
'name' => 'Ali',
'email' => 'ali@example.com'
]);
خواندن
$stmt = $pdo->query(
'SELECT * FROM users'
);
$users = $stmt->fetchAll();
ویرایش
$stmt = $pdo->prepare(
'UPDATE users
SET name = :name
WHERE id = :id'
);
$stmt->execute([
'name' => 'Ali Ahmadi',
'id' => 1
]);
حذف
$stmt = $pdo->prepare(
'DELETE FROM users
WHERE id = :id'
);
$stmt->execute([
'id' => 1
]);
بنابراین CRUD در PHP و MySQL شامل چهار عملیات اصلی است:
Create → INSERT
Read → SELECT
Update → UPDATE
Delete → DELETE
# اتصال PHP به MySQL در پروژههای حرفهای
در پروژههای کوچک ممکن است بتوانید تمام کد دیتابیس را در چند فایل PHP مدیریت کنید.
اما با بزرگ شدن پروژه بهتر است معماری مناسبتری داشته باشید.
برای مثال:
Request
↓
Controller
↓
Service
↓
Repository
↓
PDO
↓
MySQL
در این ساختار هر بخش مسئولیت مشخصی دارد.
برای مثال Repository میتواند عملیات مربوط به کاربران را مدیریت کند:
class UserRepository
{
public function __construct(
private PDO $pdo
) {}
public function findById(int $id): ?array
{
$stmt = $this->pdo->prepare(
'SELECT *
FROM users
WHERE id = :id'
);
$stmt->execute([
'id' => $id
]);
$user = $stmt->fetch();
return $user ?: null;
}
}
این نوع معماری در پروژههای بزرگتر باعث جداسازی مسئولیتها و نگهداری آسانتر کد میشود.
# ارتباط PHP و MySQL با Laravel چه تفاوتی دارد؟
اگر از PHP خام به Laravel مهاجرت کنید، معمولاً دیگر لازم نیست تمام Queryهای دیتابیس را مستقیماً با PDO بنویسید.
Laravel ابزارهایی مانند:
Eloquent ORM
Query Builder
Migration
Model
Relationship
Transaction
را ارائه میکند.
مثلاً در Laravel ممکن است برای دریافت کاربران بنویسید:
$users = User::all();
یا:
$users = User::where(
'email',
'ali@example.com'
)->first();
اما دانستن نحوه اتصال PHP به MySQL همچنان ارزشمند است؛ زیرا کمک میکند بهتر بفهمید Laravel در لایه دیتابیس چه کاری انجام میدهد.
# جمعبندی
برای اتصال PHP به MySQL دو روش مهم وجود دارد:
PDO
MySQLi
هر دو روش امکان اجرای Query و کار با MySQL را فراهم میکنند.
در پروژههای جدید باید بهخصوص با مفاهیم زیر آشنا باشید:
- اتصال به دیتابیس
- PDO
- MySQLi
- Prepared Statement
- SELECT
- INSERT
- UPDATE
- DELETE
- مدیریت Exception
- Charset و utf8mb4
- امنیت اطلاعات اتصال
- SQL Injection
مهمترین نکته امنیتی این است که دادههای دریافتشده از کاربر را مستقیماً داخل Query قرار ندهید و برای Queryهای پارامتری از Prepared Statement استفاده کنید.
پس مسیر کلی ارتباط PHP با MySQL را میتوان اینگونه خلاصه کرد:
PHP
↓
PDO / MySQLi
↓
Prepared Statement
↓
MySQL
↓
Database
اگر در حال یادگیری PHP هستید، بعد از یادگیری اتصال به MySQL، مرحله مهم بعدی کار با CRUD، Queryهای پیشرفته، JOIN، تراکنشها و مدیریت صحیح دادهها است؛ این مفاهیم پایه بسیاری از سیستمهای واقعی مانند فروشگاه، CMS، پنل مدیریت و API هستند.
سوالات متداول
بهترین روش اتصال PHP به MySQL چیست؟
دو روش اصلی PDO و MySQLi هستند. هر دو قابلیتهای لازم برای اتصال و اجرای Query را دارند و PDO در بسیاری از پروژهها به دلیل API یکپارچه و امکانات مناسب گزینهای رایج است.
آیا برای اتصال PHP به MySQL باید MySQL را روی کامپیوتر نصب کنیم؟
برای محیط توسعه معمولاً به یک MySQL Server نیاز دارید. ابزارهایی مانند XAMPP و Laragon میتوانند راهاندازی محیط PHP و MySQL را سادهتر کنند.
آیا PDO از MySQL پشتیبانی میکند؟
بله. PDO با استفاده از Driver مربوط به MySQL میتواند با MySQL ارتباط برقرار کند.
آیا MySQLi امن است؟
MySQLi میتواند به شکل امن مورد استفاده قرار بگیرد، اما باید از امکاناتی مانند Prepared Statement استفاده کنید و سایر اصول امنیتی برنامه را نیز رعایت کنید.
چرا از utf8mb4 استفاده میکنیم؟
utf8mb4 امکان ذخیره و پردازش طیف گستردهای از کاراکترهای Unicode را فراهم میکند و برای پروژههای فارسی و چندزبانه انتخاب مناسبی است.
آیا استفاده از Prepared Statement ضروری است؟
برای Queryهایی که دادههای خارجی یا ورودی کاربر را دریافت میکنند، استفاده از Prepared Statement یکی از روشهای مهم جلوگیری از SQL Injection است.





