Codegs Framework v2.0

Lightweight PHP AMVFC framework. Fast, direct, no magic. Built for real projects.

✓ Router + URL Alias ✓ Middleware Pipeline ✓ SpamGuard 5-Layer ✓ .env Config ✓ Mailer (SMTP) ✓ Activity Log ✓ Newsletter ✓ Password Reset PHP 8.2+ required

⚡ Quick Start

1
Database তৈরি করো
phpMyAdmin এ database বানাও, codegs.sql import করো।
2
.env setup করো
.env.example কপি করে .env বানাও। DB_OFFLINE_NAME এ তোমার DB নাম দাও।
3
APP_URL সেট করো
.envAPP_URL=http://localhost/yourproject দাও।
4
Admin account বানাও
http://localhost/yourproject/setup.php — email + password দাও।
5
setup.php মুছে ফেলো!
Login করার পরপরই setup.php delete করো।
⚠️ গুরুত্বপূর্ণ APP_URL এ trailing slash দিও না। সঠিক: http://localhost/codegs — ভুল: http://localhost/codegs/

📁 Folder Structure

yourproject/
├── index.php                   ← Front controller — সব request এখান থেকে শুরু
├── .env                        ← Credentials (git এ push করো না!)
├── .env.example                ← Template
├── config/
│   ├── config.php              ← সব constants define হয় এখানে
│   ├── env.php                 ← .env file loader
│   └── Router.php              ← সব route এক জায়গায়
├── controller/
│   ├── GS_GUI.php              ← Auth, home, profile, password reset
│   ├── BlogController.php      ← Blog CRUD + public show
│   ├── ContactController.php   ← Contact form + admin inbox
│   ├── UserController.php      ← User management (admin)
│   ├── SettingsController.php  ← Site settings + Route Manager
│   ├── NewsletterController.php← Subscribe/unsubscribe + broadcast
│   ├── TestimonialController.php← Testimonials CRUD
│   ├── ActivityController.php  ← Activity log viewer
│   ├── BaseController.php      ← সব controller এর parent
│   └── supporters/
│       └── supporters.php      ← Supporter class (helpers সব এখানে)
├── middleware/
│   ├── MiddlewarePipeline.php  ← Pipeline — order এখানে
│   ├── AuthMiddleware.php      ← Login check + public routes whitelist
│   ├── RateLimitMiddleware.php ← Brute force protection
│   └── VisitorMiddleware.php   ← Auto visitor tracking
├── model/
│   ├── db.php                  ← Database + GS_Model + QueryBuilder
│   ├── Blog_Model.php
│   ├── Contact_Model.php
│   └── User_Model.php
├── view/
│   ├── index.php               ← Homepage (blog section সহ)
│   ├── get_in.php              ← Login page
│   ├── sign_up.php             ← Register page
│   ├── forgot_password.php     ← Forgot password
│   ├── reset_password.php      ← Reset password
│   ├── my_profile.php          ← User profile
│   ├── change_password.php     ← Change password
│   ├── admin/                  ← Admin panel views
│   ├── gs/                     ← Public frontend views
│   └── errors/                 ← 404, 403, 500, 419
├── features/
│   └── CGS_Mailer.php          ← Email sending (PHPMailer wrapper)
├── logs/                       ← Spam logs (browser থেকে access বন্ধ)
├── assets/                     ← CSS, JS, images, uploads
│   └── uploads/
│       ├── blog/               ← Blog images
│       └── users/              ← User avatars
└── setup.php                   ← Admin setup (use করার পর delete করো)

🧩 AMVFC Pattern

Codegs এর নিজস্ব pattern — Laravel বা CodeIgniter না, একদম সরল।

Letterকীকোথায়
AAssets — CSS, JS, imagesassets/
MModel — Database queriesmodel/
VView — HTML templatesview/
FFeatures — External toolsfeatures/ (Mailer, SMS)
CController — Logiccontroller/

Request flow: Browser → index.php → Middleware → Controller → Model → View

🗃️ Database Tables

Framework এর সাথে আসা সব tables — codegs.sql import করলেই ready।

users
posts
contacts
subscribers
testimonials
general_settings
social_links
route_aliases
activity_logs
visitors
password_resets
notifications
companies
services
categories

নিজের project এর জন্য নতুন table বানাতে হলে phpMyAdmin এ বানাও বা CLI migration use করো।

🛣️ Routing System v2.0 নতুন

সব URL এক জায়গায় manage হয় — config/Router.php এ।

তিনটি URL format কাজ করে

