آموزش MySQLi در PHP شیء گرا

یکی از روش‌های اتصال به دیتابیس در PHP روش MySQLi است. در این آموزش با نحوه اتصال به پایگاه داده با MySQLi در PHP آشنا می‌شویم. ۲ مثال عملی را با هم پیاده‌سازی کرده و یاد می‌گیریم چطوری اطلاعاتی را فراخوانی کرده یا آن‌ها ذخیره کنیم.

در آموزش اتصال به دیتابیس PHP در مورد فرآیند کلی اتصال به پایگاه داده بحث کردیم. در آن آموزش از تابع‌های MySQLi (روش رویه‌ای یا Procedural) استفاده کردیم.

روش MySQLi را می‌توان به صورت شیءگرا (Object Oriented) نیز استفاده کرد. در کل، پیشنهاد می‌کنم اگر اجبار خاصی در استفاده از روش تابعی ندارید، از روش‌های شیء گرا استفاده کنید.

آموزش MySQLi

اگر نمی‌دانید برای کار با دیتابیس باید چه فرآیندی را طی کنیم، آن را خیلی خلاصه با هم مرور می‌کنیم. ابتدا باید به سرویس‌دهنده (یا سرور) پایگاه داده متصل شویم. سپس دستورهای مورد نظرمان را در آن اجرا کنیم.

بعضی از این دستورها می‌توانند یک نتیجه به همراه داشته باشند. مثلاً برای ذخیره اطلاعات یک فرد در دیتابیس، هیچ خروجی خاصی (غیر از نتیجه) نداریم؛ اما برای گرفتن لیست دانشجویان یک درس باید این اطلاعات را استخراج کنیم و نمایش دهیم.

هر سرور دیتابیس یک واسطی ارائه می‌کنند که به کمک آن می‌توانیم دستورهای خودمان را اجرا کنیم. اینکه این واسط چطور عمل می‌کند فعلاً موضوع بحث ما نیست.

روش MySQLi در PHP به سرورهای MySQL متصل شده و می‌توانند با واسط‌های آن کار کنند. برای کار با این دیتابیس بهتر است با زبان SQL آشنا باشیم. البته در این آموزش چند مثال ساده می‌زنیم. پس نگران نباشید. 🙂

در ادامه این گام‌ها را انجام می‌دهیم:

  1. اتصال به دیتابیس
  2. اجرای دستور در دیتابیس
  3. فراخوانی داده از دیتابیس با mysqli

اتصال به دیتابیس MySQLi

برای اتصال به پایگاه داده باید یک شیء از نوع MySQLi ایجاد کنیم. پارامترهای ورودی سازنده این شئ، اطلاعات دیتابیس ما خواهد بود. پارامترها به ترتیب عبارت‌اند از:

  1. آدرس سرور دیتابیس (اگر دیتابیس روی همین سرور است، مقدار localhost یا 127.0.0.1 وارد می‌کنیم.)
  2. نام کاربری وصل شدن به database
  3. رمز عبور
  4. نام دیتابیس اسکریپت ما

اگر هیچ دیتابیسی نساخته‌اید و قرار است با دستورات SQL آن را ایجاد کنید، می‌تواند پارامتر چهارم را تعریف نکنید.

$conn = new mysqli('localhost', 'user', 'pass', 'db_name');

در مورد کلمه کلیدی new و کلاس‌ها در جلسه تعریف کلاس PHP صحبت کرده‌ام. اگر با این مفاهیم آشنا نیستید، می‌توانید به جلسه‌اش مراجعه کنید.

یادتان باشد که اگر سرور MySQL شما از پورت پیشفرض استفاده نمی‌کند، باید پورت آن را مشخص کنید. (مثل localhost:3306)

اگر مشکلی در اتصال به سرور وجود نداشته باشد، شئ $conn حاوی ارتباط ما خواهد شد؛ پس آن را نگه می‌داریم تا جلوتر از آن استفاده کنیم.

اگر خطایی وجود داشته باشد، متناسب با نوع خطا و سطح گزارش خطای PHP، ممکن است با خطا مواجه شویم. با این حال، می‌توانیم از ویژگی connect_errno برای گرفتن نوع خطای اتصال استفاده کنیم. ویژگی $conn->connect_error نیز متن خطا را به ما می‌دهد.

اگر خطایی نباشد، این عدد صفر است؛ در غیر این‌صورت یک عدد مثبت متناسب با نوع خطای ماست.

if($conn->connect_errno > 0){
    die('خطا در ارتباط: ' . $conn->connect_error);
}

