تخطَّ إلى المحتوى
getnextpdf.com

الترويسات والتذييلات والمستندات متعدّدة الصفحات

نادرًا ما تكفي صفحة واحدة. في هذا الدرس التعليمي تكتب مستندًا يتوسّع من تلقاء نفسه إلى ثلاث صفحات. كما تمنح كل صفحة ترويسة متكرّرة، وتذييلًا يعرض رقم الصفحة.

ستكتب سكربتًا واحدًا، 01-multipage.php. وهو يُنتج مذكّرات سفر من ثلاث صفحات بوصفها ملفًا بصيغة المستندات المحمولة (⁨PDF⁩):

  • تتدفّق مُدخلات المذكّرات من صفحة إلى أخرى تلقائيًا. لا تحدّد أبدًا أين تنتهي الصفحة؛ فالمحرّك هو من يقرّر.
  • الترويسة شريط في أعلى الصفحة يتكرّر في كل صفحة. وتعرض ترويستك عنوان المستند.
  • التذييل هو الشريط المقابل في الأسفل. ويعرض تذييلك رقم الصفحة بالشكل 1 / 3 و2 / 3 و3 / 3.

يعمل كل شيء بحزمة nextpdf/core وحدها: بلا ملفات خطوط، وبلا امتدادات إضافية، وبلا شبكة.

الخطوة 1: أنشئ المذكّرات ذات الصفحات الثلاث

قسم بعنوان «الخطوة 1: أنشئ المذكّرات ذات الصفحات الثلاث»

فكرتان تؤدّيان كل العمل في هذا السكربت.

الأولى هي فاصل الصفحات التلقائي. أثناء كتابة المحرّك للنص، يتتبّع مؤشّرًا: الموضع على الصفحة الذي سيحطّ فيه السطر التالي. تُخبر setAutoPageBreak(true, margin: 25) المحرّكَ بمراقبة ذلك المؤشّر. وعندما يقترب إلى مسافة 25 نقطة (نحو ثلث البوصة) من الحافّة السفلى، يُغلق المحرّك الصفحة ويبدأ صفحة جديدة.

والثانية هي تجهيزات الصفحة: الترويسة والتذييل. تصفها مرة واحدة، قبل الصفحة الأولى. تُسجّل setHeaderData() العنوان ووصفًا قصيرًا للشريط العلوي. وتختار استدعاءات الخط والهامش نمطَ الحروف والمسافةَ من حافّة الصفحة. ثم يرسم المحرّك هذه التجهيزات في كل صفحة يُنشئها، بما في ذلك الصفحات التي يضيفها من تلقاء نفسه.

أنشئ 01-multipage.php في مجلد مشروعك:

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// Make sure the output folder exists next to this script.
@mkdir(__DIR__ . '/out');
$document = Document::createStandalone();
$document->setTitle('NextPDF Travel Journal');
// Configure the header and footer BEFORE the first page.
// The engine repeats them on every page for you.
$document->setHeaderData(title: 'NextPDF Travel Journal', description: 'A multi-page tutorial document');
$document->setHeaderFont('helvetica', 10);
$document->setHeaderMargin(5);
$document->setFooterFont('helvetica', 8);
$document->setFooterMargin(10);
// Turn on automatic page breaks. When the text cursor gets within
// 25 points of the bottom edge, the engine starts a new page.
$document->setAutoPageBreak(true, margin: 25);
$document->addPage();
$document->setFont('helvetica', 'B', 18);
$document->cell(0, 12, 'Travel journal: three days on the coast', newLine: true);
$document->ln(5);
$days = [
1 => 'We followed the shoreline north and counted seventeen lighthouses.',
2 => 'Rain moved in before noon, so we sketched the harbor from a cafe window.',
3 => 'On the last morning the fog lifted and the whole bay turned silver.',
];
foreach ($days as $day => $highlight) {
$document->setFont('helvetica', 'B', 14);
$document->cell(0, 10, "Day {$day}", newLine: true);
$document->setFont('helvetica', '', 11);
for ($entry = 1; $entry <= 12; $entry++) {
$text = "Entry {$entry} of day {$day}. {$highlight} "
. 'The trail hugged the cliffs for most of the afternoon, and every '
. 'turn opened another view of the water. We stopped often to take '
. 'notes, compare maps, and argue happily about where to eat dinner. '
. 'By the time we reached the guesthouse, our boots were soaked and '
. 'our notebooks were full.';
$document->multiCell(0, 7, $text);
$document->ln(3);
}
$document->ln(5);
}
// Ask the engine how many pages the layout produced, then save.
$pages = $document->getNumPages();
$document->save(__DIR__ . '/out/travel-journal.pdf');
echo "Wrote out/travel-journal.pdf with {$pages} pages\n";

