একটি সার্টিফিকেট তখনই গুরুত্বপূর্ণ যখন মানুষ সেটি বিশ্বাস করে। যখন একজন শিক্ষার্থী চাকরির আবেদনের সাথে একটি PDF যুক্ত করেন, তখন একজন নিয়োগকারী ব্যবস্থাপকের (hiring manager) কয়েক সেকেন্ডের মধ্যেই সেটি আসল কিনা তা নিশ্চিত করার ক্ষমতা থাকা উচিত। Laravel আপনাকে কোনো তৃতীয় পক্ষের প্ল্যাটফর্মের ওপর নিয়ন্ত্রণ না দিয়ে নিজেই সেই বিশ্বাস তৈরি করার সরঞ্জাম দেয়। আপনি ব্র্যান্ডিং, ডেটা এবং যাচাইকরণ চেইন (verification chain) সম্পূর্ণভাবে নিজের নিয়ন্ত্রণে রাখতে পারেন।

লক্ষ্যটি সহজ: একটি পেশাদার PDF তৈরি করা যা প্রিন্ট করার সময় দেখতে সুন্দর লাগে, তাৎক্ষণিক যাচাইকরণের জন্য একটি স্ক্যানযোগ্য QR কোড থাকে এবং একটি অনন্য রেকর্ড সংরক্ষণ করে যা অনুমান করা বা জাল করা সম্ভব নয়। এটি কীভাবে তৈরি করবেন তা নিচে দেওয়া হলো।

ডাটাবেস লেয়ার দিয়ে শুরু করুন

সার্টিফিকেটের জন্য auto-incrementing ID ব্যবহার করবেন না। 8473-এর মতো একটি ID অনুমান করা সহজ। কেউ আপনার ভেরিফিকেশন পেজে নম্বরগুলো পরিবর্তন করে আপনার ইস্যু করা প্রতিটি ক্রেডেনশিয়াল (credential) স্ক্র্যাপ করতে পারে। পরিবর্তে, সার্টিফিকেট রেকর্ড তৈরি করার সময় একটি UUID তৈরি করুন।

আপনার মাইগ্রেশনে UUID-টি একটি string হিসেবে সংরক্ষণ করুন। যখন একজন ব্যবহারকারী একটি কোর্স শেষ করেন, তখন একটি ইভেন্ট ফায়ার করুন যা ব্যবহারকারী এবং কোর্সের সাথে লিঙ্ক করা একটি Certificate মডেল তৈরি করবে। ভেরিফিকেশন এন্ডপয়েন্টটিকে (endpoint) যেকোনো অথেন্টিকেটেড ড্যাশবোর্ড থেকে সম্পূর্ণ আলাদা রাখুন। /verify/{uuid}-এর মতো একটি পাবলিক রুট রেকর্ডটি খুঁজে বের করবে এবং প্রাপকের নাম, কোর্সের শিরোনাম এবং সমাপ্তির তারিখ প্রদর্শন করবে। যদি UUID না থাকে, তবে একটি 404 রিটার্ন করুন। অতিরিক্ত কোনো লগইনের প্রয়োজন নেই।

এই একটি মাত্র ডিজাইনের সিদ্ধান্ত গোপনীয়তা রক্ষা করে এবং enumeration attack প্রতিরোধ করে।

Blade টেমপ্লেট ডিজাইন করা

আপনার সার্টিফিকেটের ডিজাইন একটি স্ট্যান্ডার্ড Blade ভিউতে থাকে, তবে আপনাকে এটিকে সাধারণ ওয়েব পেজ থেকে আলাদাভাবে বিবেচনা করতে হবে। PDF রেন্ডারিং ইঞ্জিনগুলো ব্রাউজারের মতো আচরণ করে না। এক্সটার্নাল স্টাইলশিট (stylesheets) নির্ভরযোগ্য নয় কারণ PDF কনভার্টার একই কনটেক্সটে সেগুলো নাও আনতে পারে। শুধুমাত্র ইনলাইন CSS ব্যবহার করুন।

ভৌত মাত্রার (physical dimensions) কথা চিন্তা করুন। আপনি যদি ল্যান্ডস্কেপ সার্টিফিকেট চান, তবে কন্টেইনারের প্রস্থ এবং উচ্চতা সরাসরি সেট করুন:

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

সেই কন্টেইনারের ভেতরে absolute positioning ব্যবহার করে স্বাক্ষর, সিল এবং বর্ডারগুলো স্থাপন করুন। ওয়েব-সেফ ফন্ট (Web-safe fonts) ব্যবহার করা সবচেয়ে নিরাপদ, যদিও কিছু PDF ইঞ্জিন সতর্কতার সাথে ফন্ট এমবেড করার অনুমতি দেয়। CSS Grid বা উন্নত Flexbox-এর ওপর অতিরিক্ত নির্ভরতা এড়িয়ে চলুন, যদি না আপনি নিশ্চিত হন যে আপনার রেন্ডারিং ইঞ্জিন এটি সমর্থন করে। ব্যাপক সামঞ্জস্যের (compatibility) জন্য, পুরনো আমলের table লেআউট এখনও এমন অ্যালাইনমেন্ট সমস্যা সমাধান করতে পারে যা আধুনিক CSS একটি PDF ইঞ্জিনের ভেতরে নিশ্চিত করতে পারে না।