از بحث برنامه نویسی شیء گرا می‌دانیم که اشیاء دارای ویژگی‌ها و متدهایی هستند. ویژگی معمولاً یک مقدار است و متدها مشابه تابع هستند. در روش‌های شئ گرا از این مفاهیم زیاد استفاده می‌کنیم.

اجرای دستور با MySQLi در PHP

دو روش کلی برای اجرای دستورات در MySQLi داریم. متد query() کوئری را مستقیماً اجرا می‌کند؛ بنابراین برای اجرای دستورهای ساده یا از پیش تعریف شده مناسب است. در روش دوم از متد prepare() برای ایجاد یک عبارت آماده استفاده می‌کنیم تا کوئری‌های متغیر را اجرا کنیم.

یادآوری: به دستورهای SQL اصطلاحاً کوئری (Query) گفته می‌شود.

اجرای Query روی پایگاه داده

برای اجرای مستقیم یک دستور در دیتابیس می‌توانیم از متد query() استفاده کنیم. ورودی این متد یک رشته متنی PHP است که همان کوئری (دستور SQL) است.

در قطعه کد زیر، یک کوئری ساده برای انتخاب اطلاعات ستون نام و نمره دانشجویان در جدول scores را با mysqli در php اجرا می‌کنم:

$query = "SELECT name, score FROM `scores`";

$result = $conn->query( $query );

برای یادگیری ساختار این کوئری و موارد مشابه، آموزش دستور SELECT در SQL را پیشنهاد می‌کنم.

درصورتی‌که مشکلی در اجرای کوئری نباشد، نتایج اجرای دستور در متغیر $result قرار می‌گیرد. اگر خطا داشته باشیم، مقدار آن false می‌شود. پس می‌توانیم با یک ساختار شرطی PHP مطمئن شویم خطایی وجود ندارد.

if( ! $result ){
    die('خطا در اجرای کوئری: ' . $conn->error);
}

نمایش نتایج در MySQLi

در هر بار فراخوانی متد fetch_row() یک سطر از نتایجی که از دیتابیس گرفته شده (در اینجا اسم و نمره هر دانشجو) به ما داده می‌شود. این داده‌ها به شکل آرایه است و اندیس هر ستون به همان ترتیبی است که در کوئری تعریف کرده‌ایم.

$row = $result->fetch_row();
print_r($row);

از print_r() که در آموزش پرینت در php معرفی شده برای نمایش ساختار آرایه استفاده کرده‌ام. چیزی که در $row قرار می‌گیرید مشابه تصویر زیر است:

نمونه دیتای واکشی با fetch_row
نمونه دیتای واکشی با fetch_row

وقتی از متد fetch_assoc() استفاده می‌کنیم، مشابهاً یک سطر از نتایج به ما برگردانده می‌شود با این تفاوت که آرایه به‌صورت انجمنی است؛ یعنی می‌توانیم از اندیس‌های مشابه نام ستون‌ها استفاده کنیم.

$row = $result->fetch_assoc();
print_r($row);
نمونه خروجی fetch_assoc در mysqli
نمونه خروجی fetch_assoc در mysqli

اگر با انواع آرایه و روش‌های کار با آن‌ها آشنا نیستید، جلسه کار با آرایه در PHP را ببینید.

مثال MySQLI

کوئری مثال را طوری تغییر می‌دهیم که فقط دانشجویان با نمره بالاتر از 17 را به من برگرداند. در قطعه کد زیر، ابتدا به دیتابیس وصل و کوئری را اجرا می‌کنم. سپس با یک حلقه PHP تمام سطرهای واکشی‌شده را در لیست نمایش می‌دهم.

<?php
$conn = new mysqli('localhost', 'user', 'pass', 'sabzdanesh_db');

$result = $conn->query( "SELECT name, score FROM `scores` WHERE `score` > 17" );

echo "<ul>";
while( $row = $result->fetch_assoc() ){
    echo "<li>" . $row['name'] . "(" .$row['score'] . ")</li>";
}
echo "</ul>";

?>

وقتی هیچ سطر دیگری برای نمایش وجود نداشته باشد، نتیجه هر دو متد fetch در mysqli مقدار بولین false می‌شود. پس می‌توانیم از آن به‌عنوان شرط حلقه نیز استفاده کنیم. (یعنی تا زمانی که داده‌ای برای نمایش هست، آن را در لیست نمایش بده)

ذخیره با MySQLi در PHP

برای ذخیره اطلاعات در دیتابیس صرفاً باید دستور SQL را تغییر دهیم. در قطعه کد زیر، دانشجوی «الهام» را با نمره 18.5 در جدول ذخیره می‌کنم:

