سبد (0)

تبلیغات

دستور 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، کوئری را اجرا می کنیم. اما نکته ای که وجود دارد این است که کوئری ما همچنان در پایگاه داده وجود دارد و می توانیم مجدداً آنرا با پارامترهای جدید اجرا کنیم ...!

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

  • دستورات آماده، زمان تجزیه (parsing) کوئری را کاهش می دهند و این در حالی است که برای مواقعی که قصد داریم یک کوئری را به دفعات اجرا کنیم، این زمان فقط یکبار محاسبه خواهد شد.
  • از آنجایی که برای هر بار اجرای کوئری، فقط باید پارامترها را ارسال کنیم، بنابراین پهنای باند کمتری مصرف خواهد شد.
  • دستورات آماده برای مقابله با SQL injection ها بسیار کارآمد هستند و این بخاطر استفاده از یک پروتوکول متفاوت برای انتقال مقادیر پارامترهاست.
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) است.

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

  • i - integer
  • d - double
  • s - string
  • b - BLOB

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

زمانی که نوع پارامترها را مشخص می کنیم، ریسک تزریقات 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 کلیک کنید.

دیدگاه‌ها  

0 # dada 1396-05-15 12:10
لطفا جواب بدید: من نمیفهمم، چرا در تابع bind_param، باید در پارامتر اول نوع داده ها رو مشخص کنیم...!؟ مگر نه اینکه هر ستون جدول خودش یه data type دارد.
i - integer
d - double
s - string
b - BLOB
چه معنی میده؟
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن
+1 # امیر پهلوان صادق 1396-05-16 08:52
زمانی که نوع پارامترها را مشخص می کنیم، ریسک تزریقات SQL یا SQL injections توسط هکرها را به حداقل می رسانیم.
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن
0 # arash101 1395-02-25 19:41
سلام و خسته نباشید ، برای نوع date چه آرگومانی باید استفاده بشه؟
اگه جواب بدین ممنون میشم
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن
0 # مهرداد صلاحی 1395-02-27 15:47
با سلام و تشکر.
منظورتون چیه دقیقا؟
در PHP از تابع date برای نمایش تاریخ استفاده میشه. میتونیم نمایش تاریخ رو بر اساس فرمت دلخواه تنظیم کنیم. این فرمت رو میتونید از سایت php.net ببینید.
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن
+2 # محمد 1394-01-15 22:22
با عرض سلام و خسته نباشید
ببخشید من مشکلی در استفاده از bind_param دارم که وقتی کد رو اجرا میکنم با این خطا مواجه میشم همه چی رو هم چند بار نگاه کردم مشکلی جایی نداشتم ولی بازم این خطای زیر رو میده:

fatal_error: call to a member function bind_param() on boolean in c:\xampp\htdacs \project\includ es\register.php on line 36

نمیدونم چرا این متد رو نمیشناسه!
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن
+3 # امیر پهلوان صادق 1394-01-16 08:31
سلام
متد ()prepare می تواند یک مقدار false را برگرداند و بخاطر همین باید مقدار برگشتی را چک کنید. شاید نام جدول یا ستون ها در دستور Select و یا قسمت Where صحیح نیست ...!
if ($stmt = $conn->prepare( "SELECT u_id FROM users WHERE u_username=? and u_password=?"))
{
//بایند کردن پارامترها
$stmt->bind_par am("ss", $u_username, $u_password);
...
}
از این روش در پروژه رزرو هتل استفاده شده است: www.beyamooz.com/php/339-project-hotel/2594
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن
+3 # mohsen moardi 1393-11-04 21:00
با سلام و خسته نباشيد خدمت شما و تشكر بابت زحماتتان...ببخش يد توي مثال هاي بالا روش MySQLi Procedural وجود نداره...چرا؟اگه ما به صورت MySQLi Procedural پايگاه داده داشته باشيم چطوري بايد از Prepared استفاده كنيم؟
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن
0 # امیر پهلوان صادق 1393-11-05 07:52
سلام ممنون، حتماً به لینک زیر برید و مثال Procedural style را بررسی فرمایید:
php.net/manual/en/mysqli.prepare.php
پاسخ دادن | پاسخ به نقل قول | نقل قول کردن

آموزش صوتی PHP

بستن
مدرس:
سوال و جواب:

ابزاری که در پیش روی دارید یکی از ابزارهای بسیار کاربردی سایت بیاموز در زمینه آموزش است، این ابزار برای سهولت یادگیری شما کاربران محترم طراحی شده است.

فقط کافی است روی عنوان پاراگراف مورد نظرتان کلیک کنید تا پخش صدا آغاز شود ...!

تمامی محصولات و خدمات این وبسایت، حسب مورد دارای مجوزهای لازم از مراجع مربوطه می‌باشند و فعالیت‌های این سایت تابع قوانین و مقررات جمهوری اسلامی ایران است.
logo-samandehi مجوز نشر دیجیتال از وزرات فرهنگ و ارشاد اسلامی پرداخت آنلاین -  بانک ملت معرفی بیاموز در شبکه سه پرداخت آنلاین - بانک اقتصاد نوین پرداخت آنلاین - بانک سامان
 
دوره های آموزشی راه اندازی کسب و کارهای اینترنتی
تبلیغات اینترنتی