মার্কআপ পরিষ্কার রাখুন। 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-এর মাধ্যমে ইনস্টল করুন, আপনার Blade-রেন্ডার করা HTML এতে পাস করুন এবং আউটপুট সেভ করুন। এর জন্য কোনো অতিরিক্ত সার্ভার সফটওয়্যারের প্রয়োজন হয় না, যা শেয়ার্ড হোস্টিংয়ের ক্ষেত্রে এটিকে আকর্ষণীয় করে তোলে। এর অসুবিধা হলো CSS সাপোর্ট। Flexbox এবং Grid-এর মতো আধুনিক লেআউট টুলগুলো হয় আংশিকভাবে সমর্থিত অথবা কাজ করে না। কাস্টম ওয়েবফন্ট (webfonts) ব্যবহার করা কিছুটা জটিল হতে পারে এবং জটিল ব্যাকগ্রাউন্ড প্রায়শই ভুলভাবে রেন্ডার হয়। আপনার সার্টিফিকেটের ডিজাইন যদি সাধারণ হয়, তবে DomPDF কাজ করবে। কিন্তু আপনার যদি নিখুঁত ডিজাইনের প্রয়োজন হয়, তবে এটি আপনাকে হতাশ করবে।

Browsershot ভিন্ন একটি পদ্ধতি অবলম্বন করে। এটি একটি হেডলেস Chrome ইনস্ট্যান্স চালানোর জন্য Puppeteer ব্যবহার করে, আপনার HTML-কে ঠিক যেভাবে ব্রাউজার দেখে সেভাবেই রেন্ডার করে এবং একটি PDF এক্সপোর্ট করে। যেহেতু এটি আসল Chrome, তাই আপনার Tailwind স্টাইল, কাস্টম ফন্ট এবং রেসপন্সিভ লেআউট সবই নিখুঁতভাবে কাজ করবে। এর অসুবিধা হলো সার্ভার সেটআপ। আপনার Node.js, Puppeteer এবং Chrome ইনস্টল করা থাকতে হবে। কিছু প্ল্যাটফর্মে, প্রসেস আটকে যাওয়া রোধ করতে আপনাকে Chrome sandbox নিষ্ক্রিয় করতে হবে বা মেমরি সাবধানে পরিচালনা করতে হবে। আপনি যদি আপনার সার্ভার নিয়ন্ত্রণ করেন এবং পিক্সেল-পারফেক্ট ডিজাইন রেপ্লিকেশন চান, তবে Browsershot-এর কোনো বিকল্প নেই।

HTML to PDF API হলো তৃতীয় পথ। আপনি আপনার রেন্ডার করা Blade HTML-কে একটি স্ট্রিং হিসেবে সংগ্রহ করেন, সেটি একটি এক্সটার্নাল সার্ভিসে POST করেন এবং বিনিময়ে একটি PDF পান। এর ব্যবহারিক সুবিধা হলো সার্ভার-সাইড ডিপেন্ডেন্সি বা নির্ভরতা নেই বললেই চলে। আপনাকে Chrome ইনস্টল করতে হবে না। PHP-এর ফন্ট সংক্রান্ত জটিলতা নিয়ে আপনাকে হিমশিম খেতে হবে না। আপনি সঠিকভাবে ফরম্যাট করা একটি ভেক্টর PDF পাবেন। এই পরিষেবাগুলোর বেশিরভাগই প্রতিটি ডকুমেন্টের জন্য চার্জ করে, তবে অনেক অ্যাপ্লিকেশনের ক্ষেত্রে এই পরিচালনগত সহজতা খরচের চেয়েও বেশি মূল্যবান। আপনি যদি সিস্টেম অ্যাডমিনিস্ট্রেশনের ঝামেলা ছাড়াই উচ্চ-মানের আউটপুট চান, তবে এটি সাধারণত প্রোডাকশনে যাওয়ার দ্রুততম পথ।

সম্পূর্ণ ওয়ার্কফ্লো

