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

لماذا ينتمي محرّك PDF لديك إلى PHP، لا إلى مكوّن جانبيّ

Spec: ISO/IEC 25010:2023, §3.7Spec: ISO 32000-2, §7

هناك موضعان يمكن أن يُصنَع فيهما ملف ⁨PDF⁩: داخل عملية ⁨PHP⁩ لديك، أو في مكان آخر عليك تشغيله. يصنعه ⁨NextPDF⁩ في الداخل. هذه الصفحة هي الحجّة لذلك الخيار — لماذا يكون محرّك داخل العملية هو الافتراضي الصحيح عادةً، وما الذي يكلّفه نمط “المكان الآخر” فعلًا حالما يصير في الإنتاج.

هذه هي الزاوية المعمارية، لا زاوية إطار العمل. أمّا كيف يصل المحرّك نفسه إلى ⁨Laravel⁩ و⁨Symfony⁩ و⁨CodeIgniter⁩ والكود المستقل فقصة مختلفة، مرويّة في صفحة محرّك واحد، كل إطار عمل.

نادرًا ما تبدأ ميزة ⁨PDF⁩ نظامًا تشغّله. إنها تبدأ سطرًا في متحكّم: صيِّر هذه الفاتورة، أعِد ذلك التقرير. نمط المكوّن الجانبيّ يحوّل ذلك السطر إلى بنية تحتية. فلرسم المستند تشغّل الآن شيئًا ثانيًا — ملفًا تنفيذيًا خارجيًا، أو متصفّحًا بلا واجهة، أو خدمة مصغّرة منفصلة — وكل ما يحتاجه ذلك الشيء الثاني يصير مشكلتك أيضًا: إصدارته، وذاكرته، وحاويته، وشبكته، وأنماط فشله، وصفحة مناوبته عند الساعة الثانية فجرًا.

الكلفة غير مرئية في العرض التوضيحي ولا مفرّ منها في الإنتاج. محرّك مستندات يعيش في عمليتك لا يحمل أيًّا منها. السؤال ليس “هل يستطيع مكوّن جانبيّ صنع ملف ⁨PDF⁩” — بالطبع يستطيع. إنه “ما الذي تعهّدت بتشغيله لتصل إلى هناك، وهل احتجت إليه.”

  • داخل العملية يعني لا زمن تشغيل ثانٍ. يرسم ⁨NextPDF⁩ ملف ⁨PDF⁩ داخل عامل ⁨PHP⁩ نفسه الذي عالج الطلب. لا عملية فرعية لإطلاقها، ولا خدمة لنشرها، ولا شيء إضافيّ لإبقائه حيًّا.
  • المكوّن الجانبيّ يضيف سطحًا تشغيليًّا لم يكن لديك. متصفّح مُحزَّم أو ملف تنفيذي خارجي يأتي بإصدارته الخاصة، وبصمته الأمنية الخاصة، وحاويته الخاصة — وكلها تُرقّعها وتراقبها الآن.
  • حدود العمليات هي حيث تسوء الأمور. الانطلاقات الباردة، والمهل، وسباكة العمليات الهشّة، وخروج البيانات من عمليتك هي أنماط فشل لا يملكها استدعاء داخل العملية ببساطة.
  • داخل العملية قابل للاختبار وحتميّ. المحرّك ⁨PHP⁩ محدّد النوع تستطيع اختباره وحدويًّا، ومحاكاته، والاستدلال عليه — لا مُصيِّرًا غامضًا لا تستطيع استكشافه إلا بتشغيله والنظر إلى المخرَج.
  • ما زال للمتصفّح الحقيقي استخدامات حقيقية. من أجل تصيير أمين على مستوى البكسل لصفحات ويب حديثة اعتباطية، يكون المتصفّح بلا واجهة هو الأداة الصادقة — ويستطيع ⁨NextPDF⁩ التفويض إليه عن قصد. إنه وصلة، لا الافتراض.

كيف يتعامل ⁨NextPDF⁩ مع الأمر

قسم بعنوان «كيف يتعامل ⁨NextPDF⁩ مع الأمر»

ضع المعماريّتين جنبًا إلى جنب. مسار داخل العملية استدعاء دالة. أمّا مسار المكوّن الجانبيّ فنظام موزَّع مصغَّر — وكل سهم بين صناديقه موضع يفشل بمعزل عن كودك.

  1. In-process: call the enginewriteHtml() or the document API runs inside the current PHP worker — no subprocess, no socket.
  2. In-process: receive PDF bytesThe engine returns native PDF content directly; nothing left the process.
  3. Sidecar: serialize and shipMarkup or a request is marshalled out of your process to a binary, browser, or remote service.
  4. Sidecar: cross the boundaryA process spawn or network hop — with a cold start, a timeout, and an IPC contract that can break.
  5. Sidecar: run a second runtimeAn external renderer with its own version, memory profile, and security surface to operate and patch.
  6. Sidecar: deserialize backMarshal the result back in and translate the renderer’s errors into yours.
