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

بداية سريعة — أول عرض على الحافة

في هذه الصفحة، تحوّل سلسلة نصية واحدة بلغة ترميز النص الفائق (⁨HTML⁩) إلى ملف بتنسيق المستندات المحمولة (⁨PDF⁩). يقابل كل استدعاء طريقةً محددة، ويُتحقق من سلوك كل طريقة في tests/Unit/Cloudflare/CloudflareHtmlRendererTest.php.

  • نقطة نهاية ⁨Worker⁩ تُقدّم عقد العرض عبر بروتوكول نقل النص الفائق الآمن (⁨HTTPS⁩).
  • رمز حامل (⁨bearer token⁩) يقبله الـ ⁨Worker.⁩
  • عميل توصية معايير ⁨PHP⁩ رقم 18 (⁨PSR-18⁩) ومصانع توصية معايير ⁨PHP⁩ رقم 17 (⁨PSR-17⁩) متوفرة في المسار (راجع /⁨integrations/cloudflare/install/⁩).

عقد الـ ⁨Worker⁩، كما يوضّحه CloudflareResponseParser: عند النجاح، يُرجِع بروتوكول نقل النص الفائق (⁨HTTP⁩) 200. تحمل الاستجابة إمّا Content-Type: application/pdf (بايتات ⁨PDF⁩ خام) أو Content-Type: application/json مع حقل pdf مُرمَّز بـ ⁨base64.⁩ أي حالة غير 200، أو أي محتوى لا يبدأ بالعلامة %PDF، يُعامَل على أنه إخفاق.

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Cloudflare\CloudflareRendererConfig;
$config = new CloudflareRendererConfig(
workerUrl: 'https://pdf-renderer.example.workers.dev/render',
apiToken: getenv('CF_PDF_TOKEN') ?: throw new RuntimeException('CF_PDF_TOKEN not set'),
);

اقرأ الرمز من البيئة ولا تُضمِّنه في الشيفرة أبدًا. يجب أن يستخدم workerUrl بروتوكول ⁨HTTPS.⁩ إذا مرّرت عنوان ⁨URL⁩ من نوع http://، فسيَرفضه الجسر بالرسالة Worker URL must use HTTPS قبل أن يرسل أي طلب.

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use NextPDF\Cloudflare\CloudflareHtmlRenderer;
$httpFactory = new HttpFactory();
$renderer = new CloudflareHtmlRenderer(
config: $config,
httpClient: new Client(), // PSR-18 ClientInterface
requestFactory: $httpFactory, // PSR-17 RequestFactoryInterface
streamFactory: $httpFactory, // PSR-17 StreamFactoryInterface
logger: null, // optional PSR-3 LoggerInterface
responseFactory: $httpFactory, // PSR-17; enables the pinned transport
);

يتطلب المُنشئ أربع وسائط: الإعداد، وعميل ⁨PSR-18⁩، ومصنع الطلبات، ومصنع الدفق. وهناك أربع وسائط اختيارية أخرى: المُسجِّل، ومصنع أداة العرض المحلية، وسياسة أمان ⁨HTML⁩ صريحة، ومصنع الاستجابات. يفعّل توفير مصنع الاستجابات النقلَ المُثبَّت عبر عميل ⁨URL⁩ (⁨cURL⁩) إذا توفرت مجموعة بروتوكول إنترنت (⁨IP⁩) محلولة أو مجموعة تثبيت معلومات المفتاح العام للموضوع (⁨SPKI⁩) موجودة (راجع /⁨integrations/cloudflare/security-and-operations/⁩).

use NextPDF\Cloudflare\Exception\CloudflareNotAvailableException;
use NextPDF\Cloudflare\Exception\CloudflareRenderException;
try {
$result = $renderer->render('<h1>Hello from the edge</h1>');
if (!$result->isValid()) {
throw new RuntimeException('Worker did not return a valid PDF');
}
file_put_contents('output.pdf', $result->pdfData);
printf("Wrote %d bytes from edge %s in %.1f ms\n",
$result->size(),
$result->renderLocation !== '' ? $result->renderLocation : 'unknown',
$result->renderTimeMs,
);
} catch (CloudflareRenderException $e) {
// Worker answered but the render failed (HTTP error or malformed body).
fwrite(STDERR, 'Render failed: ' . $e->getMessage() . PHP_EOL);
exit(1);
} catch (CloudflareNotAvailableException $e) {
// Worker unreachable and no usable fallback.
fwrite(STDERR, 'Edge unavailable: ' . $e->getMessage() . PHP_EOL);
exit(2);
}