TypeExampleকখন ব্যবহার করবে
Clean URL/blog, /contactসবসময় — recommended
Controller/Function/BlogController/index.htaccess active থাকলে
Query String?controller=Blog&function=indexForm action এ, legacy support

Route define করা

// config/Router.php এ যোগ করো:

// Public route (login ছাড়া access করা যাবে)
Router::get('products', 'ProductController', 'index', ['label' => 'Products', 'group' => 'public']);

// POST route
Router::post('do-subscribe', 'NewsletterController', 'subscribe', ['group' => 'public']);

// Login required
Router::any('profile', 'GS_GUI', 'profile', ['auth' => true, 'group' => 'account']);

// Admin only
Router::any('admin-products', 'ProductController', 'admin', ['admin' => true, 'group' => 'admin']);
⚠️ Public route বানালে middleware/AuthMiddleware.php এর $publicRoutes array তেও যোগ করতে হবে।

URL Alias — Settings থেকে change করো

Admin → Settings → URL Route Manager থেকে যেকোনো route এর URL পরিবর্তন করা যায়, code না ছুঁয়েই।

Route KeyDefault URLCustom Alias উদাহরণ
blog/blog/articles
contact/contact/reach-us
register/register/join-us

View এ URL বানাও

<!-- Named route (alias থাকলে alias URL দেবে) -->
<a href="<?= $Supporter->route('blog') ?>">Blog</a>

<!-- Controller + function থেকে -->
<a href="<?= $Supporter->url('BlogController', 'index') ?>">Blog</a>

<!-- Direct query string (সবসময় কাজ করবে) -->
<a href="index.php?controller=BlogController&function=index">Blog</a>

🎮 Controllers

নতুন Controller তৈরি

php codegs make:controller Product
# → controller/ProductController.php তৈরি হবে

Controller structure

<?php
require_once __DIR__ . '/BaseController.php';
require_once __DIR__ . '/../model/Product_Model.php';

class ProductController extends BaseController
{
    private Product_Model $product;

    public function __construct()
    {
        parent::__construct();
        $this->product = new Product_Model();
    }

    // Admin list
    public function index(): void
    {
        $this->requireAdmin();
        $items = $this->product->get_all();
        $this->view('admin/products', compact('items'));
    }

    // Public page
    public function show(): void
    {
        // requireAdmin() বা requireLogin() নেই = public
        $items = $this->product->get_published();
        $this->view('gs/products', compact('items'));
    }

    // Form save
    public function store(): void
    {
        $this->requireAdmin();
        $this->csrf();                           // CSRF check
        $this->Supporter->spam_guard();          // Spam check

        $name = trim($_POST['name'] ?? '');
        if (!$name) {
            $this->back_with_error('Name required.', 'ProductController', 'index');
        }

        $this->product->create(['name' => $name]);
        $this->back_with_success('Product added!', 'ProductController', 'index');
    }

    public function delete(): void
    {
        $this->requireAdmin();
        $id = (int)($_GET['id'] ?? 0);
        $this->product->delete($id);
        $this->back_with_success('Deleted.', 'ProductController', 'index');
    }
}

BaseController methods

Methodকী করে
$this->view('admin/page', $data)View render করো — $data array এর keys view এ variable হয়ে যায়
$this->requireAdmin()Admin / Super admin login required — না থাকলে login page এ redirect
$this->requireLogin()যেকোনো logged-in user — না থাকলে login page এ redirect
$this->csrf()POST form এর CSRF token verify করো
$this->back_with_success($msg, $ctrl, $fn)Flash success + redirect
$this->back_with_error($msg, $ctrl, $fn)Flash error + redirect
$this->json($data, $status)JSON response + exit
$this->showError(404)Error page দেখাও + exit
$this->redirectTo($ctrl, $fn)Simple redirect

🗄️ Models & Database

নতুন Model তৈরি

php codegs make:model Product
# → model/Product_Model.php তৈরি হবে

GS_Model — Direct SQL

// সব rows
$rows = $this->model->read_query("SELECT * FROM posts WHERE status = ?", ['published']);

// একটা row
$post = $this->model->read_one("SELECT * FROM posts WHERE id = ? LIMIT 1", [$id]);

// Single value (count, sum, etc.)
$count = $this->model->read_value("SELECT COUNT(*) FROM users");

// Insert / Update / Delete
$this->model->execute_query(
    "INSERT INTO posts (title, slug) VALUES (?, ?)",
    [$title, $slug]
);

// Last inserted ID
$newId = $this->model->last_insert_id();

// Table exists check
if ($this->model->tableExist('products')) { ... }

QueryBuilder — Fluent Style

