ویژگی تصویر

تابع real_query() در PHP

  /  PHP   /  تابع real_query() در PHP
بنر تبلیغاتی الف
آموزش PHP

تابع real_query() از افزونه MySQLi در PHP برای ارسال مستقیم یک دستور SQL به سرور MySQL استفاده می‌شود، بدون این که نتیجه به صورت خودکار بازیابی و به صورت یک شیء mysqli_result برگردانده شود. این تابع سطح پایین‌تر از query() است و کنترل بیشتری روی نحوهٔ بازیابی نتایج یا مدیریت حافظه به برنامه‌نویس می‌دهد.

چرا و چه زمانی از real_query() استفاده کنیم؟

  • وقتی می‌خواهید ابتدا دستور را ارسال کنید و سپس به‌صورت جداگانه نتایج را دریافت یا استریم کنید (مثلاً use_result() برای نتایج حجیم).
  • برای اجراهای تک‌دستور که نتیجه‌ای برنمی‌گردانند (INSERT, UPDATE، حذف) و شما فقط به وضعیت اجرای دستور نیاز دارید.
  • برای کاهش مصرف حافظه در مقابل store_result() که تمام نتایج را در حافظه کلاینت بار می‌کند.
  • در پیاده‌سازی‌هایی که نیاز به کنترل دقیق‌تر بر خطاها یا وضعیت اتصال دارند.

تفاوت real_query() با query()

ویژگیmysqli::query()mysqli::real_query()
رفتار کلیارسال + بازیابی نتیجه و بازگردانی mysqli_result یا boolفقط ارسال دستور (بازگردانی true/false)، بازیابی جداگانهٔ نتیجه
مصرف حافظهمعمولاً بیشتر (buffered)قابل کنترل: می‌توانید use_result() برای استریم استفاده کنید
امنیت پارامترهامشابه — اگر پارامترها مستقیماً داخل رشته قرار گیرند ریسک SQL Injection داردمشابه — بهتر است از prepared statements استفاده کنید

مثال‌های عملی

مثال 1 — روش شیءگرایانه: ارسال دستور و استفاده از use_result برای استریم

$mysqli = new mysqli("localhost", "user", "pass", "db");

if ($mysqli->connect_errno) {
    die("Connect failed: " . $mysqli->connect_error);
}

$sql = "SELECT id, name, email FROM users";
if ($mysqli->real_query($sql)) {
    $result = $mysqli->use_result(); // استریم نتایج از سرور
    while ($row = $result->fetch_assoc()) {
        echo $row['id'] . " - " . $row['name'] . "n";
    }
    $result->free();
} else {
    echo "Query error: " . $mysqli->error;
}

$mysqli->close();

در این کد ابتدا اتصال برقرار می‌شود، سپس با real_query() دستور ارسال می‌شود. برای بازیابی نتایج از use_result() استفاده شده که باعث می‌شود ردیف‌ها به صورت جریان (stream) از سرور خوانده شوند و حافظهٔ کلاینت کم مصرف شود. در پایان، نتیجه آزاد و اتصال بسته می‌شود.

مثال 2 — نسخهٔ متد پروسیجرال با mysqli_real_query و mysqli_store_result

$link = mysqli_connect("localhost", "user", "pass", "db");
if (!$link) {
    die("Connect failed: " . mysqli_connect_error());
}

$sql = "SELECT * FROM large_table";
if (mysqli_real_query($link, $sql)) {
    $res = mysqli_store_result($link); // نتایج را کامل ذخیره می‌کند (buffered)
    while ($row = mysqli_fetch_assoc($res)) {
        // پردازش ردیف
    }
    mysqli_free_result($res);
} else {
    echo "Error: " . mysqli_error($link);
}

mysqli_close($link);

در این مثال از تابع پروسیجرال mysqli_real_query استفاده شده و سپس با mysqli_store_result تمام نتایج در کلاینت ذخیره شده‌اند. این روش برای جدول‌های کوچک مناسب است ولی برای مجموعه‌های بزرگ حافظهٔ بیشتری مصرف می‌کند.

نکات کلیدی فنی و بهترین شیوه‌ها

  • نظافت نتایج: پس از استفاده از use_result() یا store_result() حتماً نتیجه را با free() آزاد کنید؛ تا نتایج قبلی مانع اجرای کوئری بعدی نشوند.
  • عدم استفاده برای پارامترها: تابع real_query() خودش امکانات پارامتردهی ندارد؛ برای جلوگیری از SQL Injection از prepared statements (prepare/stmt_execute) استفاده کنید.
  • ارزیابی خطا: بعد از فراخوانی real_query() مقدار بازگشتی را بررسی کنید و در صورت خطا از $mysqli->errno و $mysqli->error برای اشکال‌زدایی استفاده کنید.
  • مطابقت با multi_query: اگر قصد اجرای چند دستور پشت‌سرهم دارید از multi_query() استفاده کنید؛ real_query() تنها یک دستور را ارسال می‌کند.

نمونه‌ای که باید به prepared statement تبدیل شود

// ناامن: احتمال SQL Injection
$name = $_GET['name'];
$sql = "SELECT * FROM users WHERE name = '$name'";
$mysqli->real_query($sql);

این نمونه آسیب‌پذیر است زیرا ورودی کاربر مستقیم داخل رشته SQL قرار می‌گیرد. بهتر است از prepared statement استفاده شود. کد اصلاح‌شده در پایین آمده است.

$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    // پردازش
}
$stmt->close();

در نسخهٔ اصلاح‌شده پارامترها ایمن شده‌اند و از SQL Injection جلوگیری می‌شود. اگرچه این مثال از real_query() استفاده نمی‌کند، اما در کاربردهای واقعی امنیت مهم‌تر از استفادهٔ صرف از یک تابع سطح پایین است.

جمع‌بندی و توصیه‌ها

تابع real_query() ابزار مفیدی برای کنترل دقیق روی ارسال دستور SQL و شیوهٔ بازیابی نتایج است. مخصوصاً زمانی که با مجموعه‌های بزرگ داده سروکار دارید یا می‌خواهید استریمینگ نتایج را مدیریت کنید، این تابع برتری نشان می‌دهد. با این حال، برای اجرای کوئری‌هایی که شامل پارامترهای ورودی هستند، همیشه از prepared statements استفاده کنید. همچنین تفاوت‌های فنی با query() و نکات مربوط به use_result() و store_result() را در نظر داشته باشید تا کارایی و ایمنی کدتان افزایش یابد.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: