لا تكتسب الشهادة قيمتها إلا إذا وثق بها الناس. عندما يرفق المتعلم ملف PDF بطلب توظيف، يجب أن يكون مدير التوظيف قادرًا على التأكد من صحته في ثوانٍ معدودة. يمنحك Laravel الأدوات اللازمة لبناء هذه الثقة بنفسك، دون تسليم التحكم لمنصة خارجية. يمكنك امتلاك العلامة التجارية، والبيانات، وسلسلة التحقق من البداية إلى النهاية.

الهدف بسيط: إنشاء ملف PDF احترافي يبدو أنيقًا عند الطباعة، ويحتوي على رمز QR قابل للمسح للتحقق الفوري، ويخزن سجلًا فريدًا لا يمكن تخمينه أو تزويره. إليك كيفية تنفيذ ذلك.

ابدأ بطبقة قاعدة البيانات

لا تستخدم المعرفات ذات الزيادة التلقائية (auto-incrementing IDs) للشهادات. فالمعرف مثل 8473 سهل التخمين؛ حيث يمكن لشخص ما تجربة الأرقام المتتالية في صفحة التحقق الخاصة بك وسحب كل وثيقة أصدرتها على الإطلاق. بدلاً من ذلك، قم بإنشاء UUID عند إنشاء سجل الشهادة.

في ملف الـ migration الخاص بك، قم بتخزين الـ UUID كسلسلة نصية (string). عندما ينهي المستخدم دورة تدريبية، قم بإطلاق حدث (event) ينشئ نموذج Certificate مرتبطًا بالمستخدم والدورة التدريبية. اجعل نقطة نهاية التحقق (verification endpoint) منفصلة تمامًا عن أي لوحة تحكم تتطلب مصادقة. يجب أن يقوم مسار عام (public route) مثل /verify/{uuid} بالبحث عن السجل وعرض اسم المستلم، وعنوان الدورة، وتاريخ الإكمال. إذا لم يكن الـ UUID موجودًا، فقم بإرجاع 404. لا حاجة لتسجيل دخول إضافي.

هذا الخيار التصميمي الواحد يحمي الخصوصية ويمنع هجمات التعداد (enumeration attacks).

تصميم قالب Blade

يعيش تصميم شهادتك في عرض Blade قياسي، ولكن يجب عليك التعامل معه بشكل مختلف عن صفحة الويب العادية. محركات رندرة (rendering) ملفات PDF لا تعمل مثل المتصفحات. ملفات CSS الخارجية غير موثوقة لأن محول PDF قد لا يجلبها في نفس السياق. استخدم CSS المضمن (inline CSS) حصريًا.

فكر بالأبعاد الفيزيائية. إذا كنت تريد شهادة بالعرض (landscape)، فقم بتعيين عرض وارتفاع الحاوية مباشرة:

<div style="width: 11in; height: 8.5in; position: relative; padding: 40px; font-family: Georgia, serif;">

قم بوضع التوقيعات والأختام والحدود باستخدام التموضع المطلق (absolute positioning) داخل تلك الحاوية. الخطوط الآمنة للويب (Web-safe fonts) هي خيارك الأكثر أمانًا، رغم أن بعض محركات PDF تسمح بتضمين الخطوط إذا كنت حذرًا. تجنب الاعتماد الثقيل على CSS Grid أو Flexbox المتقدم ما لم تكن متأكدًا من أن محرك الرندرة يدعمها. ولضمان توافق واسع، لا تزال تخطيطات الجداول table التقليدية تحل مشاكل المحاذاة التي لا يستطيع CSS الحديث ضمانها داخل محرك PDF.

حافظ على نظافة الـ markup. كلما كان الـ HTML أبسط، قل احتمال أن يفاجئك المحول بتنسيق مكسور.

إضافة رمز QR

قم بتثبيت حزمة Simple QRCode. أنت بحاجة إلى رمز QR يشير مباشرة إلى صفحة التحقق الخاصة بك. في قالب Blade الخاص بك، قم برندرتها بهذا الشكل:

<img src="{!! QrCode::size(150)->generate(route('certificates.verify', $certificate->uuid)) !!}" style="position: absolute; bottom: 40px; right: 40px;">

عندما يقوم صاحب العمل بمسح ذلك الرمز باستخدام الهاتف، سينتقل إلى تطبيق Laravel الخاص بك ويرى السجل المباشر. هذا الجسر بين العالم المادي والرقمي هو ما يجعل الشهادة قابلة للتحقق. ملف PDF جميل وحده لا يثبت شيئًا، لكن رمز QR يجعل الثقة فورية وبصرية.

اختيار محرك PDF

عادةً ما يختار مطورو Laravel أحد المسارات الثلاثة، ولكل منها مقايضات حقيقية.

DomPDF يعمل بالكامل داخل PHP. قم بتثبيته عبر Composer، ومرر إليه HTML الذي تم رندرتُه بواسطة Blade، ثم احفظ المخرجات. لا يتطلب أي برامج خادم إضافية، مما يجعله جذابًا إذا كنت تستخدم استضافة مشتركة. العيب هو دعم CSS؛ فأدوات التخطيط الحديثة مثل Flexbox و Grid إما مدعومة جزئيًا أو معطلة. كما يمكن أن تكون الخطوط المخصصة (custom webfonts) متعبة، وغالبًا ما يتم رندرة الخلفيات المعقدة بشكل غير صحيح. إذا كان تصميم شهادتك محافظًا، فإن DomPDF سيفي بالغرض. أما إذا كنت بحاجة إلى الدقة، فسيصيبك بالإحباط.

