গাইড

PHP ও Laravel

Meghly-তে Laravel অ্যাপ্লিকেশন (ওয়েবসাইট, কিউ ওয়ার্কার ও শিডিউলার) এবং যেকোনো সাধারণ PHP সাইট ডিপ্লয় ও পরিচালনার গাইড।

সমর্থিত ভার্সন ও এক্সটেনশন

  • PHP 8.5, 8.4, 8.3 এবং 8.2 (PHP 8.2 ব্যবহার করলে প্যানেলে সতর্কবার্তা দেখায়)। আপনার composer.json ফাইলের config.platform.php অথবা require.php থেকে স্বয়ংক্রিয়ভাবে ভার্সন নির্ধারণ করা হয়।
  • Laravel 10, 11 ও 12 — প্রজেক্টে artisan ফাইল বা laravel/framework প্যাকেজ দেখে স্বয়ংক্রিয়ভাবে শনাক্ত করা হয়।
  • সাধারণ PHP সাইট — প্রজেক্টে composer.json বা index.php ফাইল থাকলে। যদি public/index.php থাকে তবে ডকুমেন্ট রুট হিসেবে public ফোল্ডার ব্যবহৃত হয়, অন্যথায় রিপোজিটরির রুট ফোল্ডার ব্যবহৃত হয়।
  • বিল্ট-ইন এক্সটেনশন: pdo_mysql, pdo_pgsql, zip, bcmath, opcache-সহ প্রয়োজনীয় সব সাধারণ এক্সটেনশন আগে থেকেই ইনস্টল করা থাকে। এছাড়া composer.json-এ ext-pdo_sqlsrv (বা ext-sqlsrv) উল্লেখ থাকলে স্বয়ংক্রিয়ভাবে SQL Server-এর ড্রাইভারও যুক্ত হয়।

Laravel প্রজেক্ট প্রস্তুত করার নিয়ম

১. রিপোজিটরিতে .env ফাইল কমিট করবেন না

প্রোডাকশনের সব কনফিগারেশন প্যানেলের Environment ভেরিয়েবল থেকে আসে এবং Laravel রানটাইমে সরাসরি সেখান থেকেই মানগুলো পড়ে নেয়। Meghly বিল্ডের সময় config:cache চালায় না, ফলে প্যানেলে কোনো ভেরিয়েবল পরিবর্তন করে অ্যাপ রিস্টার্ট দিলেই নতুন মান সাথে সাথে কার্যকর হয়।

২. HTTPS প্রক্সি কনফিগারেশন

অ্যাপটি Meghly-র HTTPS রাউটারের মাধ্যমে চলে। Laravel-কে এই রিভার্স প্রক্সি বিশ্বাস করার নির্দেশ না দিলে সাইটের ভেতরের লিংক ও রিডাইরেক্টগুলো ভুলবশত http:// হয়ে যেতে পারে। এজন্য নিচের কনফিগারেশনটি যুক্ত করুন:

bootstrap/app.php (Laravel 11/12)
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(at: '*');
})

Laravel 10 ব্যবহার করলে app/Http/Middleware/TrustProxies.php ফাইলে protected $proxies = '*'; সেট করুন।

৩. হেলথ চেক (Health Check)

হেলথ চেকের জন্য Meghly /up রাউটে 2xx রেসপন্স আশা করে। Laravel 11 ও 12-তে এই রাউটটি ডিফল্টভাবেই থাকে; তবে Laravel 10 ব্যবহার করলে routes/web.php ফাইলে নিচের লাইনটি যোগ করে নিন:

routes/web.php
Route::get('/up', fn () => response('OK'));

৪. ফ্রন্টএন্ড বিল্ড (Vite)

প্রজেক্টে package.json ফাইল থাকলে বিল্ড ধাপে স্বয়ংক্রিয়ভাবে npm ci এবং npm run build কমান্ড রান হয় এবং কম্পাইল করা অ্যাসেটগুলো public/build ফোল্ডারে জমা হয়।

প্রয়োজনীয় এনভায়রনমেন্ট ভেরিয়েবল

প্যানেলের Environment সেকশনে অন্তত নিচের ভেরিয়েবলগুলো সেট করুন:

Environment
APP_KEY=base64:...        # নিজের পিসিতে রান করুন: php artisan key:generate --show
APP_ENV=production
APP_DEBUG=false
APP_URL=https://shop.example.com
LOG_CHANNEL=stderr
  • APP_KEY একবার সেট করার পর পরবর্তীতে আর পরিবর্তন করবেন না; এটি পরিবর্তন করলে পূর্বের এনক্রিপ্টেড ডেটা এবং ইউজার সেশন অকার্যকর হয়ে যাবে।
  • LOG_CHANNEL=stderr সেট করলে অ্যাপের সব এরর ও লগ সরাসরি প্যানেলের Logs পেজে দেখা যাবে।

অ্যাপের সাথে ডেটাবেস যুক্ত করলে DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME ও DB_PASSWORD ভেরিয়েবলগুলো স্বয়ংক্রিয়ভাবে যুক্ত হয়ে যায়—তাই config/database.php ফাইলে হাত দেওয়ার প্রয়োজন হয় না। একইভাবে Redis যুক্ত করলে REDIS_HOST, REDIS_PASSWORD এবং REDIS_CLIENT=phpredis স্বয়ংক্রিয়ভাবে সেট হয়।

