Output Buffering در php

  • آپدیت شده در تاریخ

Output Buffering در php

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

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

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

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

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

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

Output Buffering در php

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

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

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

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

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

  • Output_buffering – به صورت پیش فرض ۰ است . نیاز داریم که با مقدار ON قابلیت Output Buffering را برای تمام اسکریپت های php فعال کنیم
  • Output_handler – مقدار پیش فرض  , NULL است .نیاز داریم که یک تابع از پیش ساخته مرجع برای ارسال خروجی به آن تابع مشخص کنیم
  • Implicit_flush –  قرار دادن مقدار ON برای این دستور  , باعث خواهد شد که اسکریپت php مقدار خروجی را به ازای هر دستور چاپی در php یکبار flush یا ارسال کند .

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

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

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

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

  • تابع Ob_start() – این تابع برای هر دیتای ذخیره شده یک بافر می سازد . این دیتا ها در صورت استفاده از دستور های print یا echo یا هر دستور چاپی به اسکریپت php پاس داده خواهند شد.
  • تابع ob_flush() , ob_end_flush() – این توابع برای ارسال خروجی بافر برای نمایش در مروگر استفاده می شوند . تفاوت این توابع اینجاست که , ob_flush() بعد از ارسال بافر , مقدار بافر ذخیره شده را پاک نمی کند . ولی با یکبار اجرای ob_end_flush() , اگر نیاز داشتیم باید دوباره یک بافر جدید بسازیم .
  • تابع ob_clean() , ob_end_clean() – این توابع برای پاک کردن داده های ذخیره شده در بافر استفاده می شوند .

مثال Output Buffering در php

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

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

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

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

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

  • خواندن داده ها از خروجی بافر ها
  • ساختن پشته (stack) برای خروجی بافر
  • فشرده سازی داده ذخیره شده در بافر
  • URL rewiting

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

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

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

  • ob_get_contents() – این تابع محتوای خروجی بافر را برگشت می دهد
  • ob_get_length() – این تابع طول داده ذخیره شده در بافر را return می کند.
  • ob_get_level() – برای دریافت سطح یا همان level خروجی بافر به کار می رود. وقتی تعداد بافرهای ما زیاد می شود این بافرها به سطح بندی می شوند که با این level ها می توانیم به راحتی به آنها دسترسی پیدا کنیم.
  • ob_get_status() – برای دریافت آرایه از وضعیت بافر های سطح بالا یا تمام بافر ها با هر سطح استفاده می شود.
  • ob_get_flush() – این تابع کار هر دو تابع ob_get_contents() و ob_end_flush() را یکجا انجام میدهد !
  • ob_get_clean() – مشابه مورد بالا تاثیر هر دو تابع ob_get_contents() و ob_end_flush() همزمان نشان می دهد .

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

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

Output Buffering در php

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

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

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

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

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

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

URL Rewriting

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

  • output_add_rewrite_var() – اسم و مقدار را به صورت جفت در آرگومان می پذیرد .این اسم و مقادیر ها به صورت query string در یک url اضافه خواهند شد و سپس یک فیلد خالی برای این جفت ها افزوده می شود .
  • output_reset_rewrite_varts() – این تابع تمام مقادیر URL Rewriting را پاک می کند .

نکته :

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

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

 

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

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

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

 

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

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

سعی کردم یکبار برای همیشه و به طور کامل مقاله ای بنویسیم که تمام مباحث Output Buffering در php را پوشش دهم و احساس می کنم این هدف هم نایل شد .

هر گونه مشکلی در پیاده سازی کدها داشتید ، از قسمت نظرات اقدام کنید . سریعا ، پاسخگوی سوالات شما هستیم .

موفق و پیروز باشید.

حسن شفیعی علاقه خاصی به برنامه نویسی وب و موبایل دارم و هر روز تلاش می کنم به این حوزه مسلط تر شوم و اطلاعاتم را به شکل کاربردی برای علاقه مندان در وب به اشتراک بگذارم

آموزش های رایگان بیشتر در اینستاگرام ما ...