The in-process path versus the sidecar path. In-process, the PDF is produced by a typed call inside the same PHP worker and returned directly. The sidecar path adds a serialization step, a process or network boundary, an external runtime with its own version and footprint, and a deserialization step back — each a distinct failure mode the in-process call does not have.

لا زمن تشغيل ثانٍ لتشغيله. نمط المكوّن الجانبيّ نظامان يرتديان زيّ ميزة واحدة. إنّ wkhtmltopdf مُحزَّمًا، أو خدمة ⁨Chromium⁩ بلا واجهة، أو خدمة تصيير مصغّرة منفصلة — كلٌّ منها زمن تشغيل بإيقاع إصدار خاص وبأخطائه الخاصة. ترث ذلك كله. يُشحَن المحرّك داخل العملية تبعيةَ ⁨Composer⁩؛ ويُرقَّى بالطريقة نفسها التي تُرقَّى بها كل مكتبة أخرى في composer.json لديك، بلا خادم دائم، أو صورة، أو مقبس مضاف إلى نشرك.

انحراف الإصدار وسطح أمني أوسع. المتصفّح المُحزَّم قاعدة كود كبيرة وسريعة الحركة بتدفّق ثابت من التنبيهات الأمنية. ثبّته فيتعفّن؛ وتتبّعه فيتقلّب. وفي كلتا الحالتين، إنها منصّة ويب كاملة لمُصيِّر جالسة في سلسلة توريدك لتغذية مستند واحد. أمّا محرّك ⁨PHP⁩ داخل العملية فمكتبة كود مركّزة تستطيع قراءتها؛ وسطحه الأمني هو ⁨PHP⁩ الذي تشغّله فعلًا، لا منصّة ثانية تشغّلها الآن أيضًا.

البيانات تبقى داخل حدّ عمليتك. حين تستعين بأمر خارجي، يعبر محتوى المستند — وهو غالبًا بالضبط البيانات الحسّاسة التي يوجد ملف ⁨PDF⁩ لحملها — حدًّا. يُكتَب إلى أنبوب، أو وسيط، أو ملف مؤقّت، أو مقبس شبكة إلى خدمة. كلٌّ من تلك موضع للتسرّب، أو للتسجيل بالخطأ، أو للترك خلفك. داخل العملية، لا تغادر البيانات قطّ العامل الذي يملكها. نصف قطر الانفجار عملية واحدة، لا أسطول.

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

قابلية الرصد والاختبار تصعبان عبر الحدّ. يصل فشل في مكوّن جانبيّ على هيئة رمز خروج، أو سطر سجلّ مبتور، أو خطأ 500 من خدمة لا تتحكّم فيها. وإعادة إنتاجه تعني إعادة إنتاج تلك البيئة كاملةً. أمّا محرّك داخل العملية فقابل للرصد بالأدوات التي تستخدمها فعلًا — أثر مكدّس، ومنقّح، ومُحلّل أداء — وهو قابل للاختبار بالطريقة التي يُختبَر بها بقيّة ⁨PHP⁩ لديك. تلك القابلية للاختبار خاصّية مسمّاة من خصائص جودة البرمجيات: تضعها ⁨ISO/IEC 25010⁩ تحت قابلية الصيانة (Spec: ISO/IEC 25010:2023, §3.7)، وتُرضيها مكتبة داخل العملية على نحو أكثر مباشرةً بكثير من مُصيِّر لا تستطيع تمرينه إلا بإطلاقه.

ملف ⁨PDF⁩ الذي تؤكّد عليه تلك الاختبارات بنية محدّدة، لا صندوق أسود. لملف ⁨PDF⁩ تخطيط كائن وملف محدّد (Spec: ISO 32000-2, §7)، ويُصدر محرّك داخل العملية تلك البنية من كود تستطيع قراءته — فيتحقّق اختبار ملف ذهبيّ أو اختبار بنيويّ من بايتات أنتجتها دالة معلومة، بدلًا من مخرَج برنامج خارجي لا تستطيع سوى رصده.

كل المقصد يتّسع في حفنة أسطر. لا عميل، ولا عنوان أساس، ولا فحص صحّة، ولا سياسة إعادة محاولة — لأنه لا يوجد نظام ثانٍ.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// The engine runs inside this very process. No subprocess is spawned,
// no socket is opened, and the report data never leaves the worker.
$document = Document::createStandalone();
$document->setTitle('Quarterly Report');
$document->addPage();
$html = <<<'HTML'
<h1 style="color: #1E3A8A;">Quarterly Report</h1>
<p>Rendered <strong>in-process</strong> by PHP — no browser, no sidecar.</p>
HTML;
$document->writeHtml($html);
// PDF bytes are returned directly. There is no boundary to marshal across,
// so there is no timeout, cold start, or deserialization step to handle.
$bytes = $document->getPdfData();

قارن شكل نسخة المكوّن الجانبيّ — لا كودها، بل شكلها التشغيليّ. إنها تحتاج ملفًا تنفيذيًا أو خدمة مثبّتة وقابلة للوصول، وطلبًا مُسلسَلًا ومُرسَلًا، ومهلة مختارة، ومسار فشل لحين يكون المُصيِّر باردًا أو معطّلًا، والنتيجة مُعادة المُسالسَة. لا شيء من ذلك في المقتطف أعلاه، لأنّ لا شيء منه موجود حين يكون المحرّك مكتبة.