شغّله باستخدام php 01-multipage.php. يطبع السكربت سطرًا واحدًا:

Wrote out/travel-journal.pdf with 3 pages

افتح out/travel-journal.pdf وتصفّحه. يقع شريط العنوان في أعلى الصفحات الثلاث جميعها، وتتصاعد أرقام الصفحات في أسفل اليمين.

لا تذكر حلقة الكتابة الصفحات مطلقًا. فهي تكتب عنوان كل يوم باستخدام cell()، التي تضع سطرًا واحدًا في صندوق غير مرئي. وتكتب المُدخلات باستخدام multiCell()، التي تلفّ النص الطويل على ما يلزمه من أسطر. لا تتّسع ست وثلاثون مُدخلة في صفحة واحدة، لذا يعمل فاصل الصفحات التلقائي مرّتين. وهكذا تصبح المذكّرات ثلاث صفحات بالضبط.

جرى ضبط الترويسة والتذييل قبل أول استدعاء لـ addPage(). وهذا الترتيب مهم: الصفحة التي رُسمت بالفعل لا تتحدّث بعد ذلك. اضبط التجهيزات أولًا، فتخرج كل صفحة متّسقة.

لم ترسم رقم الصفحة أبدًا. فالتذييل يطبعه افتراضيًا؛ ولم تختر سوى خطّه ومسافته من حافّة الصفحة. وبينما يكتب المحرّك الصفحات، لا يمكنه بعدُ معرفة العدد النهائي. لذا يترك عنصرًا نائبًا في كل تذييل، ويملأ الإجمالي الحقيقي عند الحفظ.

تفصيلان صغيران يُكمِلان السكربت. تُنشئ @mkdir مجلد out، وعلامة @ تُبقي ⁨PHP⁩ صامتة عندما يكون المجلد موجودًا بالفعل. وتسأل getNumPages() المحرّكَ عن عدد الصفحات التي أنتجها التخطيط، كي تُبلّغ الرسالةُ النهائية العددَ الحقيقي.

  • خطأ ⁨“failed to open stream”⁩ في سطر require يعني أن السكربت لم يستطع العثور على vendor/autoload.php. شغّله داخل مجلد المشروع الذي يحتوي على vendor/.
  • كل شيء يقع في صفحة واحدة، ونهاية النص مقطوعة؟ إذًا فواصل الصفحات التلقائية معطّلة. أبقِ سطر setAutoPageBreak(true, margin: 25)، وأبقِه فوق حلقة الكتابة.
  • اسمُ عائلة خط مكتوب خطأً يطرح استثناءً يذكر الخطّ الذي تعذّر العثور عليه. تحقّق من تهجئة helvetica، وراجع الخطوط والوسم لمشكلات الخطوط الأعمق.
  • لأي شيء آخر، يربط مركز استكشاف الأخطاء وإصلاحها الأعراضَ بالأسباب، ويشرح مرجع الأخطاء الاستثناءاتِ العامة للمحرّك وكيفية التعافي من كل منها.

يمكن لمستنداتك الآن أن تتوسّع إلى أي طول مع بقائها مكتملة المظهر. في الدرس التعليمي التالي تكتب محتواك بلغة ترميز النص التشعبي (⁨HTML⁩)، وتدع المحرّك يحوّله إلى صفحات.

وعندما تريد تحكّمًا أدقّ في مواضيع اليوم، تتعمّق وصفتان أكثر: