دستور prepare در PHP

چاپ

دستورات آماده برای مقابله با SQL injection ها بسیار کارآمداند.


دستورات آماده (Prepared) و Bind کردن پارامترها

Wiki

با استفاده از دستورات آماده یا Prepared، می توانید یک کوئری یکسان را به تعداد دفعات دلخواه با راندمان بالا اجرا نمایید.

نحوه عملکرد دستورات آماده یا Prepared:

  1. Prepare: با استفاده از این دستور می توانید قالبِ یک کوئری SQL را ایجاد کرده و به پایگاه داده ارسال نمایید. در واقع دلیل استفاده از کلمه قالب در اینجا این است که بجای پارامترهای لازم در کوئری، از علامت سوال (؟) استفاده می کنیم.

    مثال (دستور prepare در PHP)

    INSERT INTO MyGuests VALUES(?, ?, ?)
  2. حالا قالب SQL ارسال شده، توسط پایگاه داده، تجزیه و کامپایل می شود و در ادامه بهینه ساز کوئری (query optimization) روی آن اجرا می شود و در نهایت نتیجه کار بدون اجرا در پایگاه داده ذخیره می شود.
  3. Execute: در ادامه ی اسکریبت، مقادیر لازم را به پارامترهای کوئری مان Bind می کنیم و با استفاده از دستور Execute، کوئری را اجرا می کنیم. اما نکته ای که وجود دارد این است که کوئری ما همچنان در پایگاه داده وجود دارد و می توانیم مجدداً آنرا با پارامترهای جدید اجرا کنیم ...!

روش استفاده از دستورات آماده در مقایسه با اجرای مستقیم کوئری ها دو مزیت اصلی دارد:

Note تزریق SQL یا SQL injection چیست؟
SQL injection زمانی رخ می دهد که شما از کاربر یک ورودی می خواهید ( مثلا نام خانوادگی ، سن و ... ) و کاربر بجای نام، یک دستور MySQL را وارد می نماید و این دستور بدون اطلاع شما بر روی دیتابیس اجرا می شود.

مثال (دستور prepare در PHP)

$username="''; Delete From users";
$query="Select From users where usernamr=$username";
echo $query;

نتیجه کد بالا

Select From users where usernamr= ''; Delete From users

توضیح: همان طور که در کد بالا مشاهده می کنید، ورودی مخرب، باعث می شود که دو کوئری روی پایگاه داده اجرا شود و از آن مهمتر، کوئری دوم است که باعث می شود تا تمام اطلاعات جدول users حذف شود...!


دستورات آماده یا Prepared در MySQLi

Wiki

در مثال زیر،نحوه ی استفاده از دستورات آماده یا Prepared و همچنین نحوه ی Bind کردن پارامترها در MySQLi نشان داده شده است:

مثال(MySQLi with Prepared Statements)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// ایجاد ارتباط به پایگاه داده
$conn = new mysqli($servername, $username, $password, $dbname);

// اطمینان از صحت ارتباط
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}

// تنظیم کوئری و بایند کردن پارامترها با استفاده از دستورات آماده
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);

// تنظیم پارامترها و اجرای کوئری
$firstname = "John";
$lastname = "Doe";
$email = "این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید";
$stmt->execute();

$firstname = "Mary";
$lastname = "Moe";
$email = "این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید";
$stmt->execute();

$firstname = "Julie";
$lastname = "Dooley";
$email = "این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید";
$stmt->execute();

echo "New records created successfully";

$stmt->close();
$conn->close();
?>

توضیح مثال بالا:

"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"

در کوئری مان می توانیم از علامت سوال (؟) استفاده کنیم، این علامت در ادامه با یک عدد صحیح (integer)، رشته (string)، عدد اعشاری (double) یا داده های با اندازه بزرگ (BLOB - Binary Large OBject) جایگزین خواهد شد.

در ادامه نگاهی به تابع ()bind_param خواهیم انداخت:

$stmt->bind_param("sss", $firstname, $lastname, $email);

با استفاده از تابع ()bind_param، می توانیم پارامترها را به کوئری SQL مان Bind کنیم و به پایگاه داده بگوییم که چه پارامترهایی داریم. همچنین با استفاده از آرگومان اول یعنی "sss"، نوع پارامترها را تعیین می کنیم. کاراکتر s به MySQL می گوید که پارمتر ما از نوع رشته (string) است.

نوع آرگومان ها می تواند یکی از چهار گزینه زیر باشد:

برای هر کدام از آرگومان ها، باید یکی از چهار مقدار بالا را تنظیم کنیم.

زمانی که نوع پارامترها را مشخص می کنیم، ریسک تزریقات SQL یا SQL injections توسط هکرها را به حداقل می رسانیم.

Note توجه: اگر قصد دارید که داده ی دریافتی از کاربران را در پایگاه داده ذخیره کنید، اعتبارسنجی داده ها یک امر بسیار مهم است.

دستورات آماده یا Prepared در PDO

Wiki

در مثال زیر،نحوه ی استفاده از دستورات آماده یا Prepared و همچنین نحوه ی Bind کردن پارامترها در PDO نشان داده شده است:

مثال(PDO with Prepared Statements)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";

try {
//ایجاد ارتباط
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// تنظیم حالت برخورد با خطاها
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// تنظیم کوئری و بایند کردن پارامترها با استفاده از دستورات آماده
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (:firstname, :lastname, :email)");
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->bindParam(':email', $email);

// تنظیم پارامترها و اجرای کوئری
$firstname = "John";
$lastname = "Doe";
$email = "این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید";
$stmt->execute();

// تنظیم پارامترها و اجرای کوئری
$firstname = "Mary";
$lastname = "Moe";
$email = "این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید";
$stmt->execute();

// تنظیم پارامترها و اجرای کوئری
$firstname = "Julie";
$lastname = "Dooley";
$email = "این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید";
$stmt->execute();

echo "New records created successfully";
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>

برای مشاهده فیلم ها و آموزش های پروژه محور برنامه نویسی PHP کلیک کنید.