// SELECT
$posts = $this->model->table('posts')
    ->select('id, title, slug, created_at')
    ->where('status', '=', 'published')
    ->where('user_id', '=', $userId)
    ->orderBy('created_at', 'DESC')
    ->limit(10)
    ->offset(20)
    ->get();

// Count
$total = $this->model->table('posts')->where('status','=','published')->count();

// First
$post = $this->model->table('posts')->where('slug','=',$slug)->first();

// Insert
$id = $this->model->table('posts')->insert([
    'title' => 'Hello',
    'slug'  => 'hello',
]);

// Update
$this->model->table('posts')->where('id', '=', $id)->update(['title' => 'New Title']);

// Delete
$this->model->table('posts')->where('id', '=', $id)->delete();

// whereIn
$this->model->table('posts')->whereIn('id', [1, 2, 3])->get();

Transaction

$this->model->transaction(function($db) use ($data) {
    $db->execute_query("INSERT INTO orders ...", [...]);
    $db->execute_query("UPDATE stock SET qty = qty - 1 WHERE ...", [...]);
});

🛠️ Supporter Class

controller/supporters/supporters.php — framework এর সব helper এক জায়গায়। Controller এ $this->Supporter দিয়ে access করো, view এ $Supporter দিয়ে।

Auth

check_session()
admin / super admin required — না থাকলে login redirect
check_login()
যেকোনো logged-in user required
is_logged_in(): bool
login আছে কিনা check
is_admin(): bool
admin বা super admin কিনা
is_super_admin(): bool
super admin কিনা

Flash Messages

set_flash_success($msg)
success message session এ রাখো
set_flash_error($msg)
error message session এ রাখো
flashMessage()
view এ alert HTML output করো

Security

csrf_token(): string
CSRF token string return করো
csrf_field(): string
<input type="hidden" name="_token"> HTML return করো
spam_guard($opts)
5-layer spam protection — POST এ call করো
form_token(): string
Honeypot + timestamp hidden fields — form এ print করো
verify_recaptcha($secret)
Google reCAPTCHA v2 verify করো

Routing

route('blog'): string
named route URL — alias থাকলে alias দেবে
url($ctrl, $fn, $params)
controller+function থেকে URL বানাও
location($fn, $ctrl)
redirect করো

Validation

$errors = $this->Supporter->validate($_POST, [
    'name'    => 'required|min:2|max:100',
    'email'   => 'required|email',
    'age'     => 'required|numeric',
    'phone'   => 'min:11|max:14',
    'password'=> 'required|min:6',
]);

if ($errors) {
    // $errors['name'][0] = 'Name is required.'
}

Password

password_maker($pw): string
bcrypt hash — cost config.php এ PASSWORD_COST constant
password_verify($pw, $hash): bool
hash verify করো

Utilities

slug($text): string
'Hello World' → 'hello-world'
str_limit($text, $n): string
text truncate করো
e($value): string
htmlspecialchars shorthand
now(): string
'Y-m-d H:i:s' format current datetime
today(): string
'Y-m-d' format current date
get_client_ip(): string
visitor IP address
is_ajax(): bool
AJAX request কিনা
upload_file($file, $dest, $allowed)
file upload করো — array return করে
json_response($data, $status)
JSON output + exit
dd(...$vars)
dump & die — debug এ কাজে আসে
dump(...$vars)
dump (die করে না)
generate_jwt($payload): string
JWT token তৈরি করো
verify_jwt($token): array|false
JWT verify + payload return করো

🔗 Middleware

প্রতিটা request এ controller এর আগে চলে।

Default Pipeline — MiddlewarePipeline.php

public static function default(): static
{
    return (new static())
        ->add(new VisitorMiddleware())    // IP log করে visitors table এ
        ->add(new RateLimitMiddleware())  // login brute force block করে
        ->add(new AuthMiddleware());      // login check করে
}

Public Routes — AuthMiddleware.php

এই routes গুলো login ছাড়াই access করা যাবে। নতুন public route যোগ করলে এখানে add করো।

private array $publicRoutes = [
    'GS_GUI:home',
    'GS_GUI:get_in',
    'GS_GUI:login',
    'GS_GUI:sign_up',
    'GS_GUI:register',
    'GS_GUI:forgot_password',
    'GS_GUI:forgot_send',
    'GS_GUI:reset_password',
    'GS_GUI:reset_do',
    'GS_GUI:ajax_ping',
    'BlogController:show',
    'ContactController:index',
    'ContactController:submit',
    'NewsletterController:subscribe',
    'NewsletterController:unsubscribe',
    // নতুন public route এখানে যোগ করো:
    // 'ProductController:index',
];

