تابع store_result() در PHP
تابع store_result() در اکستنشن MySQLi برای ذخیره (buffer) نتایج یک عبارت آماده (prepared statement) در سمت کلاینت استفاده میشود. این تابع بهویژه زمانی مفید است که لازم دارید تعداد ردیفها را بدانید، یا از اتصال برای اجرای کوئری دیگری قبل از خواندن کامل نتایج فعلی استفاده کنید.
وقتی باید از store_result() استفاده کنید
- میخواهید num_rows را از یک عبارت آماده بخوانید.
- نیاز دارید همه نتایج را بلافاصله در حافظه کلاینت بارگذاری کنید تا بتوانید همزمان کوئری دیگری ارسال کنید.
- در محیطهایی که
get_result()در دسترس نیست (مثلاً mysqlnd مورد استفاده قرار نگرفته)، از این روش برای دسترسی ایمنتر به تعداد ردیفها استفاده میکنید.
تفاوت با get_result() و buffering/unbuffered
در MySQLi دو راه عمده برای دسترسی به نتایج prepared statement وجود دارد:
- store_result(): تمامی ردیفها را در حافظه کلاینت قرار میدهد (buffered).
- get_result() (نیاز به mysqlnd): یک شیء
mysqli_resultبازمیگرداند که API مشابه کوئریهای عادی دارد.
اگر دادهها بسیار بزرگ هستند، buffering میتواند مصرف حافظه را افزایش دهد. در این حالت میتوان بدون store_result و با خواندن تدریجی (fetch) ردیفها، از حافظه کمتری استفاده کرد اما باید مطمئن شد قبل از اجرای کوئری جدید روی همان اتصال، نتایج فعلی خوانده یا آزاد شوند.
مثال پایهای: استفاده شیءگرا
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$stmt = $mysqli->prepare('SELECT id, name FROM users WHERE status = ?');
$status = 'active';
$stmt->bind_param('s', $status);
$stmt->execute();
// ذخیره نتایج در کلاینت
$stmt->store_result();
// دسترسی به تعداد ردیفها
$rows = $stmt->num_rows;
// اتصال و واکشی مقادیر
$stmt->bind_result($id, $name);
while ($stmt->fetch()) {
printf("ID: %d, Name: %sn", $id, $name);
}
// آزادسازی منبع
$stmt->free_result();
$stmt->close();
$mysqli->close();
در این مثال ابتدا عبارت آماده اجرا میشود، سپس store_result() صدا زده میشود تا همه ردیفها در حافظه کلاینت قرار گیرند. پس از آن میتوان تعداد ردیفها را از $stmt->num_rows خواند، سپس با bind_result و fetch مقادیر را دریافت کرد. در انتها با free_result() حافظه آزاد میشود.
مثال دستوری (procedural)
$link = mysqli_connect('localhost', 'user', 'pass', 'db');
$stmt = mysqli_prepare($link, 'SELECT id, email FROM customers WHERE active = ?');
$active = 1;
mysqli_stmt_bind_param($stmt, 'i', $active);
mysqli_stmt_execute($stmt);
// ذخیره نتایج
mysqli_stmt_store_result($stmt);
$count = mysqli_stmt_num_rows($stmt);
mysqli_stmt_bind_result($stmt, $id, $email);
while (mysqli_stmt_fetch($stmt)) {
echo "Customer $id: $emailn";
}
mysqli_stmt_free_result($stmt);
mysqli_stmt_close($stmt);
mysqli_close($link);
نسخه دستوری عینا همان کار را انجام میدهد ولی با توابع پروسیجرال. توجه کنید متدها و توابع نامگذاری مشابه دارند.
نکات عملکردی و حافظه
- store_result همه ردیفها را در حافظه کلاینت بارگذاری میکند؛ برای نتایج بسیار بزرگ ممکن است حافظه زیادی مصرف شود.
- اگر نمیخواهید تمام نتایج را به خاطر بسپارید، میتوانید از روش streaming استفاده کنید و بدون صدا زدن store_result ردیفها را یکییکی بخوانید.
- برای خواندن
num_rowsباید از store_result یا get_result استفاده کنید؛ بدون آنها مقدار num_rows معتبر نخواهد بود. - حتما بعد از اتمام کار
free_result()یاclose()را فراخوانی کنید تا منابع آزاد شوند.
اشتباهات رایج و رفع آنها
- فراخوانی
num_rowsقبل ازstore_result()که عدد نادرست برمیگرداند. - فراموش کردن
free_result()که منجر به لوک حافظه میشود. - استفاده از store_result روی مجموعه دادههای بسیار بزرگ بدون بررسی حافظه در سرور/کلاینت.
مقایسه سریع — جدول مزایا و معایب
| روش | مزایا | معایب |
|---|---|---|
| store_result() | قابلیت خواندن num_rows، امکان اجرای کوئریهای بعدی بدون انتظار | مصرف حافظه بالاتر برای نتایج بزرگ |
| بدون store (streaming) | مصرف حافظه کمتر، مناسب دادههای بزرگ | نمیتوانید قبل از خواندن کامل نتایج کوئری دیگری روی همان اتصال اجرا کنید |
| get_result() | API مشابه mysqli_result، راحت برای استفاده (نیاز به mysqlnd) | نیازمند mysqlnd، ممکن است روی برخی محیطها در دسترس نباشد |
نکات پیشرفته و بهترین شیوهها
- برای صفحات وب که نیاز به پیمایش (pagination) دارند، ترکیب LIMIT با store_result منطقی است چون سِت داده کوچکتر است.
- برای پردازش دستهای (batch processing) دادههای بسیار بزرگ، از streaming استفاده کنید تا حافظه مصرفی کنترل شود.
- در برنامههای CLI یا سرویسهای بکاند که حافظه کافی دارند، store_result به سادهشدن منطق کمک میکند و خواندن تعداد ردیفها را سریع میکند.
- همواره بررسی کنید که mysqlnd فعال است یا خیر؛ اگر هست، get_result امکانات بیشتری در اختیارتان میگذارد.
نتیجهگیری
تابع store_result() برای موقعیتهایی که نیاز به بافر کردن نتایج در کلاینت و خواندن ویژگیهایی مثل num_rows دارید، ابزار مناسبی است. اما برای دادههای بزرگ باید احتیاط کنید و بین بافر کردن یا خواندن تدریجی یکی را انتخاب کنید. آگاهی از وضعیت mysqlnd و استفاده درست از free_result() و close() از نکات کلیدی در استفاده صحیح از این تابع هستند.
در صورت نیاز میتوان مثالهای بیشتری شامل مدیریت خطا، استفاده در ترکیب با transaction و مثالهای real-world برای بهینهسازی حافظه آماده کرد.
آیا این مطلب برای شما مفید بود ؟