Browsershot يتبع نهجًا مختلفًا. فهو يستخدم Puppeteer لتشغيل نسخة Chrome بدون واجهة (headless Chrome)، ورندرة HTML الخاص بك تمامًا كما يراه المتصفح، ثم تصدير ملف PDF. ولأنه متصفح Chrome حقيقي، فإن أنماط Tailwind والخطوط المخصصة والتخطيطات المتجاوبة تترجم جميعها بشكل مثالي. العقبة تكمن في إعداد الخادم؛ حيث تحتاج إلى تثبيت Node.js و Puppeteer و Chrome. في بعض المنصات، يجب عليك تعطيل Chrome sandbox أو إدارة الذاكرة بعناية لمنع توقف العمليات. إذا كنت تتحكم في خادمك وتحتاج إلى محاكاة التصميم بدقة متناهية (pixel-perfect)، فإن Browsershot لا يُعلى عليه.

واجهة برمجة تطبيقات HTML to PDF هي المسار الثالث. تقوم بجمع HTML الخاص بـ Blade الذي تم عرضه كسلسلة نصية (string)، ثم ترسلها عبر طلب POST إلى خدمة خارجية، وتستلم ملف PDF في المقابل. الفائدة العملية هي عدم وجود أي اعتماد على جانب الخادم (server-side). لن تحتاج لتثبيت Chrome، ولن تضطر لمعالجة مشاكل خطوط PHP المعقدة. ستحصل على ملف PDF متجه (vector) منسق بشكل صحيح. تفرض معظم هذه الخدمات رسومًا لكل مستند، ولكن بالنسبة للعديد من التطبيقات، فإن البساطة التشغيلية تستحق هذه التكلفة. إذا كنت تريد مخرجات عالية الجودة دون عناء إدارة الأنظمة، فهذا عادةً ما يكون أسرع طريق للوصول إلى مرحلة الإنتاج.

سير العمل الكامل

بمجرد اختيار المحرك الخاص بك، يصبح مسار العمل مباشرًا. يجب أن يؤدي حدث إتمام الدورة التدريبية إلى تشغيل مستمع (listener) يقوم بما يلي:

  1. إنشاء UUID وإنشاء سجل الشهادة Certificate.
  2. عرض (Render) واجهة Blade إلى سلسلة HTML باستخدام view('certificates.pdf', compact('certificate'))->render().
  3. تمرير سلسلة HTML هذه إلى خدمة أو حزمة PDF التي اخترتها.
  4. حفظ الملف الناتج في storage/app/certificates/ خلف مسار منطقي، مثل certificates/2024/06/uuid.pdf.
  5. إرفاق الملف بإشعار وإرساله إلى المتعلم عبر البريد الإلكتروني تلقائيًا.

يتولى نظام الإشعارات في Laravel عملية إرسال البريد الإلكتروني بسلاسة. ضع مهمة الإنشاء في الطابور (Queue) إذا كان العرض يستغرق أكثر من ثانية؛ فأنت لا تريد أن ينتظر المتعلم تحميل ملف PDF أثناء تحميل الصفحة.

عندما يقوم المستخدم بتنزيل الملف، سيحصل على ملف PDF قياسي يفتح في أي برنامج عرض. وعندما يقوم بطباعته، يظل النص المتجه (vector) حادًا وواضحًا. وعندما يقوم صاحب عمل بمسح رمز QR، سيقوم تطبيق Laravel الخاص بك بالتحقق من الـ UUID مقابل قاعدة البيانات ويعرض الحقائق.

لماذا لا يمكن التنازل عن المخرجات المتجهة (Vector Output)

تنتج بعض طرق إنشاء ملفات PDF مخرجات نقطية (rasterized). وهذا يعني أن كل جزء من النص يصبح عبارة عن صورة. عند التكبير، تصبح الحروف ضبابية، وتنفجر أحجام الملفات، ولا تستطيع قارئات الشاشة ومحركات البحث استخراج النص.

تحقق دائمًا من أن الطريقة التي اخترتها تنتج ملف PDF متجهًا حقيقيًا. يجب أن يظل النص قابلاً للتحديد، ويجب أن تظل الخطوط حادة عند تكبير بنسبة 400%. يستحق متعلموك وثيقة تبدو رسمية، وليس لقطة شاشة محفوظة بتنسيق PDF.

تساعد المخرجات المتجهة أيضًا في تقليل تكاليف التخزين لديك. فقد يزن صفحة من النص المتجه خمسين كيلوبايت، بينما قد تتجاوز نفس الصفحة كصورة عالية الدقة اثنين ميجابايت. وعند التوسع، يصبح هذا الفرق جوهريًا.

خلاصة يمكنك استخدامها

بناء هذا النظام داخليًا لا يتعلق فقط بتوفير المال على منصة شهادات SaaS. بل يتعلق بالمصداقية. عندما يتمكن المتعلم من طباعة وثيقة، وتسليمها عبر مكتب، ويسمح لشخص غريب بالتحقق منها فورًا باستخدام الهاتف، فقد منحتهم شيئًا دائمًا. أنت من يتحكم في التصميم، وأنت من يتحكم في البيانات. الثقة تعود لعلامتك التجارية، وليس لنطاق فرعي تابع لمزود خدمة.

كيف تتعامل مع إنشاء الشهادات والتحقق منها في تطبيقات Laravel الخاصة بك؟ أود أن أسمع ما نجح معكم في التعليقات.