ইমেইল পাঠানোর জন্য (যেহেতু পোর্ট 25 বন্ধ) SMTP কনফিগারেশন ব্যবহার করুন:

Environment
MAIL_MAILER=smtp
MAIL_HOST=<আপনার মেইল সার্ভার>
MAIL_PORT=587
MAIL_USERNAME=...
MAIL_PASSWORD=...

Meghly যে প্রসেসগুলো চালায়

প্রসেসযা রান হয়
webApache + PHP, পোর্ট 8080, হেলথ চেক পাথ /up
workerphp artisan queue:work --sleep=3 --tries=3 --max-time=3600
scheduler (cron)প্রতি মিনিটে php artisan schedule:run
releaseপ্রতিটি ডিপ্লয়ের আগে php artisan migrate --force

আপনার অ্যাপে কিউ (Queue) বা ব্যাকগ্রাউন্ড জবের প্রয়োজন না থাকলে Processes পেজ থেকে worker প্রসেসটি বন্ধ রাখতে পারেন। প্রতিটি নতুন ডিপ্লয়ের পর ওয়ার্কার স্বয়ংক্রিয়ভাবে নতুন কোডে আপডেট হয়ে যায়। এছাড়া প্রজেক্টে Laravel Reverb থাকলে অ্যাপের HTTPS ডোমেইনেই সরাসরি WebSocket কাজ করে।

storage ফোল্ডার ও ফাইল আপলোড

Laravel-এর storage/ ডিরেক্টরিটি একটি স্থায়ী ভলিউমের সাথে যুক্ত থাকে—ফলে ইউজারদের আপলোড করা ফাইল, ক্যাশ, সেশন এবং লগ ফাইল নতুন ডিপ্লয়ের পরেও অক্ষত থাকে।

যেহেতু চলমান কন্টেইনারের মূল ফাইল সিস্টেম রিড-অনলি, তাই রানটাইমে php artisan storage:link কমান্ড চালানো যায় না। পাবলিক ফাইল সার্ভ করার জন্য নিচের যেকোনো একটি পদ্ধতি অনুসরণ করুন:

  • আপনার নিজের পিসিতে php artisan storage:link --relative কমান্ডটি রান করে public/storage সিমলিংকটি (symlink) Git রিপোজিটরিতে কমিট করে দিন (উল্লেখ্য, জিপ ফাইল আপলোড করলে সিমলিংক কাজ নাও করতে পারে)।
  • অথবা ফাইল স্টোরেজের জন্য S3-কম্প্যাটিবল অবজেক্ট স্টোরেজ ব্যবহার করুন (FILESYSTEM_DISK=s3)।

পুরনো ডেটাবেস ইমপোর্ট করা

আপনার আগের সার্ভার থেকে ডেটাবেস এক্সপোর্ট করে নিন:

sh
mysqldump --single-transaction --routines --triggers --no-tablespaces mydb > mydb.sql

এরপর প্যানেলে Databases → আপনার ডেটাবেস → Import SQL dump অপশনে গিয়ে .sql ফাইলটি আপলোড করুন। ইমপোর্ট প্রক্রিয়াটি সরাসরি আপনার বরাদ্দকৃত ডেটাবেসের ভেতরে রান হয়—তাই ডাম্প ফাইলের ভেতরে অন্য কোনো ডেটাবেসের নাম (যেমন USE other_db;) লেখা থাকলে তা কাজ করবে না।

সচরাচর সমস্যা ও সমাধান

যে সমস্যা বা এরর দেখছেনকারণ ও সমাধান
500 Server Error এবং লগে No application encryption keyপ্যানেলের Environment-এ APP_KEY ভেরিয়েবলটি সেট করুন।
সাইটের লিংক বা রিডাইরেক্ট http:// হয়ে যাচ্ছে / Mixed content এররওপরে দেখানো নিয়ম অনুযায়ী trustProxies(at: '*') যুক্ত করুন এবং APP_URL-এ https:// ব্যবহার করুন।
হেলথ চেক ধাপে ডিপ্লয় আটকে যাচ্ছে (Laravel 10)routes/web.php ফাইলে /up রাউটটি যুক্ত করুন।
Permission denied … bootstrap/cacheগিট রিপোজিটরিতে bootstrap/cache ফোল্ডারের ভেতরের ফাইল কমিট করবেন না; বিল্ডের সময় এটি স্বয়ংক্রিয়ভাবে তৈরি হয়।
Release: could not find driver (SQL Server)প্রজেক্টের composer.json ফাইলে ext-pdo_sqlsrv যুক্ত করুন।
Queue-এর জবগুলো রান হচ্ছে নাProcesses পেজে worker চালু আছে কি না এবং QUEUE_CONNECTION সঠিক আছে কি না তা যাচাই করুন।
Scheduled কাজগুলো সময়মতো চলছে নাProcesses পেজে scheduler ক্রন প্রসেসটি চালু আছে কি না তা দেখে নিন।

আটকে গেছেন?

আমাদের ইঞ্জিনিয়ারদের সাথে সরাসরি কথা বলুন — ফোন বা ইমেইলে, বাংলায়।

01782618248shohag.meghly@gmail.com