الافتراض المتكرّر هو أنّ تصيير ⁨PDF⁩ “الحقيقيّ” يجب أن يعني متصفّحًا، إذًا داخل العملية لا بدّ أن يكون النسخة اللعبة. ذلك يقلب المفاضلة. المتصفّح هو الأداة الصحيحة حين تحتاج تصييرًا دقيقًا أمينًا على مستوى البكسل لمحتوى ويب حديث اعتباطيّ. إنه الافتراض الخاطئ للعمل ذي الشكل المستنديّ الذي تؤدّيه معظم الفرق فعلًا — الفواتير، والتقارير، والكشوف، والعقود — حيث يكون التخطيط معلومًا، والبيانات لك، والصحّة يفحصها مُصدِّق، لا العين. لذلك العمل، لا يشتري لك الثقل التشغيليّ لمكوّن جانبيّ شيئًا لا يمنحه المحرّك داخل العملية فعلًا، ويكلّفك كل شيء في الأقسام أعلاه.

المفهوم الخاطئ المرآة هو الذي تحرص هذه الصفحة على عدم ارتكابه: ادّعاء أنّ محرّكًا داخل العملية يُصيِّر “الويب كله” مثل متصفّح. إنه لا يفعل، ولا يتظاهر ⁨NextPDF⁩ بأنه يفعل. مسار ⁨HTML⁩ داخل العملية لديه مجموعة جزئية متوائمة مع المواصفات ومركّزة على تخطيط المستندات، بحدود موثَّقة — والنطاق الصادق مبسوط في صفحة مسار معالجة ⁨HTML⁩. وحين تحتاج فعلًا أمانة متصفّح كاملة، يكون ذلك تفويضًا مقصودًا اختياريًّا، لا تراجعًا صامتًا.

داخل العملية هو الافتراض الصحيح. ليس ادّعاءً عامًّا بأنّ عملية فرعية لا تُبرَّر أبدًا. وحيث يتطلّب مستند فعلًا تصييرًا دقيقًا لأنماط ⁨CSS⁩ حديثة اعتباطية لا يغطّيها المحرّك داخل العملية، يكون التفويض إلى متصفّح بلا واجهة هو الخيار الصحيح — ويدعم ⁨NextPDF⁩ ذلك المسار عن قصد، مع تقييد وصوله الشبكيّ، بوصفه وصلة لا الافتراض. الاثنان ليسا غريمين؛ إنهما أداتان مختلفتان لمهام مختلفة.

تحاجج هذه الصفحة المعمارية، لا مصفوفة دعم ⁨CSS.⁩ أمّا أيّ ⁨HTML⁩ و⁨CSS⁩ يغطّيه المسار داخل العملية بالضبط فيحدّده كود المحرّك واختبارات مطابقته، وهو موثَّق مع ذلك المسار — لا موعود به هنا. “داخل العملية” يصف مسار التصيير الافتراضيّ؛ وهو ليس ادّعاءً بأنّ كل مسار ممكن يتجنّب عملية فرعية.

يبقى سطح القدرة بسيطًا: المحرّك داخل العملية هو ⁨Core⁩، ومسار التفويض إلى المتصفّح امتداد اختياري، مستقلّ عن الإصدارة.

Where the PDF is rendered — edition availability
EditionAvailability
CoreCore renders PDF in-process in PHP — no subprocess, binary, or sidecar by default.
ProThe headless-browser delegation path is an optional add-on extension, independent of edition tier.
EnterpriseThe headless-browser delegation path is an optional add-on extension, independent of edition tier.
  • التوليد داخل العملية — إنتاج ملف ⁨PDF⁩ داخل عامل ⁨PHP⁩ نفسه الذي يعالج الطلب، بلا عملية فرعية، أو مقبس، أو خدمة خارجية.
  • المكوّن الجانبيّ — زمن تشغيل منفصل يعمل إلى جانب تطبيقك لأداء مهمّة واحدة؛ هنا، ملف تنفيذي خارجي، أو متصفّح بلا واجهة، أو خدمة مصغّرة تُصيِّر ملف ⁨PDF⁩ خارج عمليتك.
  • الانطلاق البارد — قفزة الكُمون والموارد المتكبَّدة حين يجب بدء عملية فرعية أو خدمة من العدم قبل أن تستطيع خدمة الطلب الأول.
  • ⁨IPC⁩ — الاتصال بين العمليات: الأنابيب، والمقابس، والملفات المؤقّتة، أو استدعاءات الشبكة المستخدَمة لتمرير البيانات من وإلى عملية منفصلة، ومصدر متكرّر لإخفاقات هشّة يصعب تنقيحها.
  • وصلة التفويض إلى المتصفّح — المسار الاختياريّ القابل للتفعيل الذي يسلّم تصييرًا إلى متصفّح بلا واجهة من أجل أمانة دقيقة، مع حظر وصول الموارد الفرعية إلى الشبكة؛ خيار مقصود، لا الافتراض.