<?php
$conn = new mysqli('localhost', 'user', 'pass', 'sabzdanesh_db');

$result = $conn->query( "INSERT INTO scores (name, score) VALUES ('elham', 18.5)" );

if($result){
    echo "با موفقیت افزوده شد.";
}else{
    echo "مشکلی در ذخیره اطلاعات به وجود آمده!";
}
?>

عبارت آماده برای ذخیره در دیتابیس

تقریباً نیمی از اوقات نیاز داریم کوئری‌های mysqli را با مقادیری که از کاربران گرفته‌ایم تکمیل کنیم. (مثل کار با فرم PHP)

فرض کنید یک فرم داریم که نمره مورد نظر را از کاربر گرفته و لیست دانشجویانی که نمره‌شان بالاتر از آن نمره است را نمایش می‌دهد. اینجا در حال استفاده از مقدار ورودی کاربران در کوئری خود هستیم.

من همیشه می‌گویم: «در توسعه و برنامه‌نویسی یک برنامه، هیچ وقت به کاربر اعتماد نکنید!» 😉

کاربران ممکن است عمداً یا سهواً داده‌های مخربی را در این فرم وارد کنند. اگر بدون ایمن‌سازی از آن‌ها استفاده کنیم، ممکن است کوئری اشتباه (یا مخرب) روی سایتمان اجرا شود. (به این روش اصطلاحاً حمله SQL Injection می‌گویند.)

روش عبارت آماده‌شده (Prepared Statement) در MySQLi به ما کمک می‌کند تا از این حملات جلوگیری کنیم. به این صورت که مقادیر مشکوک را جداگانه به کوئری می‌دهیم. موقع تعیین این مقادیر، MySQLi خودش آن‌ها را ایمن‌سازی کرده و از کدهای مخرب پاکسازی می‌کند.

برای این کار، به جای مقادیر متغیر علامت سؤال (?) قرار می‌دهیم و به جای متد query از prepare() استفاده می‌کنیم.

<?php
$statement = $conn->prepare("SELECT name, score FROM `scores` WHERE `score` > ?");

برای پاس دادن مقادیر از متد bind() روی $statement استفاده می‌کنیم. این متد دو ورودی می‌گیرد؛ اولی نوع و دومی مقدار متغیری را مشخص می‌کند.

$statement->bind_param( 'i', $_POST['score'] );

در این مثال فرض کردم که مقدار دریافتی کاربر از فرم با روش POST ارسال شده است. (بیشتر بدانید: روش get و post در php)

آرگومان اول می‌تواند مقادیر زیر را بگیرید:

کاراکترمعادل
sstring
iinteger
ddouble

با صدا زدن متد execute() کوئری خود را اجرا می‌کنیم.

$statement->execute();

حالا اگر به نتیجه کوئری (اطلاعات select شده) نیاز داشتیم، شبیه خط زیر، آن‌ها را درون $result قرار داده و مشابه قبل fetch می‌کنیم:

$result = $statement->get_result();

وقتی کارمان تمام شد، از close() یا free_result() برای پاک‌سازی نتایج و پایان عبارت آماده استفاده می‌کنیم.

$statement->close();  // OR: $statement->free_result();

۲ نکته کاربردی mysqli در PHP

اولین نکته اینکه در روش mysqli ویژگی‌ها و متدهای بسیار بیشتری داریم. تا اینجا با مهم‌ترین‌ها آشنا شدیم. در جدول زیر ۳ مورد پرکاربرد را برایتان آورده‌ام. برای دیدن موارد بیشتر می‌توانید به مستندات آن مراجعه کنید.

نمونه دستورخروجی
$result->num_rowsتعداد سطرهای نتیجه
$result->inesrt_idid آخرین سطری که insert شده
$result->fetch_all()همه سطرها در یک آرایه

نکته دوم اینکه همیشه سعی کنید وقتی کارتان با دیتابیس تمام شد، ارتباطی که در ابتدا باز کرده بودید را ببندید. برای این کار از متد close() استفاده می‌کنیم.

$conn->close();

در این آموزش سعی کردم شما را با روش MySQLi شیء گرا در PHP آشنا کنم. همین الآن یک کوئری برای واکشی و یکی برای ذخیره دیتا در دیتابیس با این روش اجرا کنید تا روند آن یادتان بماند. 🙂

اگر سؤال یا تجربه‌ای در این مورد دارید، از بخش دیدگاه‌ها با ما و دوستانتان به اشتراک بذارید.

این آموزش بخشی از یک آموزش جامع و قدم به قدم در سبز دانش است: دوره رایگان آموزش PHP