اذهب إلى المحتوى

التخزين المؤقت للخرج في PHP


سارة محمد2
الدالة تفاصيل
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

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...