الدالة | تفاصيل |
ob_start() | تبدأ إظهار المخزن المؤقت وأي خرج يوضع بعده سيُلتقط ولن يُعرض |
ob_get_contents() | تُرجع كل المحتوى المُلتقط بالدالة ob_start() |
ob_end_clean() | تُفرغ المخزن المؤقت للخرج وتوقف تشغيله للمستوى المتداخل الحالي |
ob_get_clean() | ينفّذ كل من ob_end_clean() و ob_get_contents() |
ob_get_level() | يُرجع مستوى التداخل الحالي للمخزن المؤقت للخرج |
ob_flush() | تُفرّغ محتوى المخزن المؤقت وترسله إلى المتصفح دون إنهاء المخزن المؤقت |
ob_implicit_flush() | تُمكّن التفريغ الضمني بعد كل استدعاء للخرج |
ob_end_flush() | تُفرّغ محتوى المخزن المؤقت وترسله إلى المتصفح مع إنهاء المخزن المؤقت |
الاستخدام الأساسي للحصول على المحتوى بين المخازن المؤقتة والتفريغ
يسمح لك التخزين المؤقت للخرج بتخزين أي محتوى نصي (نص، HTML) في متغير وإرساله إلى المتصفح كجزء واحد في نهاية السكربت، بشكلٍ افتراضي تُرسل PHP المحتوى كما تترجمه.
<?php // تشغيل التخزين المؤقت للخرج ob_start(); // طباعة خرج ما للمخزن المؤقت print 'Hello '; // يمكنك أيضًا الخروج من شيفرة PHP ?> <em>World</em> <?php // إرجاع المخزن المؤقت وإفراغه $content = ob_get_clean(); // إرجاع المخزن المؤقت ثم إفراغه # $content = ob_get_contents(); # $did_clear_buffer = ob_end_clean(); print($content); #> "Hello <em>World</em>"
أي محتوى خرج بين ob_start()
وob_get_clean()
سيُلتقط ويوضع في المتغير $content
.
ينفذ استدعاء ob_get_clean()
كل من ob_get_contents()
وob_end_clean()
.
معالجة المخزن المؤقت عبر رد النداء
يمكنك تطبيق أي نوع من المعالجة الإضافية على الخرج بتمرير معامل قابل للاستدعاء للدالة ob_start()
.
<?php function clearAllWhiteSpace($buffer) { return str_replace(array("\n", "\t", ' '), '', $buffer); } ob_start('clearAllWhiteSpace'); ?> <h1>Lorem Ipsum</h1> <p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. <a href="#">Donec non enim</a> in turpis pulvinar facilisis.</p> <h2>Header Level 2</h2> <ol> <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li> <li>Aliquam tincidunt mauris eu risus.</li> </ol> <?php /* ob_end_flush(); سيُفرّغ الخرج ويُعالج عندما ينتهي السكربت أو تُستدعى */
الخرج:
<h1>LoremIpsum</h1><p><strong>Pellentesquehabitantmorbitristique</strong>senectusetnetusetmalesuada famesacturpisegestas.<ahref="#">Donecnonenim</a>inturpispulvinarfacilisis.</p><h2>HeaderLevel2</h2> <ol><li>Loremipsumdolorsitamet,consectetueradipiscingelit.</li><li>Aliquamtinciduntmauriseurisus.</ li></ol>
المخازن المؤقتة للخرج المتداخل
يمكنك أن تحصل على تداخل المخازن المؤقتة للخرج ومستواها لتوفير محتوى مختلف باستخدام الدالة ob_get_level()
.
<?php $i = 1; $output = null; while( $i <= 5 ) { // `level` تُنشئ كل حلقة مخزن مؤقت خرج جديد ob_start(); print "Current nest level: ". ob_get_level() . "\n"; $i++; } // نحن الآن في المستوى 5 print 'Ended up at level: ' . ob_get_level() . PHP_EOL; // محتويات المستوى الأعلى (5) وتحذفه ob_get_clean() ستفرّغ الدالة $output .= ob_get_clean(); print $output; print 'Popped level 5, so we now start from 4' . PHP_EOL; // نحن الآن في المستوى 4 // كلما أردنا أن نزيد مستوى نعود للأسفل ونحصل على المخزن المؤقت while( $i > 2 ) { print "Current nest level: " . ob_get_level() . "\n"; echo ob_get_clean(); $i--; }
الخرج:
Current nest level: 1 Current nest level: 2 Current nest level: 3 Current nest level: 4 Current nest level: 5 Ended up at level: 5 Popped level 5, so we now start from 4 Current nest level: 4 Current nest level: 3 Current nest level: 2 Current nest level: 1
تشغيل المخزن المؤقت للخرج قبل أي محتوى
ob_start(); $user_count = 0; foreach( $users as $user ) { if( $user['access'] != 7 ) { continue; } ?> <li class="users user-<?php echo $user['id']; ?>"> <a href="<?php echo $user['link']; ?>"> <?php echo $user['name'] ?> </a> </li> <?php $user_count++; } $users_html = ob_get_clean(); if( !$user_count ) { header('Location: /404.php'); exit(); } ?> <html> <head> <title>Level 7 user results (<?php echo $user_count; ?>)</title> </head> <body> <h2>We have a total of <?php echo $user_count; ?> users with access level 7</h2> <ul class="user-list"> <?php echo $users_html; ?> </ul> </body> </html>
نفرض في هذا المثال أنّ $users
مصفوفة متعددة الأبعاد ونريد تمريرها عبر حلقة لإيجاد كل المستخدمين مع الوصول للمستوى 7، إذا لم توجد نتائج سيُعاد توجيهنا إلى صفحة خطأ.
نستخدم هنا المخزن المؤقت للخرج لأننا نفذنا إعادة توجيه header()
بالاعتماد على نتيجة الحلقة.
خرج مجرى التدفق إلى العميل
تمكّن الشيفرة التالية مجرى تدفق المخزن المؤقت للخرج، يفرّغ استدعاء هذه الدالة مباشرةً المخزن المؤقت للعميل وأي خرج لاحق سيُرسل مباشرةً له.
function _stream() { ob_implicit_flush(true); ob_end_flush(); }
استخدام المخزن المؤقت للخرج لتخزين المحتويات في ملف
يعدّ هذا مفيدًا للتقارير والفواتير وغير ذلك.
<?php ob_start(); ?> <html> <head> <title>Example invoice</title> </head> <body> <h1>Invoice #0000</h1> <h2>Cost: £15,000</h2> ... </body> </html> <?php $html = ob_get_clean(); $handle = fopen('invoices/example-invoice.html', 'w'); fwrite($handle, $html); fclose($handle);
يأخذ هذا المثال كامل المستند ويكتبه إلى ملف وهذا لا يُظهر المستند في المتصفح إنما نحتاج لكتابة echo $html;
لعرضه.
أسباب استخدام ob_start وكيفية الاستخدام النموذجي لها
يعدّ استخدام ob_start
مفيدًا بشكلٍ خاص عندما يكون لديك عمليات إعادة توجيه في صفحتك. الشيفرة التالية لن تعمل عملًا صحيحًا:
Hello! <?php header("Location: somepage.php"); ?>
سيظهر خطأ مشابه لما يلي:
headers already sent by <xxx> on line <xxx>.
لإصلاح هذه المشكلة نكتب الشيفرة التالية في بداية الصفحة:
<?php ob_start(); ?>
ونضيف ما يلي إلى نهايتها:
<?php ob_end_flush(); ?>
يخزّن ذلك كل المحتوى المتولد في المخزن المؤقت للخرج ويعرضه دفعةً واحدة، لذا إن كان لديك أي استدعاءات إعادة توجيه في صفحتك ستُنفّذ قبل إرسال أي بيانات وعندها تتجنب الخطأ headers already sent
.
التقاط المخزن المؤقت للخرج لإعادة الاستخدام لاحقًا
لدينا في هذا المثال مصفوفة تتضمن بعض البيانات، نلتقط المخزن المؤقت للخرج في المتغير $items_li_html
ونستخدمه مرتين في الصفحة.
<?php // ابدأ التقاط الخرج ob_start(); $items = ['Home', 'Blog', 'FAQ', 'Contact']; foreach($items as $item): // PHP يمكننا الآن الخروج من شيفرة ?> <li><?php echo $item ?></li> <?php // PHP العودة إلى شيفرة endforeach; // على كل المحتوى المُلتقط من المخزن المؤقت للخرج $items_lists سيحتوي المتغير $items_li_html = ob_get_clean(); ?> <!-- Menu 1: يمكننا الآن إعادة استخدام هذه القوائم عدة مرات في صفحتنا --> <ul class="header-nav"> <?php echo $items_li_html ?> </ul> <!-- Menu 2 --> <ul class="footer-nav"> <?php echo $items_li_html ?> </ul>
احفظ الشيفرة السابقة في ملف output_buffer.php
ونفذّه باستخدام php output_buffer.php
، يجب أن تحصل على قائمتي العناصر اللتين أنشأناهما في الشيفرة السابقة مع نفس عناصر القائمة المتولدة في PHP باستخدام المخزن المؤقت للخرج:
<!-- Menu 1: يمكننا الآن إعادة استخدام هذه القوائم عدة مرات في صفحتنا --> <ul class="header-nav"> <li>Home</li> <li>Blog</li> <li>FAQ</li> <li>Contact</li> </ul> <!-- Menu 2 --> <ul class="footer-nav"> <li>Home</li> <li>Blog</li> <li>FAQ</li> <li>Contact</li> </ul>
ترجمة -وبتصرف- للفصل [Output Buffering] من كتاب PHP Notes for Professionals book
اقرأ أيضًا
- المقال التالي: الانعكاس (Reflection) وحقن الاعتمادية في PHP
- المقال السابق: فضاء الأسماء (namespaces) في PHP
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.