একবার আপনি আপনার ইঞ্জিনটি বেছে নিলে, পাইপলাইনটি বেশ সহজ হয়ে যায়। একটি কোর্স সম্পন্ন হওয়ার ইভেন্ট একটি লিসেনারকে ট্রিগার করবে যা নিচের কাজগুলো করবে:

  1. একটি UUID তৈরি করুন এবং Certificate রেকর্ডটি তৈরি করুন।
  2. view('certificates.pdf', compact('certificate'))->render() ব্যবহার করে Blade ভিউটিকে একটি HTML স্ট্রিং হিসেবে রেন্ডার করুন।
  3. সেই HTML স্ট্রিংটি আপনার নির্বাচিত PDF সার্ভিস বা প্যাকেজে পাঠিয়ে দিন।
  4. ফলাফলস্বরূপ প্রাপ্ত ফাইলটি একটি লজিক্যাল পাথ ব্যবহার করে storage/app/certificates/ ডিরেক্টরিতে সেভ করুন, যেমন certificates/2024/06/uuid.pdf
  5. ফাইলটি একটি নোটিফিকেশনের সাথে যুক্ত করুন এবং স্বয়ংক্রিয়ভাবে শিক্ষার্থীর কাছে ইমেল করে দিন।

Laravel-এর নোটিফিকেশন সিস্টেম খুব সুন্দরভাবে ইমেলটি হ্যান্ডেল করে। রেন্ডারিং করতে যদি এক সেকেন্ডের বেশি সময় লাগে, তবে জেনারেশন জবটি কিউ (Queue) করে রাখুন। আপনি নিশ্চয়ই চান না যে পেজ লোড হওয়ার সময় একজন শিক্ষার্থী PDF-এর জন্য অপেক্ষা করুক।

ব্যবহারকারী যখন ফাইলটি ডাউনলোড করবেন, তখন তারা একটি স্ট্যান্ডার্ড PDF পাবেন যা যেকোনো ভিউয়ারে খোলা যাবে। যখন তারা এটি প্রিন্ট করবেন, ভেক্টর টেক্সটটি একদম স্পষ্ট থাকবে। যখন কোনো নিয়োগকর্তা QR কোডটি স্ক্যান করবেন, আপনার Laravel অ্যাপ ডাটাবেসের সাথে UUID যাচাই করে তথ্যগুলো প্রদর্শন করবে।

কেন ভেক্টর আউটপুট অপরিহার্য

কিছু PDF জেনারেশন পদ্ধতি রাস্টারাইজড (rasterized) আউটপুট তৈরি করে। এর মানে হলো প্রতিটি টেক্সট একটি ছবিতে পরিণত হয়। জুম করলে অক্ষরগুলো ঝাপসা হয়ে যায়। ফাইলের আকার অনেক বেড়ে যায়। স্ক্রিন রিডার এবং সার্চ ইঞ্জিনগুলো সেখান থেকে টেক্সট সংগ্রহ করতে পারে না।

সবসময় যাচাই করে নিন যে আপনার নির্বাচিত পদ্ধতিটি একটি প্রকৃত ভেক্টর PDF তৈরি করছে কি না। টেক্সটটি যেন সিলেক্ট করা যায়। ৪০০ শতাংশ জুম করলেও লাইনগুলো যেন স্পষ্ট থাকে। আপনার শিক্ষার্থীরা এমন একটি ডকুমেন্ট পাওয়ার যোগ্য যা দেখতে অফিসিয়াল মনে হয়, কেবল একটি PDF হিসেবে সেভ করা স্ক্রিনশট নয়।

ভেক্টর আউটপুট আপনার স্টোরেজ খরচও কমিয়ে রাখে। ভেক্টর টেক্সটের একটি পৃষ্ঠার ওজন মাত্র ৫০ কিলোবাইট হতে পারে। কিন্তু উচ্চ-রেজোলিউশনের ছবি হিসেবে একই পৃষ্ঠার আকার ২ মেগাবাইটের বেশি হতে পারে। বড় পরিসরে এই পার্থক্যটি অত্যন্ত গুরুত্বপূর্ণ।

একটি কার্যকর শিক্ষা যা আপনি ব্যবহার করতে পারেন

এটি ইন-হাউস তৈরি করা মানে কেবল একটি SaaS সার্টিফিকেট প্ল্যাটফর্মের খরচ বাঁচানো নয়। এটি মূলত বিশ্বাসযোগ্যতার বিষয়। যখন একজন শিক্ষার্থী একটি ডকুমেন্ট প্রিন্ট করতে পারেন, সেটি কাউকে হাতে দিতে পারেন এবং একজন অপরিচিত ব্যক্তি ফোনের মাধ্যমে তাৎক্ষণিকভাবে সেটি যাচাই করতে পারেন, তখন আপনি তাদের এমন কিছু দিচ্ছেন যা স্থায়ী। আপনি ডিজাইন নিয়ন্ত্রণ করছেন। আপনি ডেটা নিয়ন্ত্রণ করছেন। বিশ্বাসটি আপনার ব্র্যান্ডের কাছে থাকে, কোনো ভেন্ডরের সাবডোমেইনের কাছে নয়।

আপনি আপনার নিজস্ব Laravel অ্যাপ্লিকেশনে সার্টিফিকেট জেনারেশন এবং ভেরিফিকেশন কীভাবে হ্যান্ডেল করেন? কমেন্টে জানান আপনার জন্য কোনটি কার্যকর হয়েছে।