تستخدم render() افتراضيًا عرض ⁨A4⁩ (595.28 نقطة ⁨PDF⁩) وارتفاعًا يُكتشَف تلقائيًا (heightPt: 0). صُمّم نوعا الاستثناء ليكونا منفصلين عمدًا. يشير CloudflareRenderException إلى إخفاق من جهة الـ ⁨Worker⁩، ولا تُعاد المحاولة معه عبر بديل احتياطي إطلاقًا. أما CloudflareNotAvailableException فيعني أنه تعذّر الوصول إلى الحافة ولم يكن هناك بديل احتياطي محلي متاح.

CloudflareRenderResult هو final readonly. تُملأ الحقول أدناه من ترويسات الاستجابة في المسار الثنائي، أو من حقول تدوين كائنات ⁨JavaScript⁩ ‏(⁨JSON⁩) في مسار ⁨JSON.⁩

العضوالمصدر
pdfDataبايتات ⁨PDF⁩ خام
widthPtالعرض الذي طلبتَه
heightPtترويسة X-Pdf-Height-Pt ‏/ ‏⁨JSON⁩ heightPt؛ تكون القيمة الافتراضية 841.89 (ارتفاع ⁨A4⁩) عند غيابها أو عندما لا تكون قيمة موجبة
contentHeightPxX-Content-Height-Px ‏/ ‏⁨JSON⁩ contentHeightPx
renderLocationيُشتق من لاحقة ترويسة CF-Ray (المسار الثنائي) أو من renderLocation في ⁨JSON⁩
renderTimeMsX-Render-Time-Ms ‏/ ‏⁨JSON⁩ renderTimeMs
size()strlen($pdfData)
isValid()true عندما تبدأ البايتات بـ %PDF

اختياري — حجم ورق مخصص وخطوط و⁨CSS⁩

قسم بعنوان «اختياري — حجم ورق مخصص وخطوط و⁨CSS⁩»
$result = $renderer->render(
html: '<div style="font-family: NotoSansCJK;">繁體中文文件</div>',
widthPt: 595.28,
heightPt: 841.89, // explicit A4; 0 lets the Worker auto-detect
fontFiles: ['NotoSansCJKtc-Regular.ttf'],
);

لا يكون fontFiles ذا معنى إلا عندما يضبط الإعداد r2FontBucket. عندئذٍ تحمل الحمولة اسم الدلو ومسارات ملفات الخطوط المطلوبة كي يتمكن الـ ⁨Worker⁩ من تحميلها.

اختياري — مسبار قابلية الوصول

قسم بعنوان «اختياري — مسبار قابلية الوصول»
if ($renderer->isAvailable()) {
$result = $renderer->render($html);
}

يرسل isAvailable() طلب ⁨HTTP⁩ HEAD مُصادَقًا عليه إلى عنوان ⁨URL⁩ الخاص بالـ ⁨Worker.⁩ يُرجِع true عندما تكون الحالة أقل من 500. ويُرجِع false دون رمي استثناء عندما يكون الإعداد غير صالح أو يخفق الطلب. تعامَل معه على أنه مؤشر لا ضمان. فما يزال بإمكان الـ ⁨Worker⁩ أن يُخفِق في طلب POST اللاحق.

  • /⁨integrations/cloudflare/production-usage/⁩ — توصيل البديل الاحتياطي، والقياس عن بُعد، والأرشفة في ⁨R2.⁩
  • /⁨integrations/cloudflare/troubleshooting/⁩ — كل إخفاق مُرتبط باستثنائه ورسالته.
  • /⁨integrations/cloudflare/configuration/⁩ — مرجع كامل للحقول.