নতুন Middleware

php codegs make:middleware RoleCheck

🛡️ SpamGuard — 5 Layer Protection Security

যেকোনো public form এ একটা লাইনে সম্পূর্ণ spam protection।

1
Honeypot — Hidden field (hp_website) bot fill করলেই block। Human দেখতে পায় না, tab করা যায় না।
2
Keyword Scan — URL link, telegram, casino, slot, SEO spam, crypto, pharma keywords detect করে।
3
IP Rate Limit — একই IP থেকে ঘণ্টায় max ১০টা submit। Session-based, DB ছাড়াই কাজ করে।
4
Time Check — ২ সেকেন্ডের কম সময়ে form fill করলে bot। form_token() দিয়ে timestamp set হয়।
5
Bot User-Agent — curl, python-requests, scrapy, sqlmap, wget, zgrab — সব block।

ব্যবহার

// Controller — csrf() এর পরে:
$this->csrf();
$this->Supporter->spam_guard();

// Custom options:
$this->Supporter->spam_guard([
    'min_time'     => 3,          // minimum 3 seconds to fill form
    'max_per_hour' => 5,          // max 5 submissions per IP per hour
    'log_path'     => 'logs/',    // spam log save location
    'bot_ua'       => true,       // bot user-agent detection
    'honeypot'     => true,       // honeypot field check
    'keywords'     => true,       // spam keyword scan
]);

// View — form এর ভেতরে:
<input type="hidden" name="_token" value="<?= $Supporter->csrf_token() ?>">
<?= (new Supporter())->form_token() ?>   <!-- honeypot + timestamp -->

reCAPTCHA (optional)

// .env এ:
RECAPTCHA_SITE_KEY=your_site_key
RECAPTCHA_SECRET=your_secret_key

// View এ:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey="<?= RECAPTCHA_SITE_KEY ?>"></div>

// Controller এ (spam_guard এর পরে):
if (!$this->Supporter->verify_recaptcha()) {
    $this->back_with_error('reCAPTCHA failed.', 'ContactController', 'index');
}
Spam log logs/spam.log এ save হয়। Browser থেকে access বন্ধ (logs/.htaccess দিয়ে)।

🔐 CSRF Protection

<!-- View — প্রতিটা POST form এ অবশ্যই: -->
<form method="POST">
    <input type="hidden" name="controller" value="ProductController">
    <input type="hidden" name="function"   value="store">
    <input type="hidden" name="_token"     value="<?= $Supporter->csrf_token() ?>">
    <!-- অথবা shorthand: -->
    <?= $Supporter->csrf_field() ?>
    ...
</form>

// Controller এ:
$this->csrf();   // fail হলে session expired page দেখাবে

👤 Auth & Roles — RBAC v3 আপডেট

Role System

RoleSlugDefault Access
Super Adminsuper-adminসব কিছু — কোনো restriction নেই
AdminadminBlog, Users, Contacts, Settings, Newsletter, Testimonials
EditoreditorBlog manage, Testimonials view
SupportsupportContacts view ও edit
Useruserনিজের Profile, Change Password

Permission Check — Controller এ

// পুরনো method (এখনো কাজ করে)
$this->requireAdmin();    // admin + super admin চেক
$this->requireLogin();    // যেকোনো logged-in user

// নতুন RBAC method
$this->Supporter->requirePermission('blog', 'create');  // না থাকলে 403
$this->Supporter->requirePermission('users', 'delete'); // না থাকলে 403

// Boolean check
if ($this->Supporter->can('blog', 'edit')) {
    // edit button দেখাও
}
if ($this->Supporter->can('settings', 'view')) {
    // settings menu দেখাও
}

// Actions: view | create | edit | delete

View এ Permission Check

// View file এ $Supporter available থাকে
if ($Supporter->can('blog', 'create')) {
    echo '<a href="...">New Post</a>';
}
if ($Supporter->is_super_admin()) {
    // super admin only
}
if ($Supporter->is_admin()) {
    // admin menu
}

Custom Role বানানো

Admin Panel → Users → Roles এ গিয়ে নতুন role তৈরি করো, তারপর প্রতিটা module এর জন্য permission set করো।

RBAC কাজ করতে php codegs migrate একবার run করো — rolespermissions table তৈরি হবে।

🔑 Password Reset

Forgot password → email link → reset password flow সম্পূর্ণ built-in।

URLকী করে
/forgot-passwordEmail input form
Email এ link আসেToken generate হয়, password_resets table এ save
/reset-password?token=...New password set করো
কাজ করতে হলে .env এ SMTP credentials দিতে হবে।

📝 Blog Module

