Output Buffering در php

خروجی بافر یا همان Output Buffering در php یکی از قابلیت های مهم برای کنترل خروجی اسکریپت php است . کنترل خروجی بر اساس زمان ارسال خروجی به مرورگر , ترتیب خروجی ها و غیره .. . انجام می شود .

به طور پیش فرض , تمام داده های مشخص شده در در دستورات چاپی یا محتویات HTML در اسکریپت PHP به طور تکه تکه به مرورگر ارسال می شود .

اما با استفاده از Output Buffering در php این داده ها در یک متغییر در حافظه بافر ذخیره خواهند شد و در نهایت به صورت یکجا یا همان یک تکه به مرورگر ارسال می شوند.

این قابلیت باعث جلوگیری از خطاهایی مثل header already sent در هنگام استفاده از توابعی مثل ()session_start که در مقاله آموزش کار با SESSION ها در php توضیح دادم می شود

Buffer یا بافر چیست ؟

بافر یک قسمت کوچک از حافضه برای ذخیره سازی موقت داده ها است .

پیکربندی Output Buffering در php

برای کنترل خروجی های یک اسکریپت php توسط بافر , نیاز داریم که Output Buffering را با استفاده از هرکدام از روش های زیر فعال کنیم .

فعال کردن Output Buffering در php از طریق فایل php.ini

سه دستور پیکربندی زیر برای کنترل خروجی بافر استفاده می شوند

هر دو دستور اول در هرکدام از فایل های php.ini , .htacces , httpd.conf یا user.ini می تواند ست شود . و دستور پیکربندی آخر لیست بالا می تواند به هر طریق حتی با تابع ()ini_set ست شود .

فعال کردن Output Buffering از طریق توابع PHP

با ست کردن تنظیمات بالا , نتیجه بر روی تمام اسکریپت های php که بر روی سرور اجرا می شوند , اثر خواهد گذاشت . اما , فعال کردن Output Buffering در php بر روی یک فایل یا پروژه خاص بهتر از آن است که بخواهیم به صورت سراسری تنظیمات را اعمال کنیم .

بنابراین , php شامل توابعی برای کنترل Output Buffering است .این توابع با توضیحات کوتاه در زیر لیست شده اند .

مثال Output Buffering در php

با استفاده از توابع بالا قصد داریم یک مثال را با هم ببینیم.

<?php
ob_start();
print "PHP Output Buffering: level-1<br/>";
ob_end_flush();

ob_start();
print "PHP Output Buffering: level-2<br/>";
ob_flush();

print "Store into recently created buffer on level-2<br/>";
ob_end_flush();
?>

در اسکریپت php بالا , در اولین خط با استفاده از تابع ()ob_start یک بافر ساختیم . و بعد , داده مشخص شده در تابع print در بافر ذخیره شد . پس از آن , تابع ()ob_end_flush را به ترتیب برای ارسال و پاکسازی داده های بافر اجرا کردیم

بعد از آن , دوباره تابع ()ob_start را برای ساخت یک بافر با محتوای داده های دستور print ساختیم . اما این دفعه به جای تابع ()ob_end_flush , تابع ()ob_flush را استفاده کردیم . بنابراین فقط مقدار بافر را برای نمایش ارسال کردیم ولی آن را از بافر حذف نکردیم . بنابراین , سومین دستور print داده ذخیره شده در بافر قبلی را نیز ذخیره می کند.

توابع کنترل Output Buffering در php

به جز توابع اولیه و پایه بالا , php چندین تابع دیگر برای این extension را نیز پشتیبانی می کند . این توابع برای پیاده سازی قابلیت های زیر کاربرد دارد .

حالا اجازه بدید دسته بندی های بالا را به ترتیب بررسی کنیم

خواندن داده ها از خروجی بافر ها

با استفاده از تابع Output Buffering در php , می توانیم اطلاعاتی مثل محتوای بافر , طول داده بافر شده و غیره .. را بدست آوریم.

ساختن پشته (stack) برای خروجی بافر

می توانیم از مثال قبلی برای نحوه ارسال بافر ها به stack یا همان پشته استفاده کنیم .

<?php
ob_start();
print "PHP Output Buffering: level-1<br/>";

ob_start();
print "PHP Output Buffering: level-2<br/>";

ob_end_flush();
?>

stack یکی از سه بخش تخصص یافته به یک برنامه در حافظه RAM است .ساختمان داده های stack به صورت LIFO عمل می کند.(Last in First Out)

این نوع تکنیک به این معناست که آخرین دیتای ورودی اول از همه خارج می شود .(روش LIFO و FIFO در حسابداری موجودی کالا نیز استفاده می شود.)

حتما بخوانید  تفاوت بین آرایه ها در php

اگر یک بافر را با فراخوانی تابع ()ob_start بسازیم , پس از آن هر بافر ساخته شده به حافظه stack در بالای بافر قبلی قرار می گیرد . برای مثال :

فشرده سازی داده ذخیره شده در بافر

در php , خروجی دیتای بافر شده با مشخص کردن مقدار ob_gzhandler به عنوان آرگومان تابع ()ob_start فشرده سازی خواهد شد . ()ob_gzhandler یک تابع از پیش ساخته (in-built) در php است که به عنوان تابع بازگشتی (callback) استفاده کردیم. با کمک این تابع بازگشتی , php داده فشرده شده را به مرورگر ارسال خواهد کرد.

طبیعتا کمی زمان برای فشرده کردن داده خروجی صرف خواهد شد , این زمان توسط مروگر برای دانلود دیتای فشرده شده جبران خواهد شد .

URL Rewriting

دو تابع برای کنترل Output Buffering در php هنگام کار با URL Rewritng وجود دارد که به صورت زیر است .

نکته :

Php به طور خودکار قادر است عملیات ارسال داده های خروجی بافر را تا زمان رسیدن به پایان خط php انجام دهد حتی اگر هیچ تابع output bufferingی مشخص نشده باشد !

با استفاده از Output Buffering در php , می توانید جلوی خطاهایی که مربوط به ارسال داده قبل از اجرای کدهای session یا ()setcookie می شود , را بگیرد.

 

بافرهای تو در تو (nested)

بافرها در PHP می توانند بصورت تو در تو (Nested) باشند. بنابراین زمانی که یکی از بافرها فعال است, یک ()ob_start دیگر یک بافر جدید را فعال می کند.
بنابراین هر دو تابع ()ob_end_flush و ()ob_flush در واقع هیچ بافری را به خروجی (output) ارسال نمی کنند, اما به بافر والد (parent) بله. و همچنین فقط زمانی هیچ بافر والدی نداریم که محتویات به مرورگر ارسال شده باشد.

بنابراین بسیار مهم است که عملیات بافر را غیرفعال کنیم حتی اگر یک استثنا (exception) رخ دهد.

ob_start();
try {
    $foo->render();
} finally {  //finally exists since PHP 5.5
    ob_end_clean(); // or ob_end_flush()
}

مزایای استفاده از Output Buffering در php این است که

  1. چونکه تمام اطلاعات و مقادیر html به جای اینکه به صورت تکه تکه به مروگر ارسال شود , در یک متغیر ذخیره و به صورت یکجا ارسال می شود که در نهایت باعث افزایش سرعت درخواست ها و لود صفحات وب می شود .
  2. باعت جلوگیری از خطا های header already sent که مربوط به استفاده از سیشن و کوکی ها است می شود .