থিম
অধ্যায় ২: আইসোলেটেড এনভায়রনমেন্ট সেটআপ
এই অধ্যায়ের উদ্দেশ্য হলো প্যাকেজকে এমনভাবে সাজানো যাতে এটি হোস্ট অ্যাপের Kernel ব্যবহার করতে পারে, কিন্তু নিজের কোড, টেস্ট, অ্যাসেট সম্পূর্ণ আলাদা ও আইসোলেটেড থাকে। আমরা ফোল্ডার স্ট্রাকচার, composer.json মেটাডাটা, এবং Composer Path Repository (সিমলিংক) কিভাবে ইন্টারনালি কাজ করে তা ডিপ ডাইভ করব।
২.১ packages ডিরেক্টরি এবং ফোল্ডার স্ট্রাকচার ডিজাইন
হোস্ট অ্যাপের রুটে একটি packages/ ডিরেক্টরি তৈরি করে তার নিচে ভেন্ডর/প্যাকেজ নাম অনুযায়ী নেমস্পেসড ফোল্ডার রাখুন।
laravel-app/
├─ app/
├─ bootstrap/
├─ packages/
│ └─ DevMaster/
│ └─ InvoiceLite/
│ ├─ src/ // মূল কোড (ServiceProvider, Facade, Jobs, etc.)
│ ├─ config/ // প্যাকেজ কনফিগ (প্রিফিক্সড)
│ ├─ routes/ // web.php/api.php (কনফিগ-ড্রিভেন প্রিফিক্স)
│ ├─ database/
│ │ └─ migrations/ // stub বা publish করার ফাইল
│ ├─ resources/
│ │ ├─ views/ // loadViewsFrom + publish
│ │ └─ assets/ // JS/CSS/Images (publish->public/vendor)
│ ├─ tests/ // Orchestra Testbench
│ ├─ composer.json
│ └─ README.md
└─ composer.json- প্রত্যেক ফোল্ডারের ওপর
.gitkeepরাখতে পারেন যাতে গিট খালি ফোল্ডার ট্র্যাক করে। - App Kernel (
App\Http\Kernel) কখনোই এই স্ট্রাকচারে থাকে না; প্যাকেজ কেবল সার্ভিস প্রোভাইডারের মাধ্যমে Kernel-এর রাউটিং/মিডলওয়্যার পাইপলাইন ব্যবহার করবে। - একাধিক প্যাকেজ থাকলে
packages/DevMaster/{PackageName}প্যাটার্ন অনুসরণ করলে PSR-4 অটোলোড ম্যাপ সহজ হয়।
২.২ composer.json কনফিগারেশন এবং মেটাডাটা স্ট্যান্ডার্ড
এই ফাইল আপনার প্যাকেজের পরিচয়, অটোলোড, এবং অটো-ডিসকভারি নির্ধারণ করে। একটি প্রডাকশন-রেডি, কিন্তু লীন উদাহরণ:
json
{
"name": "devmaster/invoicelite",
"description": "InvoiceLite - Laravel invoice package (multi-tenant ready).",
"type": "library",
"license": "MIT",
"authors": [
{ "name": "Your Name", "email": "you@example.com" }
],
"require": {
"php": "^8.2",
"illuminate/support": "^11.0"
},
"require-dev": {
"orchestra/testbench": "^9.0"
},
"autoload": {
"psr-4": {
"DevMaster\\InvoiceLite\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"DevMaster\\InvoiceLite\\Tests\\": "tests/"
}
},
"scripts": {
"test": "vendor/bin/phpunit"
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"laravel": {
"providers": [
"DevMaster\\InvoiceLite\\InvoiceLiteServiceProvider"
],
"aliases": {
"InvoiceLite": "DevMaster\\InvoiceLite\\Facades\\InvoiceLite"
}
}
}
}ডিজাইন নোটস:
"type": "library"রাখুন;"project"দিলে কম্পোজার এটিকে অ্যাপ ধরে নেবে (ভুল)।minimum-stability: dev+prefer-stable: trueদিলে আপনি Path Repository থেকে@devভার্সন নিতে পারবেন, কিন্তু স্টেবল থাকলে সেটাই আগে নেবে।scripts.testরাখলে হোস্ট অ্যাপেওcomposer test -d packages/DevMaster/InvoiceLiteচালিয়ে প্যাকেজ টেস্ট করা সহজ হয়।autoload.filesএ হেল্পার দিলে তা ইগার-লোড হবে; তবে এগুলো নামস্পেসড স্ট্যাটিক ক্লাস হলে আরও সেফ।
২.৩ লোকাল রিপোজিটরি লিংকিং (Symlink Strategy)
প্যাকেজকে হোস্ট অ্যাপে ইনস্টল করা মানে vendor/-এ কপি করা নয়; আমরা Composer Path Repository ব্যবহার করে সিমলিংক তৈরি করব। এতে একই ফাইল সিস্টেমে এক কপি থাকবে, উভয় জায়গায় দেখা যাবে।
২.৩.১ হোস্ট composer.json এ Path Repository
json
{
"repositories": {
"invoicelite": {
"type": "path",
"url": "packages/DevMaster/InvoiceLite",
"options": {
"symlink": true
}
}
}
}symlink: trueহলেvendor/devmaster/invoiceliteআসলেpackages/DevMaster/InvoiceLite-এর সিমলিংক হয়। ফাইল সেভ করলেই হোস্ট অ্যাপে প্রভাব পড়ে।- যদি
symlinkবাদ দেন বা ফাইল সিস্টেম সাপোর্ট না করে, Composer প্যাকেজ ফোল্ডার কপি করবে (ডুপ্লিকেট); ডেভেলপমেন্টে এটি এড়িয়ে চলুন।
২.৩.২ প্যাকেজ ইনস্টল ও ভার্সন রেজল্যুশন
bash
composer require devmaster/invoicelite:@dev- Path রিপোজিটরিতে ট্যাগ না থাকলে ভার্সন স্বয়ংক্রিয়ভাবে
dev-main(অথবা বর্তমান ব্রাঞ্চ) হিসেবে রেজল্ভ হয়। composer.lockএversionফিল্ডdev-mainএবংinstall_pathসিমলিংক পাথ হিসেবে সেভ হয়:
php
// vendor/composer/installed.php
[
'name' => 'devmaster/invoicelite',
'version' => 'dev-main',
'install_path' => __DIR__ . '/../devmaster/invoicelite',
'type' => 'library',
'dev' => true,
],২.৩.৩ সিমলিংক যাচাই ও রিফ্রেশ
bash
ls -l vendor/devmaster/invoicelite
# ... invoicelite -> ../../packages/DevMaster/InvoiceLite- সিমলিংক না হয়ে কপি হয়ে গেলে:
composer remove devmaster/invoicelite→composer clear-cache(প্রয়োজনে) → Path repo কনফিগ ঠিক আছে কিনা চেক → আবারcomposer require .... composer dump-autoloadবাcomposer installসিমলিংক ভাঙে না; এটি শুধু অটোলোড ম্যাপ রিফ্রেশ করে।
২.৩.৪ Kernel অ্যাক্সেসের জন্য গুরুত্বপূর্ণ চেক
- সিমলিংক পাথ যদি ভুল হয়,
InvoiceLiteServiceProviderলোড হবে না, ফলে হোস্ট Kernel রাউট/মিডলওয়্যার আপনার প্যাকেজকে দেখবে না। - হোস্ট অ্যাপ
config/app.phpম্যানুয়ালি স্পর্শ করার দরকার নেই (Auto-Discovery যথেষ্ট)। তবে অটো-ডিসকভারি বন্ধ করতে চাইলে হোস্টcomposer.jsonএ"extra": {"laravel": {"dont-discover": ["devmaster/invoicelite"]}}সেট করতে পারে—ডকুমেন্টে উল্লেখ রাখুন।
🔨 ২.৪ Complete Step-by-Step Implementation: InvoiceBuilder Package তৈরি
এখন আমরা সম্পূর্ণ হাতে-কলমে একটি InvoiceBuilder প্যাকেজ তৈরি করব। প্রতিটি ধাপ copy-paste করে অনুসরণ করুন।
২.৪.১ Project Initialization
Step 1: Laravel প্রজেক্ট তৈরি
bash
# নতুন Laravel অ্যাপ তৈরি
laravel new invoice-demo
cd invoice-demo
# Package ডিরেক্টরি structure তৈরি
mkdir -p packages/DevMaster/InvoiceBuilder/{src,config,database/migrations,routes,resources/views,tests}Step 2: .gitkeep ফাইল যোগ (খালি ডিরেক্টরি track করতে)
bash
touch packages/DevMaster/InvoiceBuilder/src/.gitkeep
touch packages/DevMaster/InvoiceBuilder/tests/.gitkeep
touch packages/DevMaster/InvoiceBuilder/resources/views/.gitkeep২.৪.২ Package composer.json Setup
Complete composer.json তৈরি:
bash
cat > packages/DevMaster/InvoiceBuilder/composer.json << 'EOF'
{
"name": "devmaster/invoice-builder",
"description": "Laravel Invoice Builder - Generate professional invoices with PDF support",
"type": "library",
"license": "MIT",
"keywords": ["laravel", "invoice", "pdf", "mpdf", "billing"],
"authors": [
{
"name": "DevMaster",
"email": "dev@example.com"
}
],
"require": {
"php": "^8.1",
"illuminate/support": "^10.0|^11.0",
"mpdf/mpdf": "^8.2"
},
"require-dev": {
"orchestra/testbench": "^8.0|^9.0",
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"DevMaster\\InvoiceBuilder\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"DevMaster\\InvoiceBuilder\\Tests\\": "tests/"
}
},
"scripts": {
"test": "vendor/bin/phpunit",
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"laravel": {
"providers": [
"DevMaster\\InvoiceBuilder\\InvoiceBuilderServiceProvider"
],
"aliases": {
"InvoiceBuilder": "DevMaster\\InvoiceBuilder\\Facades\\InvoiceBuilder"
}
}
}
}
EOF২.৪.৩ Basic Service Provider Implementation
Minimal Service Provider তৈরি (Chapter 2 scope):
php
// packages/DevMaster/InvoiceBuilder/src/InvoiceBuilderServiceProvider.php
<?php
namespace DevMaster\InvoiceBuilder;
use Illuminate\Support\ServiceProvider;
class InvoiceBuilderServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register()
{
// Basic registration - will expand in Chapter 3
}
/**
* Bootstrap any application services.
*/
public function boot()
{
// Basic boot - will expand in Chapter 3
}
}২.৪.৪ Package Configuration
Configuration ফাইল তৈরি:
php
// packages/DevMaster/InvoiceBuilder/config/invoice-builder.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Invoice Settings
|--------------------------------------------------------------------------
| These are the default settings for invoice generation
*/
'currency' => env('INVOICE_CURRENCY', 'USD'),
'currency_symbol' => env('INVOICE_CURRENCY_SYMBOL', '$'),
'locale' => env('INVOICE_LOCALE', 'en'),
/*
|--------------------------------------------------------------------------
| Company Information (Default)
|--------------------------------------------------------------------------
| Default company information for invoices
*/
'company' => [
'name' => env('INVOICE_COMPANY_NAME', 'Your Company'),
'address' => env('INVOICE_COMPANY_ADDRESS', ''),
'email' => env('INVOICE_COMPANY_EMAIL', ''),
'phone' => env('INVOICE_COMPANY_PHONE', ''),
'website' => env('INVOICE_COMPANY_WEBSITE', ''),
],
/*
|--------------------------------------------------------------------------
| PDF Generation Settings
|--------------------------------------------------------------------------
| Settings for PDF generation using mPDF
*/
'pdf' => [
'format' => 'A4',
'orientation' => 'P', // P for Portrait, L for Landscape
'margin' => [
'top' => 15,
'bottom' => 15,
'left' => 15,
'right' => 15,
],
'font' => [
'default' => 'dejavu-sans', // mPDF compatible font
'size' => 10,
],
'watermark' => [
'enabled' => false,
'text' => 'DRAFT',
'opacity' => 0.1,
],
],
/*
|--------------------------------------------------------------------------
| Database Settings
|--------------------------------------------------------------------------
| Database table configurations
*/
'database' => [
'table_prefix' => env('INVOICE_TABLE_PREFIX', 'invoice_'),
'connection' => env('INVOICE_DB_CONNECTION', null), // null = default connection
],
/*
|--------------------------------------------------------------------------
| Invoice Number Settings
|--------------------------------------------------------------------------
| Settings for automatic invoice number generation
*/
'invoice_number' => [
'prefix' => env('INVOICE_NUMBER_PREFIX', 'INV-'),
'length' => 6, // Padding length for numbers (e.g., 000001)
'start_from' => 1,
],
/*
|--------------------------------------------------------------------------
| Tax Settings
|--------------------------------------------------------------------------
| Default tax configurations
*/
'tax' => [
'default_rate' => 0.0, // 0% default
'label' => 'Tax',
'included' => false, // Tax is added on top
],
];২.৪.৫ Placeholder Files (Chapter 2 scope)
Create placeholder files for future chapters:
bash
# Create empty files that we'll build in later chapters
touch packages/DevMaster/InvoiceBuilder/src/Services/.gitkeep
touch packages/DevMaster/InvoiceBuilder/src/Facades/.gitkeep
touch packages/DevMaster/InvoiceBuilder/src/helpers.php
touch packages/DevMaster/InvoiceBuilder/routes/web.phpBasic Helper (empty for now):
php
// packages/DevMaster/InvoiceBuilder/src/helpers.php
<?php
// Helper functions will be added in later chaptersBasic Routes (placeholder):
php
// packages/DevMaster/InvoiceBuilder/routes/web.php
<?php
// Routes will be added in Chapter 6২.৪.৯ Local Repository Setup
Main app এর composer.json modify করুন:
json
{
"repositories": [
{
"type": "path",
"url": "./packages/DevMaster/InvoiceBuilder",
"options": {
"symlink": true
}
}
]
}২.৪.১০ Package Installation & Testing
Install করুন:
bash
# Main Laravel app directory তে
composer require devmaster/invoice-builder:@dev
# Auto-discovery run করুন
php artisan package:discover
# Configuration publish করুন
php artisan vendor:publish --tag=invoice-builder-configBasic Testing (Chapter 2 scope):
bash
# Check if package is discovered
php artisan package:discover | grep InvoiceBuilder
# Check config is published
php artisan vendor:publish --tag=invoice-builder-config
ls config/invoice-builder.php
# Basic tinker test
php artisan tinker
>>> config('invoice-builder.currency')
>>> class_exists('DevMaster\InvoiceBuilder\InvoiceBuilderServiceProvider')২.৫ অধ্যায় ২: এক নজরে কী শিখলেন
এই অধ্যায় শেষে আপনি যা হাতে-কলমে আয়ত্ত করেছেন:
- প্যাকেজ ফোল্ডার স্থাপত্য -
packages/DevMaster/InvoiceBuilderস্ট্রাকচার কেন ও কীভাবে সাজাতে হয়। composer.jsonসেটআপ - PSR-4 অটোলোড, মেটাডাটা, এবং Laravel auto-discovery কনফিগারেশন।- লোকাল প্যাকেজ লিংকিং - Path repository + symlink ব্যবহার করে একই কোডে দ্রুত ডেভেলপমেন্ট।
- মিনিমাল সার্ভিস প্রোভাইডার -
register()ওboot()এর বেস স্ট্রাকচার তৈরি (পরের অধ্যায়ে বিস্তৃত হবে)। - পাব্লিশেবল কনফিগ ফাইল - ইউজারের অ্যাপে publish করা যায় এমন প্যাকেজ কনফিগ প্রস্তুত করা।
- ভবিষ্যৎ অধ্যায়ের ভিত্তি - Facade, Service, Routes, Views ইত্যাদির জন্য placeholder ফাইল/স্ট্রাকচার।
দ্রুত যাচাই কমান্ড (Quick Check):
bash
# প্যাকেজ স্ট্রাকচার ঠিক আছে কি না
ls -la packages/DevMaster/InvoiceBuilder/
# প্যাকেজ auto-discovery কাজ করছে কি না
php artisan package:discover | grep InvoiceBuilder
# কনফিগ publish হয়েছে কি না
php artisan vendor:publish --tag=invoice-builder-config
cat config/invoice-builder.php
# vendor path symlink হয়েছে কি না
ls -l vendor/devmaster/invoice-builder