Admin URLs

  • /admin-blog — Post list
  • ?function=create — নতুন post
  • ?function=edit&id=X — Edit
  • ?function=toggle&id=X — Draft/Published
  • ?function=delete&id=X — Delete

Public URL

  • /blog — Homepage blog section
  • ?controller=BlogController&function=show&slug=post-slug — Post detail

Image upload, auto slug, view count, author name — সব built-in।

👥 User Module

URL / Actionকী করে
/admin-usersAll users list (paginated)
?function=createনতুন user বানাও (admin করতে পারে)
?function=edit&id=XUser edit করো — role, status, password change
?function=toggle&id=XActive ↔ Inactive toggle
?function=delete&id=XUser delete (নিজেকে করা যাবে না)
/profileনিজের profile edit
/change-passwordPassword change

📬 Contact Module

Public Form

/contact — Visitor এখানে message পাঠায়।

  • SpamGuard protection আছে
  • Settings থেকে contact info দেখায়

Admin Inbox

/admin-contacts — সব messages।

  • Read / Unread badge
  • Message detail view
  • Reply via email link
  • Delete

📨 Newsletter Module

Actionকী করে
Public subscribeEmail form submit → subscribers table এ save
UnsubscribeEmail link এ click করলে auto unsubscribe
/admin-newsletterSubscriber list + broadcast email
Broadcastসব active subscriber কে email পাঠাও — SMTP required

Homepage এ subscribe form যোগ করো

<?php include 'view/gs/partials/newsletter_form.php'; ?>

⭐ Testimonials Module

URLকী করে
/admin → Testimonials menuAll testimonials list
Create / Edit / DeleteName, designation, company, rating, message, avatar
ToggleActive ↔ Inactive
// Homepage বা যেকোনো view এ testimonials দেখাতে:
$testimonials = $this->model->read_query(
    "SELECT * FROM testimonials WHERE status = 'active' ORDER BY id DESC"
);

📋 Activity Log

Admin এর সব action log হয় — কে কখন কী করেছে।

// যেকোনো জায়গা থেকে log করো:
ActivityController::log(
    'post_created',
    'Created blog post: Hello World',
    $_SESSION['user_id']  // optional
);

// Admin এ দেখো:
// /admin-activity → সব log list
// Clear all logs button আছে

⚙️ Settings Module

Admin → /admin-settings থেকে সব site settings control করো।

General Info

  • Site name, email, phone, address
  • Site logo upload
  • SEO meta title & description

System Mode

  • Active — Normal
  • Maintenance — Visitors maintenance page দেখবে
  • Coming Soon — Coming soon page দেখাবে

URL Route Manager

যেকোনো route এর URL slug পরিবর্তন করো — code না ছুঁয়েই।

DB এর route_aliases table এ save হয়।

Social Links

Facebook, WhatsApp, Instagram, YouTube — সব manage করো। Platform, URL, icon class দাও।

View এ settings access করো

// GS_GUI home() এ already load হয়:
$general_settings['site_name']
$general_settings['site_email']
$general_settings['system_mode']

// যেকোনো controller থেকে:
$settings = $this->Supporter->get_settings();

📧 Mailer — CGS_Mailer

require_once __DIR__ . '/../features/CGS_Mailer.php';

// Static call — সহজ
$sent = CGS_Mailer::send(
    to: 'user@example.com',
    subject: 'Welcome to ' . APP_NAME,
    body: CGS_Mailer::template('Welcome!', '<p>Your account is ready.</p>')
);

if (!$sent) {
    // email fail হয়েছে — log করো বা error দেখাও
}

Built-in HTML template

$body = CGS_Mailer::template(
    title: 'Password Reset',
    body: '<p>Click the link below to reset your password:</p>
           <a href="' . $resetUrl . '">Reset Password</a>'
);

CGS_Mailer::send('user@example.com', 'Reset your password', $body);

.env SMTP config

SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your@gmail.com
SMTP_PASS=your_app_password    # Gmail App Password (2FA এ)
SMTP_FROM=your@gmail.com
SMTP_FROM_NAME=CodeGS

💻 CLI Commands

php codegs help                        → সব command দেখো
php codegs --version                   → version
php codegs serve                       → Dev server localhost:8000
php codegs serve localhost:9000        → Custom port

# Code generation
php codegs make:controller Product    → controller/ProductController.php
php codegs make:model Product         → model/Product_Model.php
php codegs make:middleware RoleCheck  → middleware/RoleCheckMiddleware.php
php codegs make:migration products    → model/migrations/YYYY_MM_DD_products.php
php codegs make:command notify:send   → commands/notify_send.php

