اگر با PHP برای ساخت سایت، پنل مدیریت، فروشگاه اینترنتی یا نرمافزار تحت وب کار میکنید، خیلی زود با یک نیاز اساسی روبهرو میشوید: ذخیره و بازیابی اطلاعات.
اطلاعاتی مانند کاربران، محصولات، سفارشها، مقالات، دیدگاهها، تراکنشها و تنظیمات برنامه معمولاً نباید فقط در فایلهای PHP نگهداری شوند. برای مدیریت چنین اطلاعاتی به یک سیستم مدیریت پایگاه داده نیاز داریم.
یکی از رایجترین انتخابها در پروژههای PHP، MySQL است.
در این مقاله ابتدا رابطه PHP و MySQL را بررسی میکنیم، سپس با روشهای اصلی دسترسی PHP به MySQL، یعنی PDO و MySQLi آشنا میشویم و در نهایت یک ساختار عملی برای کار با دیتابیس و نکات امنیتی مهم را بررسی میکنیم.
PHP و MySQL چه ارتباطی با یکدیگر دارند؟
PHP یک زبان برنامهنویسی سمت سرور است و MySQL یک سیستم مدیریت پایگاه داده رابطهای است.
به زبان ساده:
کاربر
↓
مرورگر
↓
PHP
↓
MySQL
↓
اطلاعات
فرض کنید کاربر در یک سایت ثبتنام میکند.
PHP اطلاعاتی مانند:
نام
ایمیل
رمز عبور
را از فرم دریافت میکند و سپس آنها را برای ذخیرهسازی به MySQL ارسال میکند.
در هنگام ورود کاربر نیز مسیر برعکس میشود:
کاربر
↓
PHP
↓
MySQL
↓
بررسی اطلاعات
↓
PHP
↓
پاسخ به کاربر
بنابراین PHP و MySQL معمولاً نقشهای متفاوتی دارند:
| فناوری | وظیفه |
|---|---|
| PHP | منطق و پردازش برنامه |
| MySQL | ذخیره و مدیریت اطلاعات |
| HTML | ساختار صفحه |
| CSS | ظاهر صفحه |
| JavaScript | تعاملات سمت کاربر |
چرا از MySQL در پروژههای PHP استفاده میشود؟
MySQL یکی از پایگاههای دادهای است که در پروژههای وب کاربرد زیادی دارد و PHP نیز ابزارهای مختلفی برای ارتباط با پایگاههای داده در اختیار توسعهدهنده قرار میدهد.
برای مثال میتوان اطلاعات کاربران را در جدولی مانند زیر ذخیره کرد:
users
id
name
email
password
created_at
یا برای یک فروشگاه اینترنتی:
products
id
title
price
stock
description
created_at
سپس PHP میتواند اطلاعات این جداول را:
- ایجاد کند
- بخواند
- ویرایش کند
- حذف کند
- فیلتر کند
- مرتب کند
- بین چند جدول جستوجو کند
این چهار عملیات اصلی معمولاً با نام CRUD شناخته میشوند:
Create
Read
Update
Delete
# PHP چگونه به MySQL متصل میشود؟
PHP برای ارتباط با MySQL چند API در اختیار توسعهدهنده قرار میدهد.
دو گزینه مهم عبارتاند از:
- PDO
- MySQLi
مستندات رسمی PHP نیز PDO و MySQLi را بهعنوان دو API اصلی برای دسترسی به MySQL معرفی میکند.
PDO چیست؟
PDO مخفف:
PHP Data Objects
است.
PDO یک رابط استاندارد برای دسترسی به پایگاههای داده در PHP فراهم میکند و با استفاده از Driver مربوط به دیتابیس با پایگاه داده ارتباط برقرار میکند.
برای MySQL از Driver زیر استفاده میشود:
PDO_MYSQL
یکی از مزیتهای مهم PDO این است که API نسبتاً یکپارچهای برای کار با دیتابیسهای مختلف ارائه میکند.
برای مثال، ساختار کلی اتصال به MySQL با PDO به شکل زیر است:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'root',
''
);
در این کد:
mysql:
نوع Driver را مشخص میکند.
host=localhost
آدرس سرور MySQL را مشخص میکند.
dbname=my_database
نام دیتابیس را مشخص میکند.
و:
charset=utf8mb4
Encoding ارتباط با دیتابیس را مشخص میکند.
# MySQLi چیست؟
MySQLi مخفف:
MySQL Improved
است.
این Extension بهصورت اختصاصی برای کار با MySQL طراحی شده و هم رابط شیگرا و هم رابط رویهای ارائه میکند.
یک اتصال ساده با MySQLi:
<?php
$mysqli = new mysqli(
'localhost',
'root',
'',
'my_database'
);
بعد از اتصال میتوان Queryهای SQL را اجرا کرد.
برای مثال:
$result = $mysqli->query(
"SELECT * FROM users"
);
# تفاوت PDO و MySQLi چیست؟
هر دو روش برای ارتباط PHP با MySQL قابل استفاده هستند، اما تفاوتهایی دارند.
| ویژگی | PDO | MySQLi |
|---|---|---|
| پشتیبانی از MySQL | بله | بله |
| Prepared Statement | بله | بله |
| Transaction | بله | بله |
| رابط شیگرا | بله | بله |
| رابط رویهای | خیر | بله |
| پشتیبانی از چند نوع دیتابیس | بله | خیر |
| API یکپارچهتر | بله | محدود به MySQL |
PDO برای پروژههایی که میخواهند لایه دسترسی به دیتابیس نسبتاً مستقل و قابل انتقالی داشته باشند، انتخاب مناسبی است.
MySQLi نیز برای پروژههایی که مشخصاً فقط با MySQL کار میکنند گزینه قدرتمندی است.
# آیا باید PDO یاد بگیریم یا MySQLi؟
اگر در حال یادگیری PHP هستید، بهتر است با هر دو آشنا شوید؛ اما در پروژههای جدید میتوانید روی PDO تمرکز بیشتری داشته باشید.
دلیل مهم این موضوع، API تمیز و پشتیبانی مناسب از Prepared Statement است.
در هر صورت مهمتر از انتخاب بین PDO و MySQLi، رعایت اصول صحیح دسترسی به دیتابیس است.
بهخصوص نباید اطلاعات دریافتشده از کاربر را مستقیماً داخل SQL قرار دهید.
# اجرای Query در PHP
فرض کنید جدول زیر را داریم:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
حالا میتوانیم یک Query برای دریافت کاربران اجرا کنیم.
با PDO:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'root',
''
);
$stmt = $pdo->query(
'SELECT id, name, email FROM users'
);
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($users as $user) {
echo $user['name'];
}
در این مثال:
$pdo->query()
Query را اجرا میکند.
سپس:
fetchAll()
نتایج را دریافت میکند.
و:
PDO::FETCH_ASSOC
باعث میشود نتیجه بهصورت آرایه associative در اختیار ما قرار بگیرد.
# اضافه کردن اطلاعات به MySQL
فرض کنید میخواهیم یک کاربر جدید ایجاد کنیم.
روش نادرست این است که مقدار ورودی کاربر را مستقیماً داخل Query قرار دهیم.
مثلاً:
$name = $_POST['name'];
$sql = "INSERT INTO users (name) VALUES ('$name')";
این روش میتواند برنامه را در برابر SQL Injection آسیبپذیر کند.
روش مناسب استفاده از Prepared Statement است.
# Prepared Statement چیست؟
Prepared Statement روشی برای اجرای Queryهایی است که مقادیر متغیر دارند.
برای مثال:
<?php
$sql = "
INSERT INTO users (name, email)
VALUES (:name, :email)
";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'name' => $name,
'email' => $email,
]);
در اینجا مقادیر:
:name
:email
بهعنوان پارامتر Query استفاده میشوند.
به این ترتیب مقدار کاربر مستقیماً بهعنوان بخشی از ساختار SQL وارد Query نمیشود.
# دریافت اطلاعات با Prepared Statement
فرض کنید میخواهیم کاربری را بر اساس ایمیل پیدا کنیم.
<?php
$email = 'user@example.com';
$stmt = $pdo->prepare(
'SELECT id, name, email
FROM users
WHERE email = :email'
);
$stmt->execute([
'email' => $email
]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
اگر کاربر پیدا شود، نتیجه در متغیر:
$user
قرار میگیرد.
برای بررسی نتیجه:
if ($user) {
echo $user['name'];
} else {
echo 'کاربر پیدا نشد.';
}
# ویرایش اطلاعات در MySQL با PHP
برای ویرایش اطلاعات نیز میتوان از Prepared Statement استفاده کرد.
مثلاً:
<?php
$id = 10;
$name = 'Ali';
$stmt = $pdo->prepare(
'UPDATE users
SET name = :name
WHERE id = :id'
);
$stmt->execute([
'name' => $name,
'id' => $id
]);
در اینجا فقط کاربری که شناسه آن برابر با 10 است تغییر میکند.
# حذف اطلاعات از MySQL با PHP
برای حذف نیز میتوان از همین روش استفاده کرد:
<?php
$id = 10;
$stmt = $pdo->prepare(
'DELETE FROM users
WHERE id = :id'
);
$stmt->execute([
'id' => $id
]);
استفاده از پارامترها باعث میشود مقدار ورودی مستقیماً در SQL قرار نگیرد.
# مدیریت خطا هنگام اتصال PHP به MySQL
در پروژه واقعی بهتر است خطاهای دیتابیس را بهدرستی مدیریت کنیم.
برای PDO میتوان حالت Exception را فعال کرد:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'root',
''
);
$pdo->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
);
حالا میتوان عملیات دیتابیس را داخل try/catch قرار داد:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'root',
''
);
$pdo->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
);
echo 'اتصال موفق بود.';
} catch (PDOException $e) {
echo 'خطا در اتصال به دیتابیس.';
}
در محیط Production نباید جزئیات حساس خطای دیتابیس را مستقیماً به کاربر نمایش دهید.
# charset در اتصال PHP به MySQL
هنگام اتصال به MySQL بهتر است Encoding مناسب را مشخص کنید.
برای مثال:
charset=utf8mb4
استفاده از utf8mb4 برای پروژههایی که با زبان فارسی و محتوای چندزبانه کار میکنند اهمیت زیادی دارد.
نمونه:
$pdo = new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'root',
''
);
این موضوع مخصوصاً برای سایتهایی که محتوای فارسی، انگلیسی و Emoji دارند مهم است.
# اتصال PHP به MySQL با یک کلاس اختصاصی
در پروژههای بزرگ بهتر است کد اتصال دیتابیس را در تمام فایلها تکرار نکنیم.
برای مثال میتوانیم یک کلاس Database ایجاد کنیم:
<?php
class Database
{
public static function connect(): PDO
{
return new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
}
}
سپس:
<?php
$pdo = Database::connect();
$stmt = $pdo->query(
'SELECT * FROM users'
);
$users = $stmt->fetchAll();
البته در پروژههای حرفهای معمولاً این ساختار را میتوان با معماریهایی مانند Repository، Service Layer یا Dependency Injection توسعه داد.
# ساختار بهتر برای پروژههای واقعی
در پروژه ساده ممکن است همه چیز در یک فایل قرار داشته باشد:
index.php
اما با بزرگ شدن پروژه بهتر است مسئولیتها جدا شوند.
برای مثال:
project/
│
├── config/
│ └── database.php
│
├── src/
│ ├── Database/
│ ├── Repository/
│ ├── Service/
│ └── Models/
│
├── public/
│ └── index.php
│
└── vendor/
در چنین ساختاری:
Database
مسئول ارتباط با دیتابیس است.
Repository
میتواند مسئول عملیات مربوط به دادهها باشد.
Service
منطق تجاری برنامه را مدیریت میکند.
و:
Controller
در صورت استفاده از معماری MVC میتواند درخواست کاربر را مدیریت کند.
# PHP و MySQL در معماری MVC
در یک برنامه MVC معمولاً ارتباط PHP با MySQL مستقیماً داخل View انجام نمیشود.
ساختار ساده میتواند به شکل زیر باشد:
Request
↓
Controller
↓
Service
↓
Repository
↓
MySQL
و سپس:
MySQL
↓
Repository
↓
Service
↓
Controller
↓
View
این تفکیک باعث میشود کد برنامه قابل نگهداریتر و تستپذیرتر شود.
# PHP و MySQL در Laravel
اگر بعداً وارد Laravel شوید، معمولاً مستقیماً با PDO Queryهای خام کار نخواهید کرد.
Laravel ابزارهایی مانند:
- Eloquent ORM
- Query Builder
- Migration
- Model
- Relationship
- Database Transactions
را در اختیار شما قرار میدهد.
برای مثال در Laravel میتوانید بنویسید:
$users = User::where('status', 'active')->get();
اما در نهایت Laravel نیز برای ارتباط با دیتابیس از لایههای PHP و Driverهای مربوط به دیتابیس استفاده میکند.
به همین دلیل یادگیری ارتباط PHP با MySQL قبل از یادگیری Eloquent میتواند درک شما از لایه دیتابیس Laravel را بهتر کند.
# SQL Injection و PHP و MySQL
یکی از مهمترین مشکلات امنیتی هنگام کار با دیتابیس، SQL Injection است.
فرض کنید این کد را داریم:
$email = $_GET['email'];
$sql = "SELECT * FROM users WHERE email = '$email'";
در این حالت ورودی کاربر مستقیماً وارد Query شده است.
این روش خطرناک است.
راهکار مناسب استفاده از Prepared Statement است:
$stmt = $pdo->prepare(
'SELECT * FROM users WHERE email = :email'
);
$stmt->execute([
'email' => $email
]);
Prepared Statement برای پارامترهای ورودی روش استاندارد و مهمی برای جلوگیری از SQL Injection است.
# آیا استفاده از PDO بهتنهایی امنیت برنامه را تضمین میکند؟
خیر.
استفاده از PDO یا Prepared Statement بسیار مهم است، اما امنیت یک برنامه فقط به نحوه اجرای Query محدود نمیشود.
برای یک برنامه PHP امن باید مواردی مانند موارد زیر نیز در نظر گرفته شوند:
- اعتبارسنجی ورودیها
- کنترل دسترسی کاربران
- مدیریت صحیح Session
- ذخیره امن رمز عبور
- جلوگیری از XSS
- جلوگیری از CSRF
- مدیریت صحیح خطاها
- محدود کردن دسترسی دیتابیس
- نگهداری امن اطلاعات اتصال
- استفاده از HTTPS
- بهروزرسانی PHP و وابستگیها
# اطلاعات اتصال MySQL را کجا قرار دهیم؟
نباید اطلاعات حساس دیتابیس را در فایلهای عمومی یا داخل Git قرار دهید.
مثلاً بهتر است اطلاعاتی مانند:
DB_HOST
DB_DATABASE
DB_USERNAME
DB_PASSWORD
در متغیرهای محیطی نگهداری شوند.
در یک پروژه واقعی میتوان از فایل .env استفاده کرد:
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_database
DB_USERNAME=my_user
DB_PASSWORD=secret
و سپس برنامه PHP این اطلاعات را از محیط دریافت کند.
همچنین فایل .env نباید بهصورت عمومی از طریق وب قابل دسترسی باشد.
# آیا PHP فقط با MySQL کار میکند؟
خیر.
PHP میتواند با پایگاههای داده مختلفی کار کند.
از جمله:
- MySQL
- PostgreSQL
- SQLite
- Microsoft SQL Server
- Oracle
- و سایر سیستمهایی که Driver مناسب PHP برای آنها وجود دارد.
PDO نیز یک API عمومی برای دسترسی به دیتابیس ارائه میکند و Driver مربوط به هر دیتابیس مسئول ارتباط با آن سیستم است.
بنابراین مفهوم اتصال PHP به دیتابیس فقط به MySQL محدود نمیشود.
# تفاوت MySQL و MySQLi چیست؟
این دو اصطلاح را نباید با یکدیگر اشتباه گرفت.
MySQL یک سیستم مدیریت پایگاه داده است.
اما:
MySQLi یک Extension در PHP برای ارتباط با MySQL است.
یعنی:
PHP
↓
MySQLi
↓
MySQL
یا:
PHP
↓
PDO
↓
PDO_MYSQL
↓
MySQL
این تفاوت در پروژههای PHP بسیار مهم است.
# برای PHP و MySQL از چه روشی استفاده کنیم؟
برای پروژههای جدید، مهمترین گزینههایی که باید بشناسید PDO و MySQLi هستند.
اگر پروژه شما فقط با MySQL کار میکند، MySQLi کاملاً قابل استفاده است.
اگر میخواهید API یکپارچهتری برای دسترسی به دیتابیس داشته باشید و احتمال استفاده از Driverهای مختلف برایتان اهمیت دارد، PDO گزینه مناسبی است.
در هر دو حالت، رعایت Prepared Statement و اصول امنیتی اهمیت بیشتری از انتخاب صرف بین این دو API دارد.
# یک نمونه کامل و ساده PHP و MySQL با PDO
در نهایت میتوانیم یک نمونه ساده از عملیات CRUD را کنار هم قرار دهیم.
ابتدا اتصال:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'root',
'',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
ایجاد کاربر:
$name = 'Ali';
$email = 'ali@example.com';
$stmt = $pdo->prepare(
'INSERT INTO users (name, email)
VALUES (:name, :email)'
);
$stmt->execute([
'name' => $name,
'email' => $email
]);
خواندن کاربر:
$stmt = $pdo->prepare(
'SELECT * FROM users
WHERE email = :email'
);
$stmt->execute([
'email' => $email
]);
$user = $stmt->fetch();
print_r($user);
ویرایش کاربر:
$stmt = $pdo->prepare(
'UPDATE users
SET name = :name
WHERE email = :email'
);
$stmt->execute([
'name' => 'Ali Rezaei',
'email' => $email
]);
حذف کاربر:
$stmt = $pdo->prepare(
'DELETE FROM users
WHERE email = :email'
);
$stmt->execute([
'email' => $email
]);
در این مثال چهار عملیات اصلی CRUD را با PDO انجام دادیم:
Create → INSERT
Read → SELECT
Update → UPDATE
Delete → DELETE
# جمعبندی
PHP و MySQL یکی از ترکیبهای مهم در توسعه برنامههای وب هستند. PHP مسئول اجرای منطق برنامه و پردازش درخواستها است و MySQL میتواند اطلاعات ساختاریافته برنامه را ذخیره و مدیریت کند.
برای ارتباط PHP با MySQL دو API مهم وجود دارد:
PDO
MySQLi
در پروژههای جدید، استفاده صحیح از Prepared Statement اهمیت زیادی دارد؛ زیرا قرار دادن مستقیم ورودی کاربر در Query میتواند برنامه را در معرض SQL Injection قرار دهد.
همچنین در پروژههای واقعی بهتر است کد اتصال به دیتابیس، منطق دسترسی به داده و منطق تجاری از یکدیگر جدا شوند.
اگر مسیر یادگیری PHP را ادامه میدهید، بعد از آشنایی کلی با PHP و MySQL، مرحله بعدی یادگیری اتصال PHP به MySQL بهصورت عملی با PDO و MySQLi، اجرای Queryهای مختلف، Fetch کردن نتایج و مدیریت خطاها است.
سوالات متداول
آیا PHP بدون MySQL هم قابل استفاده است؟
بله. PHP یک زبان برنامهنویسی مستقل است و میتواند بدون MySQL نیز برای پروژههای مختلف استفاده شود. MySQL فقط یکی از سیستمهای پایگاه دادهای است که PHP میتواند با آن ارتباط برقرار کند.
PDO بهتر است یا MySQLi؟
هر دو ابزارهای رسمی PHP برای ارتباط با MySQL هستند. PDO API یکپارچهتری برای دسترسی به دیتابیسها ارائه میکند، در حالی که MySQLi مشخصاً برای MySQL طراحی شده است.
آیا PDO جلوی SQL Injection را میگیرد؟
PDO بهتنهایی تضمین امنیت نمیکند، اما استفاده صحیح از Prepared Statement و پارامترهای Query میتواند از SQL Injection ناشی از ورود مستقیم دادههای کاربر به Query جلوگیری کند.
آیا MySQL و MySQLi یکی هستند؟
خیر. MySQL سیستم مدیریت پایگاه داده است، در حالی که MySQLi یک Extension در PHP برای ارتباط با MySQL است.
آیا Laravel هم از MySQL استفاده میکند؟
بله. Laravel میتواند با MySQL و چندین پایگاه داده دیگر کار کند. Laravel لایههای سطح بالاتری مانند Eloquent و Query Builder را برای کار با دیتابیس در اختیار توسعهدهنده قرار میدهد.





