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

Roleকী access করতে পারে
super adminসব কিছু — user এর role পরিবর্তন করতে পারে
adminDashboard, Blog, Users, Contacts, Settings, Newsletter
userনিজের Profile, Change Password — dashboard নয়
// Controller এ:
$this->requireAdmin();    // admin + super admin — others redirect to home
$this->requireLogin();    // সব logged-in user — না থাকলে login redirect

// View এ:
if ($Supporter->is_admin()) {
    // admin menu দেখাও
}
if ($Supporter->is_super_admin()) {
    // super admin only section
}
if ($Supporter->is_logged_in()) {
    // logout button দেখাও
}

Login এর পর কোথায় যাবে

🔑 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

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/mX_products.php
php codegs make:command notify:send   → commands/notify_send.php

php codegs key:generate               → নতুন JWT secret key (production এ ব্যবহার করো)

➕ নতুন Module বানানো — Step by Step

উদাহরণ: Product module বানাবো।

1
Database table বানাও
phpMyAdmin এ products table বানাও বা SQL migration:
php codegs make:migration products
# → model/migrations/mX_products.php এ SQL লেখো
2
Model বানাও
php codegs make:model Product
# model/Product_Model.php এ query methods লেখো:

class Product_Model extends GS_Model {
    private string $table = 'products';

    public function get_all(): array {
        return $this->read_query("SELECT * FROM {$this->table} ORDER BY id DESC") ?: [];
    }
    public function create(array $data): void {
        $this->execute_query("INSERT INTO {$this->table} (name) VALUES (?)", [$data['name']]);
    }
}
3
Controller বানাও
php codegs make:controller Product
# controller/ProductController.php এ logic লেখো
4
Views বানাও
Admin view: view/admin/products.php
Public view: view/gs/products.php
5
Route যোগ করো
// config/Router.php এ:
Router::get('products',       'ProductController', 'show',  ['label' => 'Products', 'group' => 'public']);
Router::any('admin-products', 'ProductController', 'index', ['admin' => true, 'group' => 'admin']);
6
AuthMiddleware এ public route যোগ করো (public হলে)
// middleware/AuthMiddleware.php — $publicRoutes array তে:
'ProductController:show',
7
Sidebar এ link যোগ করো (optional)
Admin views এর sidebar এ নতুন link যোগ করো।

🚀 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 এ রাখো না।

Codegs Framework v2.0.0  ·  Author: Alamin  ·  AMVFC Pattern  ·  PHP 8.2+