# Security
php codegs key:generate               → নতুন JWT secret key

Database Migration Commands v3 নতুন

# Pending সব migration run করো — DB automatically update হবে
php codegs migrate

# কোন migration ran, কোনটা pending দেখো
php codegs migrate:status

# সর্বশেষ migration rollback করো
php codegs migrate:rollback

# সব rollback করে fresh migrate করো (সতর্ক!)
php codegs migrate:fresh
Migration কীভাবে কাজ করে: model/migrations/ folder এর সব .php file alphabetical order এ run হয়। প্রতিটা migration এ version, up, down থাকে। _migrations table এ track রাখা হয় কোনটা already ran। Module এর migrations/ folder ও automatically scan হয়।

Migration file structure

<?php
// model/migrations/2026_04_20_create_products.php

return [
    'version'     => '2026_04_20_create_products',
    'description' => 'Create products table',

    'up' => "
        CREATE TABLE IF NOT EXISTS `products` (
          `id`         INT UNSIGNED NOT NULL AUTO_INCREMENT,
          `name`       VARCHAR(255) NOT NULL,
          `price`      DECIMAL(10,2) NOT NULL DEFAULT 0,
          `status`     ENUM('active','inactive') DEFAULT 'active',
          `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
          PRIMARY KEY (`id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    ",

    'down' => "DROP TABLE IF EXISTS `products`;",
];

🧩 Module System v3 নতুন

Codegs এ দুটো উপায়ে module বানানো যায়:

Pluggable Module — কীভাবে কাজ করে

প্রতিটা module modules/ folder এর ভেতরে একটা আলাদা folder। ভেতরে একটা module.json manifest থাকে। index.php boot করার সময় ModuleLoader সব enabled module automatically load করে — routes, migrations, event listeners সব।

modules/
└── InvoiceModule/
    ├── module.json              ← manifest (required)
    ├── InvoiceController.php    ← auto-loaded
    ├── Invoice_Model.php        ← auto-loaded
    ├── views/
    │   ├── index.php
    │   └── admin.php
    └── migrations/
        └── 2026_04_20_invoices.php

module.json — Manifest

{
  "name":        "InvoiceModule",
  "version":     "1.0.0",
  "description": "Invoice management module",
  "author":      "Alamin",
  "enabled":     true,

  "routes": [
    {
      "method":     "any",
      "slug":       "invoices",
      "controller": "InvoiceController",
      "function":   "index",
      "options":    { "label": "Invoices", "group": "admin", "admin": true }
    }
  ],

  "permissions": ["invoice.view", "invoice.create", "invoice.edit", "invoice.delete"],

  "events": {
    "contact.submitted": "InvoiceNotificationListener"
  },

  "depends": []
}

নতুন Pluggable Module বানানোর steps

1
Folder structure তৈরি করো
mkdir -p modules/MyModule/views
mkdir -p modules/MyModule/migrations
2
module.json তৈরি করো
modules/ExampleModule/module.json copy করে rename করো, তারপর edit করো।
3
Controller তৈরি করো
<?php
require_once __DIR__ . '/../../controller/BaseController.php';

class MyController extends BaseController
{
    public function index(): void
    {
        $this->Supporter->requirePermission('my-module', 'view');
        $viewPath = ModuleLoader::viewPath('MyModule', 'index');
        $Supporter = $this->Supporter;
        include $viewPath;
    }
}
4
Migration তৈরি করো
<?php
// modules/MyModule/migrations/2026_04_20_my_table.php
return [
    'version'     => '2026_04_20_my_table',
    'description' => 'Create my_items table',
    'up'   => "CREATE TABLE IF NOT EXISTS `my_items` (...);",
    'down' => "DROP TABLE IF EXISTS `my_items`;",
];
5
Module enable করো
module.json"enabled": true করো।
6
DB migrate করো
php codegs migrate
Module এর migrations/ folder ও automatically scan হবে।

Event Listener (Module এ)

<?php
// modules/MyModule/ContactListener.php

class ContactListener
{
    public function handle(array $data): void
    {
        // contact submit হলে এই function call হবে
        // $data['name'], $data['email'] etc. পাবে
    }
}

// module.json এ:
// "events": { "contact.submitted": "ContactListener" }

Event fire করা (core controller থেকে)

// যেকোনো controller এ:
EventDispatcher::fire('contact.submitted', [
    'name'    => $name,
    'email'   => $email,
    'message' => $message,
]);

Module disable করা

module.json"enabled": false করলে module পুরোপুরি বন্ধ — কোনো code change নেই।

অন্য project এ Module নিয়ে যাওয়া

পুরো modules/MyModule/ folder copy করো নতুন project এ। তারপর php codegs migrate। ব্যস।

➕ Classic Module বানানো (পুরনো way)

উদাহরণ: Product module।

1
Migration তৈরি করো
php codegs make:migration products
# model/migrations/YYYY_MM_DD_products.php এ SQL লেখো
php codegs migrate    # run করো
2
Model বানাও
php codegs make:model Product
# model/Product_Model.php এ query methods লেখো
3
Controller বানাও
php codegs make:controller Product
# controller/ProductController.php এ logic লেখো
4
Route যোগ করো — config/Router.php
Router::get('products',       'ProductController', 'show',  ['group' => 'public']);
Router::any('admin-products', 'ProductController', 'index', ['admin' => true, 'group' => 'admin']);
5
Permission check যোগ করো (RBAC)
// Controller এ:
$this->Supporter->requirePermission('products', 'view');

🚀 Production Deploy Checklist

⚠️ Deploy এর আগে অবশ্যই করো — না করলে security risk!
1
.env update করো
DEV_MODE=false
APP_URL=https://yourdomain.com    # trailing slash দিও না
DB_ONLINE_HOST=your_host
DB_ONLINE_USER=your_user
DB_ONLINE_PASS=your_pass
DB_ONLINE_NAME=your_db
2
JWT Secret পরিবর্তন করো
php codegs key:generate
# output টা .env এর JWT_SECRET এ দাও
3
setup.php মুছে ফেলো
Server এ upload করার আগেই delete করো।
4
.env git এ push করো না
.gitignore এ already আছে — তবু confirm করো।
5
File permissions check করো
logs/ এবং assets/uploads/ folder এ write permission দাও (755 বা 775)।
6
reCAPTCHA keys যোগ করো (recommended)
RECAPTCHA_SITE_KEY=your_site_key
RECAPTCHA_SECRET=your_secret
7
Admin password পরিবর্তন করো
Local এ test করা password production এ রাখো না।

🛡️ Role Manager — কোথায় পাবো, কীভাবে ব্যবহার করবো

📍 URL: index.php?controller=SettingsController&function=roles
Admin sidebar → Role Manager link থেকেও যেতে পারবে।

Role Manager হলো RBAC-এর visual control center। এখান থেকে কোন role কোন module access করতে পারবে সেটা checkbox দিয়ে toggle করা যায় — কোনো SQL লিখতে হবে না।

Permission Matrix — কীভাবে কাজ করে

Columnমানে
Viewসেই module-এর list/index দেখতে পারবে
Createনতুন item তৈরি করতে পারবে
Editexisting item update করতে পারবে
Deleteitem মুছতে পারবে
All (হলুদ checkbox)একসাথে সব toggle করে

Default Roles এবং তাদের Access

RoleBlogUsersContactsSettingsRoles
Super Admin✅ সব✅ সব✅ সব✅ সব✅ সব
Admin✅ সবView+Create+EditView+Edit+DeleteView+Edit❌ নেই
EditorView+Create+Edit❌ নেই❌ নেই❌ নেই❌ নেই
SupportView only❌ নেইView+Edit❌ নেই❌ নেই
User❌ নেই❌ নেই❌ নেই❌ নেই❌ নেই

নতুন Role তৈরি করতে

Role Manager page-এর ডানদিকে "New Role" form আছে। Name + Description দিয়ে Create করো। Role তৈরি হওয়ার পর Permission Matrix থেকে সেই role select করে permissions set করো।

⚠️ System Roles: Super Admin, Admin, User — এই তিনটা is_system=1 তাই delete করা যাবে না। Editor ও Support delete করা যাবে।

User কে Role assign করতে

Admin Panel → Users → Edit → Role dropdown থেকে role select করো। User login করলে সেই role-এর permissions automatically load হবে।


🔐 RBAC System — কোথায় কোথায় কাজ করে

v4 এ যোগ হয়েছে: BlogController, UserController, ContactController — সব admin method এ requirePermission() apply করা হয়েছে।

Controller এ RBAC ব্যবহার

// BaseController এ built-in — যেকোনো controller এ call করো
$this->Supporter->requirePermission('blog', 'delete');
// Permission না থাকলে → 403 page দেখাবে, exit করবে

কোন Controller এ কোন Permission চেক হয়

ControllerMethodRequired Permission
BlogControllerindex()blog → view
create(), store()blog → create
edit(), update(), toggle()blog → edit
delete()blog → delete
show()— (public, no check)
UserControllerindex()users → view
create(), store()users → create
edit(), update(), toggle()users → edit
delete()users → delete
ContactControllerinbox(), show()contacts → view
toggle_read()contacts → edit
delete()contacts → delete
submit()— (public form)

View থেকে Permission check করতে

// View file এ Supporter সবসময় available
<?php if ($Supporter->can('blog', 'delete')): ?>
  <a href="...delete...">Delete</a>
<?php endif; ?>

Session Cache

Permissions login করার সময় $_SESSION['permissions'] এ cache হয়। Role Manager থেকে permissions update করলে সেই user-এর session এ cache clear হয় — পরের request থেকে নতুন permissions load হবে।


⚡ Event System — কোথায় fire হয়, কীভাবে listen করবো

v4 এ যোগ হয়েছে: ContactController এ contact.submitted event fire হয়।

এখন পর্যন্ত যেসব Events fire হয়

Event Nameকোথায় fire হয়Data যা পাওয়া যায়
contact.submittedContactController::submit()name, email, phone, subject, message

Listener তৈরি করতে (Module এ)

// modules/MyModule/ContactListener.php
class ContactListener {
    public function handle(array $data): void {
        // $data['name'], $data['email'], $data['message']
        // e.g. Slack notification, CRM integration
        error_log("New contact from: " . $data['name']);
    }
}

তারপর module.json এ register করো:

"events": {
  "contact.submitted": "ContactListener"
}

নিজে Event fire করতে

// যেকোনো controller বা model থেকে
EventDispatcher::fire('user.registered', [
    'user_id' => $id,
    'email'   => $email,
]);

// Listener register করতে (bootstrap এ)
EventDispatcher::listen('user.registered', function(array $data) {
    // welcome email পাঠাও
});

🧩 Module System — কীভাবে কাজ করে

v4 এ fix হয়েছে: index.php এ module controller lookup যোগ হয়েছে। এখন module enable করলে controller সঠিকভাবে found হবে।

Module Structure

modules/
└── MyModule/
    ├── module.json          ← manifest (required)
    ├── MyModuleController.php
    ├── MyModule_Model.php   ← optional
    ├── views/
    │   ├── index.php
    │   └── admin.php
    └── migrations/
        └── 2026_01_01_my_table.php

module.json এর structure

{
  "name":    "MyModule",
  "version": "1.0.0",
  "enabled": true,
  "routes": [
    {
      "method":     "any",
      "slug":       "my-page",
      "controller": "MyModuleController",
      "function":   "index"
    }
  ],
  "permissions": ["my-module.view", "my-module.create"],
  "events": {
    "contact.submitted": "MyContactListener"
  },
  "depends": []
}

Module enable/disable করতে

module.json"enabled": true করলে framework automatically boot করবে। false করলে ignore করবে — কোনো code change লাগবে না।

Module এর view load করতে

// Controller এ
$viewPath = ModuleLoader::viewPath('MyModule', 'index');
if (file_exists($viewPath)) {
    $Supporter = $this->Supporter;
    include $viewPath;
}

📦 make:module CLI Command

v4 এ নতুন: একটা command এ পুরো module scaffold তৈরি হয়।
php codegs make:module InvoiceModule

এটা automatically তৈরি করবে:

তারপর করতে হবে:

1
module.json"enabled": true করো
2
Route slug customize করো (default: invoice-module)
3
Controller এ নিজের logic লেখো
4
Migration দরকার হলে php codegs make:migration invoice_items চালাও

CLI browser UI থেকেও চালানো যাবে: cli.php → sidebar এ make:module দেখবে।


✅ v4 — সব Changes এক জায়গায়

Categoryকী পরিবর্তন হয়েছেকোথায় কন্ট্রোল করবে
Bug Fix index.php — module controller lookup Automatic — module enable করলেই কাজ করবে
Bug Fix cli.php — migrate commands এখন browser CLI তে কাজ করে cli.php → Database group → migrate/status/rollback
RBAC BlogController, UserController, ContactController এ permission check Admin → Role Manager থেকে permission দাও/সরাও
Role Manager নতুন admin page — permission matrix visual UI ?controller=SettingsController&function=roles
Event System contact.submitted event fire হয় ContactController এ Module এর module.jsonevents block
make:module CLI command — পুরো module scaffold auto-generate php codegs make:module ModuleName বা cli.php
ExampleModule views/index.php + views/admin.php তৈরি হয়েছে module.json এ enabled: true করলে error হবে না
Database roles + permissions table, users.role_id column codegs.sql import করো বা php codegs migrate চালাও

Codegs Framework v4.0  ·  Author: Alamin  ·  AMVFC Pattern  ·  PHP 8.2+