NETPARADIS /
مطالب زیر را حتما بخوانید
دیدگاه کاربران (۱۸)

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

  1. حامد ۵ اردیبهشت ۱۳۹۸

    سلام آقای شفیعی
    من با ارور warning: Cannot modify header information – headers already sent by (output started at
    مواجه میشم تو اسکریپت، چطوری این خطا رو رفع کنم، لینک فایل رو اینجا قرار میدم ببینید. لاین خطا ها هم تو زیر مشخص کردم
    template.php:144
    routing.php on line 141
    http://s8.picofile.com/file/8358482968/help.zip.html

    یاشا

    پاسخ
    1. حسن شفیعی ۵ اردیبهشت ۱۳۹۸

      سلام. در خط اول یعنی بعد از تگ php بلافاصله تابع ob_start() را استفاده کنید این خطا حل میشه.
      موفق باشید.

      پاسخ
      1. حامد ۵ اردیبهشت ۱۳۹۸

        سلام، آقای شفیعی متوجه نشدم !

        پاسخ
      2. حسن شفیعی ۵ اردیبهشت ۱۳۹۸

        سلام. بسیار سادست. اول فایل های php خودتون قبل از همه کدها این تابع ob_start() رو کپی پیست کنید همین.
        اول فایل های php شما اگر php?> است باید بعد کپی تابع بالا به اینصورت باشه
        php?>
        ob_start()

        بعد اینکارخطای موردنطر رفع میشه.
        موفق باشید.

        پاسخ
      3. حامد ۶ اردیبهشت ۱۳۹۸

        ممنون، با این تابع مشکل ام تا حدودی حل شد، و دیگه ارور بالا نمایش داده نمیشه.من از اسکریپت درگاه واسط استفاده میکنم، وقتی لینک پرداخت ایجاد میکنم و آدرس پرداخت ناموفق رو خالی میزارم … وارد صفحه پرداخت میشم و از پرداخت انصراف میدم به جای اینکه صفحه پیشفرض سایت رو نشون بده و بگه پرداخت انجام نشد یا شخص از خرید انصراف داده، لینک پرداخت موفق رو نشون میده، و در ضمن اگه آدرس پرداخت ناموفق رو خالی نذارم و آدرسی وارد کنم به اون صفحه هدایت میشه و لینک دانلود موفق رو نشون نمیده برعکس بالا، ممنون میشم در این باره منو راهنمایی کنید (البته اگه منظورمو درست رسونده باشم)

        پاسخ
      4. حسن شفیعی ۶ اردیبهشت ۱۳۹۸

        سلام
        خب چه دلیلی داره صفحه پرداخت نا موفق رو ست نمی کنید. اگر میخوایین به صفحه اصلی برگرده که آدرس دامنه خودتون رو وارد کنید.
        همچنین اگر این ایراد هست مطمینا یا کد وضعیت رو درست اعتبارسنجی نمی کنید یا ایراد از خود سیستم درگاه واسط است که باید اطلاع بدید حل کنند.

        پاسخ
      5. حامد ۶ اردیبهشت ۱۳۹۸

        سلام، یاشا آقای شفیعی
        ممنون که جواب کاربران رو دقیق و شفاف میدید، و همینطور مرسی بابت سایت خوبتون

        پاسخ
      6. حسن شفیعی ۶ اردیبهشت ۱۳۹۸

        سلام. خواهش می کنم. خوشحالیم که مفید واقع شده.
        موفق و پیروز باشید.

        پاسخ
      7. محمد ذبیح مند ۲۴ فروردین ۱۳۹۹

        با سلام
        بر اساس تجربه ،یک سورس مشخص روی هاست های اشتراکی مختلف. ممکنه خطای
        already headers sent رو بدهند. یعنی یک هاست خطا میده اما هاست دیگه خطا نمیده.
        در حالی که سورس عوض نشده. تنها نکته هم استفاده از دستور header برای ریدایرکت هست.
        مانند header(“Location:index.php?go=listmaker”);
        آیا استفاده از این ob_start() در تمام صفحاتی که از header استفاده می کنند بدون flush یا End مشکلی بوجود نمیاره؟

        پاسخ
      8. حسن شفیعی ۲۴ فروردین ۱۳۹۹

        سلام. این خطا بستگی به این دارد در هاست مورد نظر فعال شده باشه یا خیر که بهتره در فایل موردنظر با کد php این موارد رو پیش فرض فعال کنید

        پاسخ
      9. محمد ذبیح مند ۲۵ فروردین ۱۳۹۹

        چون هاست اشتراکی هست ، آیا استفاده از این ob_start() در تمام صفحاتی که از header استفاده می کنند بدون flush یا End مشکلی بوجود نمیاره؟

        پاسخ
      10. حسن شفیعی ۲۵ فروردین ۱۳۹۹

        خیر مشکلی پیش نمیاد

        پاسخ
  2. محمدرضا ۲۴ آذر ۱۳۹۷

    سلام بر شما. چجوری میشه برای این تابع اوت پوت بافر ایجاد کرد؟
    $post_link=get_field(‘postlink’);
    function urlsite ($post_link){
    $reg_exUrl = “/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+/”;
    preg_match($reg_exUrl, $post_link, $url);
    return $url[0];
    }
    $res= urlsite ($post_link);

    پاسخ
    1. حسن شفیعی ۲۴ آذر ۱۳۹۷

      سلام. زمانی میتونید از output buffering استفاده کنید که در خروجی یه چیزی چاپ بشه.
      اینجا شماreturnکردید که بعد از چاپ کردن مقدارها باید از $res= ob_get_clean(); استفاده کنید. البته قبل از هر چیزی باید مطمین باشید انجینش روشن باشه (ob_start() )

      یک مثال سادشو هنگام نمایش محتوای پست the_content ببینید :

      موفق باشید.

      پاسخ
  3. AMIR ۷ آذر ۱۳۹۷

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

    پاسخ
    1. حسن شفیعی ۸ آذر ۱۳۹۷

      سلام. خوشحالم که مفید واقع شده. موفق و پیروز باشید.

      پاسخ
  4. حمیدرضا ۲۹ دی ۱۳۹۶

    سلام حسین جان
    اگر لطف کنید و در مورد بافرهای تودرتو یا nested بنویسید ممنون میشم من هرقدر در موردش مطالب انگلیسی می‌خوانم متوجه نمیشم چی میگن!!!

    پاسخ
    1. حسن شفیعی ۲ بهمن ۱۳۹۶

      سلام .
      بله حتما این موضوع به عنوان ویرایش به مقاله اضافه و از طریق ایمیل به شما اطلاع داده می شود .
      موفق و پیروز باشید

      پاسخ
دوره های آموزشی

دانلود رایگان کتاب آموزش PHP

صفر تا صد PHP و MySQL را یکجا یاد بگیرید
همین الان دانلود کن
نگران نباشید. ایمیل‌های مزاحم نمی‌فرستیم
close-link