Raptor Framework - Бүрэн танилцуулга
codesaur/raptor - PSR стандартууд дээр суурилсан, олон давхаргат архитектуртай, олон байгууллагын (multi-tenant) PHP CMS фреймворк.
Агуулга
- Танилцуулга
- Суулгах
- Тохиргоо (.env)
- Архитектур
- Middleware pipeline
- Модулиуд - модуль бүр өөрийн дэд бүлэгтэй
- Template систем
- Routing
- Controller
- Model
- Тест
- Хэрэглээний жишээ
1. Танилцуулга
codesaur/raptor нь PSR-7/PSR-15 middleware суурьтай PHP фреймворк юм. Анхдагч байдлаараа Web (нийтийн вебсайт) болон Dashboard (админ панель) гэсэн хоёр апп-тай ирэх бөгөөд developer хэрэгцээндээ тааруулан хэдэн ч апп давхарга нэмж болно.
Гол боломжууд
- PSR-7/PSR-15 middleware суурьтай архитектур
- JWT + Session нэвтрэлт баталгаажуулалт
- Олон байгууллагын (multi-tenant) RBAC эрхийн удирдлага
- Олон хэл дэмжлэг (Localization)
- CMS модулиуд: Мэдээ, Хуудас, Файл, Лавлах, Тохиргоо
- Дэлгүүр модуль (Бүтээгдэхүүн, Захиалга, Үнэлгээ)
- MySQL, PostgreSQL алийг нь ч дэмжинэ
- SQL файл суурьтай өгөгдлийн сангийн migration систем
- codesaur/template өөрийн template engine (Twig-маягийн синтакс)
- OpenAI интеграци (moedit editor)
- Зураг optimize хийх (GD)
- PSR-3 лог систем
- И-мэйл илгээх (Brevo API, SMTP, PHP mail)
- PSR-14 Event Dispatcher систем (Discord, и-мэйл, лог - listener-ээр)
- Discord webhook мэдэгдэл (event listener-ээр)
- SEO: Хайлт, Sitemap, XML Sitemap, RSS feed
- Спам хамгаалалт (honeypot, HMAC token, rate limiting, Cloudflare Turnstile)
- CSRF хамгаалалт (CsrfMiddleware, csrfFetch)
- Shared hosting / WAF тохиромж (cPanel/LiteSpeed/mod_security): HTTP method override, body encoding
- File-based DB cache (PSR-16 SimpleCache) - автомат invalidation-тэй
- Холбоо барих форм, мессеж удирдлага
- Мэдээний сэтгэгдэл, 1 түвшний хариулт
- Бүтээгдэхүүний үнэлгээ, одтой үнэлгээ (1-5)
- Админ имэйл мэдэгдэл: мессеж, захиалга, сэтгэгдэл, үнэлгээ (суваг тус бүрд тохируулах боломжтой)
- Хогийн сав модуль - устгасан контент бичлэгүүдийг сэргээх боломжтой
codesaur экосистем
Raptor нь дараах codesaur packages-тэй хамтран ажиллана:
| Package | Зориулалт |
|---|---|
codesaur/http-application | PSR-15 Application, Router, Middleware суурь |
codesaur/dataobject | PDO суурьтай ORM (Model, LocalizedModel) |
codesaur/template | Template engine wrapper |
codesaur/http-client | HTTP client (OpenAI API дуудлага) |
codesaur/container | PSR-11 Dependency Injection Container |
2. Суулгах
Шаардлага
- PHP 8.2.1+
- Composer
- MySQL or PostgreSQL
- PHP extensions:
ext-gd,ext-intl
Composer ашиглан суулгах
composer create-project codesaur/raptor my-project
Composer-ийн setup-env скрипт (create-project, composer install, composer update бүрт ажиллана):
.env.exampleфайлыг.envруу автоматаар хуулна (.envбайхгүй бол)RAPTOR_JWT_SECRETнууц түлхүүрийг автоматаар үүсгэнэ (зөвхөн байхгүй, хоосон, эсвэл placeholder хэвээр байвал - бодит secret-ийг хэзээ ч дарж солихгүй)
Хэрэв
.envфайл үүсээгүй болcp docs/conf.example/.env.example .envкомандаар гараар хуулж,RAPTOR_JWT_SECRETутгыг өөрөө тохируулна.
Гараар суулгах
git clone https://github.com/codesaur-php/Raptor.git my-project
cd my-project
composer install
composer install дээрх setup-env скриптийг ажиллуулж .env-ийг автоматаар үүсгэнэ.
3. Тохиргоо
.env файлын бүх тохиргоонуудын тайлбар:
Орчин ба Апп
# Орчны горим: development эсвэл production
CODESAUR_APP_ENV=development
# Аппликейшний нэр
CODESAUR_APP_NAME=raptor
# Цагийн бүс (заавал биш)
#CODESAUR_APP_TIME_ZONE=Asia/Ulaanbaatar
developmentгоримд алдааг дэлгэцэн дээр харуулахын зэрэгцээlogs/code.logфайлд бичнэproductionгоримд зөвхөнlogs/code.logфайлд бичнэ
Өгөгдлийн сан
RAPTOR_DB_HOST=localhost
RAPTOR_DB_NAME=raptor
RAPTOR_DB_USERNAME=root
RAPTOR_DB_PASSWORD=
RAPTOR_DB_CHARSET=utf8mb4
RAPTOR_DB_COLLATION=utf8mb4_unicode_ci
RAPTOR_DB_PERSISTENT=false
- Шинэ орчинд хоосон өгөгдлийн санг developer өөрөө заавал урьдчилж үүсгэнэ - Raptor зөвхөн бэлэн сан руу холбогддог, санг өөрөө үүсгэдэггүй (жишээ нь MySQL дээр:
CREATE DATABASE raptor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;) - Харин сан доторх бүх хүснэгт болон анхны seed өгөгдлийг (permission, role, орчуулга, цэс, жишээ контент) Raptor анх ажиллах үедээ Model классуудаараа автоматаар үүсгэнэ
- Хүснэгтүүдийг гараар үүсгэж болохгүй - бүтэц нь зөрсөн хүснэгт дээр код ажиллахгүй
JWT (JSON Web Token)
RAPTOR_JWT_ALGORITHM=HS256
RAPTOR_JWT_LIFETIME=2592000
RAPTOR_JWT_SECRET=auto-generated
#RAPTOR_JWT_LEEWAY=10
RAPTOR_JWT_SECRET- Composer-ийн скриптээр автоматаар 128 тэмдэгт (64 байт hex) үүсгэнэRAPTOR_JWT_LIFETIME- Токений хүчинтэй хугацаа секундээр (2592000 = 30 хоног)RAPTOR_JWT_LEEWAY- Серверийн цагийн зөрөөг зөвшөөрөх хугацаа
WAF Compatibility (mod_security)
RAPTOR_WAF_BODY_ENCODING=true
RAPTOR_WAF_BODY_ENCODING-true(default) үедcsrfFetch()form талбаруудыг base64-аар кодолж, mod_security маягийн WAF-д POST body доторх HTML/JS-төстэй rich-text харагдахгүй болгоно;BodyEncodingMiddlewareserver тал дээр decode хийнэ. Body-inspection хийдэг WAF-гүй хост дээрfalseболго. ДэлгэрэнгүйгCLAUDE.md-ийн "Shared Hosting / WAF Compatibility" хэсгээс үз.
Session cookie-ийн хугацааг Raptor
SessionMiddlewareдотроос 30 хоног болгож тохируулдаг (session_set_cookie_params(...)) - энэ нь зөвхөн client талын cookie бөгөөд практик дээр админ browser хаасан ч удаан нэвтэрсэн хэвээр үлддэг нь батлагдсан. Харин server талын session файлын цэвэрлэгээ (session.gc_maxlifetime) нь Raptor-аар бус host-ийн php.ini-аар удирдагдана; session file-ийг найдвартай хадгалж хугацаанд нь цэвэрлэдэг байлгахыг хүсвэл host бүрд түүнийг тохируулна - SESSION-LIFETIME.md-г үз.
"Яагаад миний PUT/DELETE хүсэлт browser дээр POST болж харагдаж байна вэ?"
Энэ нь алдаа биш, зориудаар. DevTools -> Network нээгээд method="PUT" (эсвэл PATCH/DELETE) гэсэн dashboard form илгээхэд хүсэлт POST-оор гарахыг харна. csrfFetch() эдгээр verb-ийг зориудаар POST болгож, жинхэнэ verb-ийг X-HTTP-Method-Override request header-аар дамжуулдаг - учир нь олон shared host (cPanel/LiteSpeed + mod_security) PUT/PATCH/DELETE-г PHP ажиллахаас өмнө web-server түвшинд блоклодог. Server тал дээр MethodOverrideMiddleware тэр header-ийг уншиж, routing-аас өмнө жинхэнэ method-ийг сэргээдэг тул GET_PUT('/news/{id}') нь PUT handler-руугаа хэвийн очно.
DevTools -> Network -> (хүсэлт) -> Headers дотроос юу болж буйг шалгах:
- Request method:
POST(tunnel) X-HTTP-Method-Override: PUT- route хүлээж авах жинхэнэ verbX-Body-Encoding: base64- body encoding асаалттай үед байна; form body нь уншигдах HTML биш, base64-аар харагдана (энэ нь бас зориуд - доороос үз)
URL болон JSON хариу нь жинхэнэ PUT-тэй яг ижил тул дараагийн ямар ч хэсэг өөрчлөгдөхгүй.
Body encoding-г унтраах
Хост чинь body-inspection хийдэг WAF-гүй бөгөөд raw form body-г харах/шалгахыг хүсвэл:
- Site-wide:
.env-дRAPTOR_WAF_BODY_ENCODING=falseболго. ТэгвэлController::template()нь<meta name="waf-body-encoding" content="0">гаргаж,csrfFetch()encode хийхээ болино. (Server талын decode нь header-gated тул огт ажиллахгүй - аль ч тохиолдолд аюулгүй.) - Custom layout:
<meta name="waf-body-encoding">tag нь энэ флагийг browser-т дамжуулах цорын ганц суваг. Shippeddashboard.html-ийг ашиглахгүй бол түүнийг заавал оруул, эс бөгөөс=falseтохиргоо client дээр чимээгүй үл хэрэгсэгдэнэ. - Нэг удаагийн raw хүсэлт:
csrfFetch()-д per-call opt-out байхгүй. Нэг хүсэлтийг verb болон body-той нь хувиргалгүй илгээх бол энгийнfetch()-ийг ашигла - гэхдээ CSRF-тэй route-дX-CSRF-TOKENheader-ийг өөрөө нэм (getCsrfToken()). Энэ нь голдуу dashboard-аас гадуурх / external endpoint-д зориулагдсан; dashboard route-уудадcsrfFetch()-ийг илүүд үз.
Тэмдэглэл: method override (verb -> POST хувиргалт)-д унтраах switch байхгүй - үргэлж асаалттай ч override header байхгүй бол no-op тул хэзээ ч унтраах шаардлагагүй. Endpoint руу жинхэнэ PUT/DELETE verb-ээр хүрэхийн тулд хост тэр verb-ийг зөвшөөрдөг байх ёстой бөгөөд csrfFetch()-аас өөр client (жишээ: энгийн fetch()) ашиглах хэрэгтэй.
И-мэйл
RAPTOR_MAIL_FROM=noreply@codesaur.domain
#RAPTOR_MAIL_FROM_NAME="Raptor Notification"
#RAPTOR_MAIL_REPLY_TO=
# Transport: brevo (анхдагч), smtp, mail
#RAPTOR_MAIL_TRANSPORT=brevo
#RAPTOR_MAIL_BREVO_APIKEY=
# SMTP тохиргоо (transport=smtp үед)
#RAPTOR_SMTP_HOST=smtp.gmail.com
#RAPTOR_SMTP_PORT=465
#RAPTOR_SMTP_USERNAME=
#RAPTOR_SMTP_PASSWORD=
#RAPTOR_SMTP_SECURE=ssl
send()ньRAPTOR_MAIL_TRANSPORT-оос хамааран transport сонгоно (brevo/smtp/mail)
OpenAI
#RAPTOR_OPENAI_API_KEY=sk-your-api-key-here
- moedit editor-ийн AI товчинд ашиглагдана
Зургийн optimize
RAPTOR_CONTENT_IMG_MAX_WIDTH=1920
RAPTOR_CONTENT_IMG_QUALITY=90
- CMS-д зураг upload хийхэд GD extension ашиглан optimize хийнэ
Cloudflare Turnstile
#RAPTOR_TURNSTILE_SITE_KEY=
#RAPTOR_TURNSTILE_SECRET_KEY=
- Заавал биш: тохируулаагүй бол Turnstile widget харагдахгүй, сервер талын шалгалт алгасна
SpamProtectionTraitашиглан нийтийн формуудад CAPTCHA шалгалт хийнэ
Discord мэдэгдэл
#RAPTOR_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
- Заавал биш: хоосон эсвэл тохируулаагүй бол мэдэгдэл илгээхгүй
DiscordNotifierсервис системийн үйл явдлын мэдэгдэлд ашиглана
Серверийн тохиргоо
Анхаар: web серверийн document root нь заавал
public_html/байх ёстой, project root биш. Зөвхөнpublic_html/-ийг web-ээр үйлчлүүлэхээр зориулсан; бусад бүх зүйл (application/,protected/,database/,vendor/,.env,logs/, ...) түүний нэг шатнаас дээр байрладаг бөгөөд URL-аар хүрэшгүй байх ёстой. Docroot-ийг project root руу чиглүүлбэл эх код,.envнууц утгууд, upload хийсэн файл, session өгөгдөл бүгд ил гарна. Энэ ганц дүрэм нь server-аас үл хамаарах үндсэн хамгаалалт (Apache, Nginx адил) -.htaccess/ nginxdenyдүрмүүд нь зөвхөн яг энэ буруу тохиргооны үеийн нэмэлт fallback. Shared hosting дээр домэйний document root-ийг.../public_htmlболго; доорх жишээ тохиргоонууд аль хэдийн ингэж тохируулсан.
Apache болон Nginx серверийн жишээ тохиргоонууд docs/conf.example/ хавтаст байна:
| Файл | Тайлбар |
|---|---|
.env.example | Орчны тохиргооны лавлагаа |
.htaccess.example | Apache URL rewrite болон HTTPS redirect |
.nginx.conf.example | Nginx серверийн блок (HTTP, HTTPS, PHP-FPM) |
CI/CD
Framework нь 2 GitHub Actions workflow-тэй:
CI (.github/workflows/ci.yml)
Repo-д анхнаасаа орсон default workflow. Push болон pull request бүрт код чанарын шалгалт хийнэ:
composer validate --strict- composer.json шалгах- PHP syntax check - бүх
.phpфайлын синтакс - Merge conflict markers -
<<<<<<<,=======,>>>>>>>илрүүлэх - Debug statements -
var_dump,dd,print_rанхааруулга composer dump-autoload --strict-psr- autoload шалгах
Deploy (.github/workflows/deploy.yml)
Нэгдсэн deploy workflow, 3 job-той: FTP, SSH, болон Windows Server self-hosted runner. Job бүр зөвхөн шаардлагатай secrets/variables тохируулсан үед ажиллана. Тохируулсан бүх job-ууд зэрэг (parallel) ажиллана.
Доорх A / B / C нь энэ workflow-ийн job-ууд бөгөөд shared hosting, VPS, cloud VM, dedicated, Windows Server гээд бараг бүх орчныг хамарна. D нь workflow-оос гаднах, зөвхөн A/B/C-гийн аль нь ч сервер лүү хүрч чадахгүй онцгой орчны fallback.
Ажиллах дараалал:
Push to main -> CI workflow ажиллана -> Амжилттай бол -> Deploy workflow эхэлнэ
-> Амжилтгүй бол -> Deploy хийгдэхгүй
Deploy workflow нь workflow_run trigger ашиглан CI workflow-н дүнг хүлээнэ. CI амжилттай дуусвал (conclusion == 'success') deploy эхэлнэ. CI fail болвол deploy skipped болно - алдаатай код серверт очихгүй. Deploy-ийн secrets/variables тохируулаагүй бол (жишээ: developer clone) бүх job чимээгүй алгасагдана.
A) FTP Deploy
FTP хандалттай дурын серверт (shared hosting, VPS, dedicated). Settings -> Secrets and variables -> Actions -> Secrets хэсэгт дараах secret-үүдийг нэмнэ:
| Secret | Тайлбар | Жишээ |
|---|---|---|
FTP_HOST | Серверийн FTP хаяг | ftp.example.com |
FTP_USERNAME | FTP хэрэглэгчийн нэр | user@example.com |
FTP_PASSWORD | FTP нууц үг | |
FTP_SERVER_DIR | Серверийн зорьсон хавтас | / |
B) SSH Deploy
SSH хандалттай Linux серверт (VPS, cloud VM, dedicated). Settings -> Secrets and variables -> Actions -> Secrets хэсэгт дараах secret-үүдийг нэмнэ:
| Secret | Тайлбар | Жишээ |
|---|---|---|
SSH_HOST | Серверийн хаяг | example.com эсвэл 1.2.3.4 |
SSH_USERNAME | SSH хэрэглэгчийн нэр | deploy |
SSH_KEY | SSH private key (id_rsa агуулга бүтнээр) | |
SSH_DEPLOY_DIR | Серверийн зорьсон хавтас | /var/www/myproject |
SSH_PORT | (заавал биш) SSH порт, анхдагч: 22 | 22 |
C) Windows Self-hosted Runner Deploy
- Windows Server дээр self-hosted runner суулгах:
- Settings -> Actions -> Runners -> New self-hosted runner -> Windows
- Runner-г Windows service болгон бүртгэж, сервер restart хийхэд автомат асдаг болгоно
- Settings -> Secrets and variables -> Actions -> Variables хэсэгт дараах variable нэмнэ:
| Variable | Тайлбар | Жишээ |
|---|---|---|
DEPLOY_PATH | Серверийн project хавтас | C:\xampp\htdocs\myproject |
- PHP болон Composer серверийн system PATH-д байх ёстой.
D) cPanel Git Deploy (fallback - зөвхөн A/B/C-гийн аль нь ч боломжгүй үед)
Дээрх гурван зам бол стандарт бөгөөд cPanel хосттой байлаа ч гэсэн FTP (A) эсвэл SSH (B) хандалт нээлттэй л бол тэдгээрийг ашиглана - cPanel дээр байршсан гэдэг нь дангаараа энэ D замыг сонгох шалтгаан биш.
Харин GitHub Actions-ийн аль ч job сервер лүү хүрч чадахгүй онцгой орчин цөөн ч гэсэн байдаг: SSH/Terminal хаалттай, гаднаас FTP холбогдох боломжгүй cPanel shared hosting. Ийм орчны нэг бодит жишээ нь Монгол Улсын Үндэсний Дата Төвийн төрийн байгууллагуудын веб порталд зориулсан shared hosting юм. Зөвхөн ийм тохиолдолд cPanel-ийн өөрийн Git + cron дээр суурилсан scaffold-ийг ашиглана:
| Файл | Үүрэг |
|---|---|
docs/conf.example/.cpanel.yml.example | Repo root-д .cpanel.yml нэрээр хуулна - cPanel Git deploy task list |
docs/conf.example/auto-deploy.sh.example | deploy/auto-deploy.sh болгон хуулж cron-оор ажиллуулна |
Бүрэн заавар: docs/mn/CPANEL.md
Анхаарах: Deploy workflow нь CI (ci.yml) байхыг шаарддаг. CI workflow-г устгасан бол deploy trigger хийгдэхгүй.
Deploy хийгдэхгүй файлууд
.env- Серверт гараар үүсгэж тохируулна- Runtime хавтаснуудын агуулга -
cache/,logs/,protected/,public_html/public/,database/migrations/хавтаснууд guard файлуудтайгаа (.htaccessг.м.) deploy хийгдэж серверт үүснэ, харин доторх runtime агуулгыг нь (кэш, лог, upload файл, migration SQL) deploy хэзээ ч upload хийхгүй, дарахгүй, устгахгүй. Deploy зам бүр үүнийг өөр өөрийн механизмаар хангадаг тулdeploy.yml-ийн гурван шүүлтүүрийн жагсаалт зориудаар ялгаатай - "жигдлэхээсээ" өмнө тэндхийн comment-уудыг уншина уу. docs/,tests/- Зөвхөн хөгжүүлэлтийн зориулалттайvendor/- Workflow доторcomposer install/update --no-devажиллуулж build хийнэ
4. Архитектур
Хоёр давхаргат бүтэц
public_html/index.php (Entry point)
|
|-- /dashboard/* -> Dashboard\Application (Админ панель)
| |-- Middleware: ErrorHandler -> MethodOverride -> BodyEncoding -> Session -> JWT -> Container -> Localization -> Settings (CSRF нь per-route)
| |-- Routers: Login, Users, Organization, RBAC, Localization, Contents, Messages, Comments, Logs, Template, Shop, Development, Migration
| \-- Controllers -> Templates -> HTML Response
|
\-- /* -> Web\Application (Нийтийн вэб сайт)
|-- Middleware: ExceptionHandler -> Container -> Session -> Localization -> Settings
|-- Router: WebRouter (/, /page, /news, /contact, /products, /order, /search, /sitemap, /rss, /session/language, /session/contact-send, /session/order, /session/news/{id}/comment, /session/product/{id}/review, ...)
\-- Controllers -> Templates -> HTML Response
Request-ийн дамжих урсгал
Browser -> index.php -> .env -> ServerRequest
-> Application сонгох (URL path-аар)
-> Middleware chain (дарааллаар)
-> Router match
-> Controller::action()
-> Model (DB)
-> FileTemplate (codesaur/template) -> render()
-> HTML Response -> Browser
Директорийн бүтэц
Raptor нь MVC pattern-г баримталдаг ч модульчилсан (package-by-feature)
зохион байгуулалттай: модуль бүр өөрийн Controller, Model, темплейтүүдийг нэг хавтаст
хамт агуулдаг бөгөөд тэдгээрийг тусдаа давхаргын директорт (top-level Models/,
Controllers/, Views/) салгадаггүй. Модуль нэмэх, устгах нь нэг хавтсыг хуулах,
устгахтай адил энгийн.
application/ дотор хоёр апп бий: dashboard/ (удирдлагын самбарын application -
web-ийн хэрэглэдэг хуваалцсан суурь модулиуд болох Controller, middleware,
model-ууд ч энд байрлана), web/ (нийтийн вэбийн application). Апп түвшний
директорийн бүдүүвчийг үндсэн README.md-ийн "Directory Structure" хэсгээс харна
уу. Модуль бүрийн хавтасны байршил, ангиудыг 6-р бүлгийн тухайн модулийн хэсэгт
баримтжуулсан.
vendor/-оос бусад бүх директор хөгжүүлэгчийн мэдэлд.composer create-project-оор татсаны дарааapplication/,public_html/,database/,tests/,docs/, тохиргооны файлууд бүгд таны төслийн хэсэг болж, хэрэгцээ шаардлагадаа тааруулан бүрэн өөрчлөх, устгах, шинээр бичих боломжтой. Тусдаа "framework core" гэсэн давхарга байхгүй -application/доторdashboard/,web/гэсэн хоёр апп байх бөгөөд хоёулаа таны төслийн энгийн код. Үндсэн (default) codebase нь хөгжүүлэгчийн нийтлэг хэрэгцээг хангасан суурь тул өөрийн нарийвчилсан хэрэгцээ шаардлагаа кодод шууд шингээгээрэй. Зөвхөнvendor/*packages нь Composer-ээр удирдагдах dependency тул гар хүрэхгүй (composer update-ээр шинэчилнэ).
5. Middleware Pipeline
Middleware бол PSR-15 стандартын дагуу request/response-г боловсруулах давхаргууд юм. Бүртгэгдсэн дараалал чухал!
PDO холболт нь public_html/index.php entry point дотор
\Dashboard\DatabaseConnection::connect()-ээр нэг л удаа үүсэн request-ийн
pdo attribute хэлбэрээр Application руу дамждаг.
Dashboard Middleware
| # | Middleware | Зориулалт |
|---|---|---|
| 1 | ErrorHandler | Алдааг JSON/HTML хэлбэрээр хариулна |
| 2 | MethodOverrideMiddleware | X-HTTP-Method-Override-аас PUT/PATCH/DELETE-г сэргээнэ (WAF verb-block-ийн шийдэл). Session/routing-аас өмнө ажиллаж жинхэнэ verb-ийг бүх давхаргад харагдуулна |
| 3 | BodyEncodingMiddleware | X-Body-Encoding-той ирсэн form талбаруудыг base64-аас decode хийнэ (WAF body-inspection-ийн шийдэл) |
| 4 | SessionMiddleware | PHP session эхлүүлж удирдна |
| 5 | JWTAuthMiddleware | JWT шалгаж User объект үүсгэнэ |
| 6 | ContainerMiddleware | DI Container-г inject хийнэ |
| 7 | LocalizationMiddleware | Хэл, орчуулгыг тодорхойлно |
| 8 | SettingsMiddleware | Системийн тохиргоог inject хийнэ |
CsrfMiddlewareнь app-wide pipeline-д биш - router дээр mutating route бүрд per-route наагдана (6.20-г үз).
Web Middleware
| # | Middleware | Зориулалт |
|---|---|---|
| 1 | ExceptionHandler | Template ашиглан алдааны хуудас рендерлэнэ |
| 2 | ContainerMiddleware | DI Container |
| 3 | SessionMiddleware | Session (хэл хадгалах) |
| 4 | LocalizationMiddleware | Олон хэл |
| 5 | SettingsMiddleware | Тохиргоо (logo, title, footer) |
Database driver сонголт
Driver сонголт .env доторх RAPTOR_DB_DRIVER хувьсагчаар хийгдэнэ
(mysql эсвэл pgsql). \Dashboard\DatabaseConnection::connect() түүнийг
уншиж тохирох PDO instance үүсгэж буцаана:
# MySQL (default)
RAPTOR_DB_DRIVER=mysql
# PostgreSQL
RAPTOR_DB_DRIVER=pgsql
6. Модулиуд
6.1 Authentication (Нэвтрэлт)
Классууд: LoginRouter, LoginController, JWTAuthMiddleware, SessionMiddleware, User
- JWT + Session хосолсон authentication
- Login / Logout / Forgot password / Signup
- Нууц үг сэргээх токен нэг удаагийн хэрэглээтэй: амжилттай сольсны дараа
deactivateById()-ээр идэвхгүй болдог (устгагдахгүй) - админы хүсэлтүүдийн жагсаалтад used / expired / ready гэсэн 3 төлөвт харагдана - Байгууллага сонгох (олон байгууллагатай хэрэглэгч)
- JWT нь
$_SESSION['RAPTOR_JWT']дотор хадгалагдана Userобъект нь profile, organization, RBAC permissions агуулна
6.2 User (Хэрэглэгч)
Классууд: UsersRouter, UsersController, UsersModel
- Хэрэглэгчийн CRUD (Create, Read, Update, Deactivate/soft delete)
- Нууц үг bcrypt hash ашиглан хадгална
- Profile мэдээлэл: username, email, phone, first_name, last_name
- Avatar зураг upload
6.3 Organization (Байгууллага)
Классууд: OrganizationRouter, OrganizationController, OrganizationModel, OrganizationUserModel
- Байгууллагын CRUD
- Хэрэглэгч-байгууллагын холбоос удирдлага
- Нэг хэрэглэгч олон байгууллагад харьяалагдах боломжтой
- Topbar байгууллага солих dropdown: олон байгууллагатай хэрэглэгч topbar-ийн brand хэсгээс шууд солино (10-аас олон бол хайлтын шүүлтүүр гарна)
system_coderаль ч идэвхтэй байгууллага руу шилжинэ - хандах эрх рольоос гарна, гишүүнчлэлийн мөр үүсгэхгүй
6.4 RBAC (Эрхийн удирдлага)
Классууд: RBACRouter, RBACController, RBAC, Roles, Permissions, RolePermissions, UserRole
- Role (дүр) үүсгэх, удирдах
- Permission (эрх) үүсгэх, удирдах
- Role-Permission хамаарал
- User-Role оноох
- Controller дотроос эрх шалгах:
// Хэрэглэгч system байгууллага дээр "admin" дүртэй эсэх
$this->isUser('system_admin');
// Хэрэглэгч "news_edit" эрхтэй эсэх
$this->isUserCan('news_edit');
6.5 Files (Файл)
Классууд: FileRouter, FileController, FilesController, FilesModel, ProtectedFilesController
- Файл upload (native JS, FormData)
- Зураг optimize хийх (GD)
- Файлыг модуль/хүснэгтээр ангилах
- MIME type тодорхойлох
- Protected файл (зөвхөн нэвтэрсэн хэрэглэгчдэд, authorizeRead() hook)
6.6 Content - News (Мэдээ)
Классууд: NewsController, NewsModel
- Мэдээний CRUD (бүрмөсөн устгах, Хогийн савд нөөцлөх)
- Нүүр зураг upload
- Хавсралт файлууд
- Нийтлэх огноо удирдах
- Үзэлтийн тоо (read_count)
- moedit editor ашиглан контент засварлах
- Жишиг дата цэвэрлэх: seed дата устгаж ID=1-ээс эхлүүлэх (
reset()метод)
6.7 Content - Pages (Хуудас)
Классууд: PagesController, PagesModel
- Хуудасны CRUD (бүрмөсөн устгах, Хогийн савд нөөцлөх), хялбаршуулсан нэг формтой интерфэйс (type wizard хасагдсан)
- Parent-child бүтэц (олон түвшний навигацийн меню)
positionталбараар эрэмбэлэхtypeталбар:content(анхдагч),nav(эцэг/навигац хуудас - "Эцэг хуудас" switch ашиглан үүсгэнэ)- Эцэг хуудас (хүүхэдтэй хуудас) засах үед контент талбарууд (description, content, link, featured) нуугдана
is_featuredталбар: Footer-д онцлох холбоос (хуудас эцэг болоход автоматаар 0 болно)linkталбар: URL эсвэл локал зам, frontend + backend шалгалттай (isValidLink())read()хамгаалалт: нийтлэгдсэн эсэх, эцэг хуудас эсэх, link redirect- SEO slug үүсгэх (
generateSlug) - Файл хавсаргах
- Жишиг дата цэвэрлэх: seed дата устгаж ID=1-ээс эхлүүлэх (
reset()метод)
6.8 Content - References (Лавлагаа)
Классууд: ReferencesController, ReferencesModel
- Лавлагааны хүснэгтүүд (key-value хэлбэрийн)
- Олон хэлтэй (LocalizedModel)
- Динамик хүснэгтийн нэр
6.9 Content - Settings (Тохиргоо)
Классууд: SettingsController, SettingsModel, SettingsMiddleware
- Системийн ерөнхий тохиргоо (олон хэлтэй)
- Сайтын гарчиг, лого, тайлбар
- Favicon, Apple Touch Icon
- Холбоо барих мэдээлэл (утас, имэйл, хаяг)
- Footer мэдээлэл (copyright, социал холбоосууд)
SettingsMiddlewareнь тохиргоог request attributes-д inject хийнэ
6.10 Localization (Олон хэл)
Классууд: LocalizationRouter, LocalizationController, LanguageModel, TextModel, LocalizationMiddleware
- Хэл нэмэх / засах / устгах
- Орчуулгын текст удирдах (key -> value)
- Session дээр суурилсан хэл сонголт
- Template дотор
{{ 'key'|text }}ашиглах
6.11 Log (Лог)
Классууд: LogsRouter, LogsController, Logger
- PSR-3 стандартын лог систем
- Өгөгдлийн санд лог хадгалах
- Лог түвшин: emergency, alert, critical, error, warning, notice, info, debug
- Server request metadata автоматаар бүртгэх
- Хэрэглэгчийн мэдээлэл автоматаар бүртгэх
- Error log таб (system_coder хэрэглэгчид) - PHP error.log файлыг Хандалтын протокол хуудаснаас шууд харах
6.12 Mail (И-мэйл)
Классууд: Mailer
send()нь.env-ийнRAPTOR_MAIL_TRANSPORT-оос хамааран brevo/smtp/mail сонгоно- HTML форматтай мессеж, CC/BCC, хавсралт дэмжинэ
6.13 Template (Dashboard UI)
Классууд: TemplateRouter, TemplateController, DashboardTrait, MenuModel, FileController
- Dashboard layout рендерлэлт
DashboardTrait::dashboardTemplate()ашиглан - Sidebar цэс олон хэл, эрх, parent/child бүтэцтэй (
MenuModel) - Цэс удирдлагын CRUD (нэмэх, засах, идэвхгүй болгох)
- Файл upload, шалгалт, зураг optimize
FileControllerсуурь классаар - SweetAlert2, motable, moedit зэрэг JS компонентууд
- Responsive Bootstrap 5 дизайн
6.14 Shop (Дэлгүүр)
Классууд: ProductsController, OrdersController, ReviewsController, ShopRouter (products + orders + reviews нэгдсэн router), ProductsModel, ProductOrdersModel, ReviewsModel
- Бүтээгдэхүүний CRUD (бүрмөсөн устгах, Хогийн савд нөөцлөх), slug үүсгэх, хураангуй гаргах
- Бүтээгдэхүүний талбарууд: үнэ, хямдралын үнэ, SKU, barcode, хэмжээ, өнгө, нөөц, ангилал, онцлох, үнэлгээ зөвшөөрөх
- Захиалгын удирдлага (
products_ordersхүснэгт) - хэрэглэгчийн мэдээлэл, статус хянах - Бүтээгдэхүүний үнэлгээ, одтой үнэлгээ (1-5), бичмэл сэтгэгдэл
- Үнэлгээ products-view дотор харагдана (web болон dashboard)
- Web бүтээгдэхүүний хуудсанд media gallery (thumbnail strip + том preview)
- Жишиг дата анхны ачааллаар автоматаар үүсгэгдэнэ
- Шинэ захиалга, статус өөрчлөлт, үнэлгээний PSR-14 event суурьтай мэдэгдэл
- Шинэ захиалгын админ имэйл мэдэгдэл (toggle + хаяг тохируулах,
system_coderэрхтэй)
6.15 Reviews (Бүтээгдэхүүний үнэлгээ)
Классууд: ReviewsController, ReviewsModel (dashboard, ShopRouter-аар бүртгэгдсэн), ShopController::reviewSubmit() (web)
- Бүтээгдэхүүний хуудсан дээрх нийтийн үнэлгээний форм (
review=1үед) - Одтой үнэлгээ (1-5), бичмэл сэтгэгдэл
- Зочин хэрэглэгч нэр, имэйлээ бичнэ (имэйл заавал биш)
SpamProtectionTraitашиглан спам хамгаалалт (honeypot, HMAC, rate limiting, Turnstile)- Дундаж үнэлгээ, тоо бүтээгдэхүүний жагсаалтын карт дээр харагдана
- Dashboard: products-view дотор үнэлгээний жагсаалт, устгах боломжтой
- Dashboard: products-index толгой хэсгээс үнэлгээний жагсаалт руу очих линк
- Badge: шинэ үнэлгээ
info(усан цэнхэр) badge-ээр products sidebar дээр харагдана - Админ имэйл мэдэгдэл (toggle + хаяг тохируулах,
system_coderэрхтэй, анхдагч: идэвхгүй) - Web талаас
/session/product/{id}/review-ээр үнэлгээ илгээнэ
6.16 Event систем & Мэдэгдэл
Классууд: EventDispatcher, ListenerProvider, ContentEvent, UserEvent, OrderEvent, DevRequestEvent, DiscordListener
- PSR-14 Event Dispatcher систем - шууд Discord дуудлагыг орлосон
- Event классууд:
ContentEvent,UserEvent,OrderEvent,DevRequestEvent ListenerProviderнь listener-үүдийг бүртгэнэ (одоогоорDiscordListener)DiscordListenerнь бүх төрлийн event-д Discord webhook мэдэгдэл илгээнэ- Controller-ууд
$this->dispatch(new ContentEvent(...))helper-ээр event дамжуулна DiscordNotifierнь админы нэр, dashboard URL-г хадгална (ContainerMiddleware-д inject хийгдсэн)- Мэдэгдлийн төрлүүд: хэрэглэгч бүртгүүлсэн, хэрэглэгч зөвшөөрсөн, шинэ захиалга, захиалгын статус өөрчлөлт, контентийн үйлдлүүд (нэмэх, засах, устгах, нийтлэх)
- Өнгөт Discord embed мессеж
RAPTOR_DISCORD_WEBHOOK_URLорчны хувьсагчаар тохируулна- Webhook URL тохируулаагүй эсвэл listener байхгүй бол чимээгүй алгасна
6.17 Development (Хөгжүүлэлтийн хэрэгсэл)
Классууд: DevelopmentRouter, DevRequestController, DevRequestModel, DevResponseModel
- Хөгжүүлэлтийн хүсэлт хянах систем (хүсэлт илгээх, хариулах, түүх харах)
application/dashboard/development/хавтаст байрлана (Dashboard\Developmentnamespace)- Нэвтэрсэн бүх хэрэглэгч хүсэлт үүсгэж, зөвхөн өөрийн үүсгэсэн болон өөрт хуваарилагдсан хүсэлтийг харах, хариулах, устгах боломжтой
system_developmentэрхтэй хэрэглэгч бүх хүсэлтийг харах, хариулах, устгах бүрэн эрхтэй
6.18 Site Service (Web)
Классууд: SeoController
- Хуудас, мэдээ, бүтээгдэхүүн дундаас бүтэн текст хайлт
- Хүнд ээлтэй sitemap хуудас, шатлалтай хуудасны бүтэцтэй
- XML sitemap (
/sitemap.xml) хайлтын системүүдэд - RSS 2.0 feed (
/rss) сүүлийн мэдээ, бүтээгдэхүүнтэй robots.txt- Хайлтын системийн бот удирдлагаpublic_html/-д агуулагдана
robots.txt
public_html/robots.txt файл нь хайлтын системийн ботуудыг удирдана:
- Зөвшөөрөгдсөн: Googlebot, Bingbot, YandexBot, Baiduspider
- Хаагдсан: SEO scraper-ууд (MJ12bot, SemrushBot, AhrefsBot, DotBot, Bytespider, PetalBot)
- AI ботууд: Анхдагчаар зөвшөөрөгдсөн (GPTBot, ClaudeBot гэх мэт). Хаахыг хүсвэл тухайн мөрийг uncomment хийнэ
- Dashboard:
/dashboard/бүх ботоос хаагдсан - Sitemap:
Sitemap:мөрийг өөрийн домэйн хаягаар солино
Sitemap: https://example.com/sitemap.xml
6.19 Спам хамгаалалт
Классууд: SpamProtectionTrait
- Honeypot нууц талбарын илрүүлэлт
- HMAC токен цаг хугацааны хамт шалгах
- Үйлдэл тус бүрийн хурд хязгаарлалт (login 2s, signup 5s, forgot 10s)
- Формын хугацаа дуусах шалгалт (1 цагийн дотор)
- Бөглөх хурдны доод хязгаар (1 секунд)
- Cloudflare Turnstile CAPTCHA дэмжлэг (
.envдоторRAPTOR_TURNSTILE_SECRET_KEYтохируулсан үед идэвхжинэ) - Линк спам шүүлтүүр (хэт олон URL агуулсан текстийг хаана)
- Нэвтрэх, бүртгүүлэх, нууц үг сэргээх, холбоо барих, сэтгэгдэл, үнэлгээ, захиалгын формуудад ашиглагдана
6.20 CSRF хамгаалалт
Классууд: CsrfMiddleware
- Per-route middleware (app-wide биш). Router дээр mutating route бүрд
->middleware([CsrfMiddleware::class])-аар наагдана (use Dashboard\CsrfMiddleware;) - Middleware нь зөвхөн шалгана:
$_SESSION['CSRF_TOKEN']-гX-CSRF-TOKENheader-тэй тулгаж, зөрвөл 403 буцаана - GET/HEAD/OPTIONS хүсэлтүүд шалгалтгүйгээр дамжина (
GET_POST/GET_PUTcompound route-ийн GET талыг хамгаална) - Token нь login үед үүсэж
$_SESSION['CSRF_TOKEN']дотор хадгалагдана. Хуучин session-д fallback болгожController::template()(нэвтэрсэн хэрэглэгчид token байхгүй + session writable бол) үүсгэнэ - Token нь
dashboard.htmlдоторх<meta name="csrf-token">tag-аар frontend-д хүрнэ (Controller::template()session-аас уншина) - Клиент тал (JS) нь
csrfFetch()wrapper ашигланX-CSRF-TOKENheader-аар дамжуулна - Шинэ модуль нэмэхэд: mutating route бүрд
->middleware([CsrfMiddleware::class])нэмнэ (автомат биш); зөвхөн login routes exempt. Клиент талд бүх state-changing хүсэлтэдfetch()бишcsrfFetch()ашиглана
6.21 Database Migration (Өгөгдлийн сангийн шилжүүлэг)
Классууд: MigrationRunner, MigrationController, MigrationRouter, MigrationSecurityScanner
- SQL файл дээр суурилсан, зөвхөн урагшлах (forward-only) migration систем
- Файлын систем дээр state хадгалагдана (tracking хүснэгт байхгүй)
database/migrations/нь git-ignored - per-environment upload- Per-user folder:
{userId}-{username}/дотор pending файл,{userId}-{username}/ran/дотор амжилттай ажилласан файл - Coder dashboard-аас
.sqlupload хийнэ (max = min(10 MB, php.ini post_max_size, upload_max_filesize)), apply дарвал ажиллаж дараагийн file-ааran/руу зөөнө - Apply үед
MigrationSecurityScannerнь sensitive хүснэгт (users,rbac_*,organizations*,localization_language,raptor_menu) болон DCL (GRANT/REVOKE/CREATE-DROP-ALTER USER)-д хандсан pattern илрүүлж soft warning гаргана - coderCONFIRMбичиж баталгаажуулна - Advisory lock (
GET_LOCK/pg_try_advisory_lock) зэрэгцээ apply-аас хамгаална dashboard_log-д бүх upload/apply/delete үйлдлийг SHA-256 hash, statement тоо, warning тоотойгоор бичнэ- Зөвхөн
system_coderrole-той хэрэглэгчид хандах боломжтой - Эцэг
database/.htaccess(deny from all) хамгаалалт SQL файлуудад шууд хандахыг хаана
6.22 Messages (Холбоо барих мессеж)
Классууд: MessagesController, MessagesModel (dashboard), ContactController (web)
- Нийтийн холбоо барих форм (
/contact), спам хамгаалалттай - Холбоо барих формын мессежүүдийг өгөгдлийн санд хадгална
- Dashboard интерфэйс: мессежүүдийг харах, удирдах
- Мессежийн дэлгэрэнгүйг modal цонхонд харуулна
- Бүрмөсөн устгах, Хогийн савд нөөцлөх (soft delete/идэвхгүй болгохыг орлосон)
- Шинэ мессежийн event суурьтай мэдэгдэл (PSR-14 listener-ээр Discord)
- Админ имэйл мэдэгдэл (toggle + хаяг тохируулах,
system_coderэрхтэй) - Web талын
ContactControllerнь формыг харуулах болон/session/contact-send-ээр илгээхийг удирдана
6.23 Comments (Мэдээний сэтгэгдэл)
Классууд: CommentsController, CommentsModel (dashboard), NewsController::commentSubmit() (web)
- Мэдээний хуудсан дээрх нийтийн сэтгэгдлийн форм
- 1 түвшний хариулт (parent_id ашиглан дээд түвшний сэтгэгдэлд хариулах)
- Зочин хэрэглэгч нэр, имэйлээ бичнэ
- Нэвтэрсэн хэрэглэгчийн нэр/имэйл профайлаас автоматаар бөглөгдөнө
SpamProtectionTraitашиглан спам хамгаалалт (honeypot, HMAC, rate limiting, Turnstile)- Dashboard: news-view дотор сэтгэгдлийн жагсаалт, хариулах, устгах боломжтой
- Dashboard: news-index толгой хэсгээс сэтгэгдлийн жагсаалт руу очих линк
- Badge: шинэ сэтгэгдэл
info(усан цэнхэр) badge-ээр news sidebar дээр харагдана - Бүрмөсөн устгах, Хогийн савд нөөцлөх (soft delete/идэвхгүй болгохыг орлосон)
- Админ имэйл мэдэгдэл (toggle + хаяг тохируулах,
system_coderэрхтэй, анхдагч: идэвхгүй) - Web талаас
/session/news/{id}/comment-ээр сэтгэгдэл илгээнэ
6.24 Badge систем (Sidebar Badge)
Классууд: Dashboard\Badge\BadgeController, Dashboard\Badge\BadgeRouter, Dashboard\Badge\AdminBadgeSeenModel (application/dashboard/badge/)
- Sidebar цэсний зүйлс дээр модуль тус бүрийн уншаагүй үйлдлийн тоог өнгөт badge-ээр харуулна
*_logхүснэгтүүдээс уншина - тусдаа event хүснэгт шаардахгүй- Multi-tenant:
orgScopedModules()жагсаасан модулийн badge-ийг харж буй админы байгууллагаар хязгаарлана - бичлэгийн байгууллагаар (log context-ийнrecord_organization_id) шүүж, байхгүй бол үйлдэгчийн байгууллага руу fallback хийнэ;system_coderболон системийн байгууллагаар нэвтэрсэн админ (isSystemWideViewer()) бүх байгууллагыг харна - Badge өнгө: ногоон (create), цэнхэр (update), улаан (delete)
- Модуль бүрт 3 хүртэл badge, зүүнээс баруун тийш ногоон-цэнхэр-улаан дарааллаар
- Админы эрхээр шүүж (PERMISSION_MAP), өөрийн үйлдлийг хасна
- Шинэ хэрэглэгчид 30 хоногийн lookback
- Manual, migration-д файлын тоон дээр суурилсан badge (лог бус)
- JS:
initSidebarBadges()dashboard.jsдотор хуудас ачаалахад badge татаж рендерлэнэ
6.25 Dashboard Home
Классууд: HomeRouter, SearchController, WebLogStatsController, WebLogStats
- Dashboard нүүр хуудас системийн ерөнхий мэдээлэлтэй
- Topbar түргэн icon-ууд (хайлт | хэл | загвар): хайлтын modal (Ctrl+K) - мэдээ, хуудас, бүтээгдэхүүн, захиалга, хэрэглэгч, байгууллага, хөгжүүлэлтийн хүсэлт, мессеж, сэтгэгдэл, үнэлгээнээс (RBAC шүүлтүүртэй - эх сурвалж бүр модулийнхаа index permission эсвэл мөрийн түвшний шүүлтээр хамгаалагдана); хэл солих dropdown (session-д хадгалагдана); цайвар/бараан загварын dropdown (reload-гүй шууд)
- Вэб зочилсон статистик: график, шилдэг хуудас/мэдээ/бүтээгдэхүүн, IP хаяг
- Системийн
*_logхүснэгтүүдийн статистик (өнөөдөр/долоо хоног/нийт) web_log_cacheхүснэгт гүйцэтгэлийг хурдасгахад ашиглана
6.26 Dashboard Manual (Гарын авлага)
Классууд: ManualRouter, ManualController
- Бүх гарын авлагын HTML файлуудыг модулиар бүлэглэн жагсаана
- Тодорхой гарын авлагыг харуулна, хэлний fallback англи руу
- Файлууд:
application/dashboard/manual/хавтаст{name}-manual-{lang}.htmlформаттай
6.27 AI Helper (moedit)
Классууд: AIHelper
- moedit WYSIWYG editor-ийн OpenAI API интеграци
- HTML горим: контент сайжруулалт (Bootstrap 5 компонент) - модель
RAPTOR_OPENAI_MODEL(.env, defaultgpt-5-mini) - Vision горим: зургаас текст таних (OCR) - модель
RAPTOR_OPENAI_VISION_MODEL(.env, defaultgpt-5.1) - Endpoint:
POST /dashboard/content/moedit/ai .env-дRAPTOR_OPENAI_API_KEYшаардлагатай
6.28 Seed болон анхдагч дата
Классууд: PermissionsSeed, RolePermissionSeed, MenuSeed, TextInitial, ReferenceInitial, NewsSamples, PagesSamples, ProductsSamples
- Шинэ суулгалтад өгөгдлийн сангийг Model
__initial()методоор автоматаар дүүргэнэ - Эрхүүд:
system_угтвартай 18+ системийн эрх - Role-ууд: coder, admin, manager, editor, viewer - эрхийн оноолттой
- Цэс: 4 хэсэгтэй dashboard sidebar (Contents, Shop, System, Coder - сүүлийнх нь зөвхөн system_coder-д), олон хэлтэй
- Орчуулга: 100+ системийн UI keyword MN/EN хэлээр
- Лавлагаа загварууд: 11+ и-мэйл загвар (нууц үг сэргээх, мэдэгдлүүд, захиалга) + Нөхцөл/Нууцлал
- Жишиг дата: демо мэдээ (6), хуудас (14+), бүтээгдэхүүн (4) - dashboard-ийн "Reset" товчоор устгах боломжтой
6.29 Trash (Хогийн сав)
Классууд: TrashRouter, TrashController, TrashModel
- Бүрмөсөн устгахаас өмнө устгасан бичлэгүүдийг JSON хэлбэрээр хадгална
- Контент модулиудын хуучин soft delete (
is_active=0) загварыг орлосон - 15 model-оос
is_activeбагана хасагдсан;deactivateById()ньdeleteById()болж солигдсон: News, Pages, Products, Orders, Reviews, Comments, Messages, Files, References, Settings, DevRequests, DevResponses, Menus, Texts, Languages - Users болон Organizations нь soft delete хэвээр хадгалагдсан (
is_activeбагана хэвээр) - Dashboard интерфэйсээс устгасан бичлэгүүдийг харах, шалгах, удирдах
- Сэргээх (Restore): бичлэгийг үндсэн хүснэгт рүү буцаах. Эхлээд анхны ID-аар оролдох (FK холбоосыг хадгалахын тулд), амжилтгүй бол auto-increment ID; UNIQUE талбар (slug, keyword, code, sku) давхцалтай бол админд ойлгомжтой алдаа буцаах; LocalizedModel-ийн
_contentмөрүүд хамт сэргээгдэнэ - Хоёр давхар аудит лог: сэргээх үйлдэл
trash_log(бүрэн audit) ба trash бичлэгийнlog_tableбаганаас уншсан channel-д аль алинд бичигдэнэ - энэ нь Logger Protocol-оор сэргээгдсэн record-ын view/update хуудсан дээр харагдана. Controller-уудTrashModel::store()-руу log channel-ийн нэрийг шууд дамжуулна (жишээ:ReviewsController->'products',ReferencesController->'content') - Хогийн савыг бүрэн хоослох боломжтой
- Зөвхөн
system_coderдүртэй админ хандана
7. Template систем
Raptor нь codesaur/template package-ийн FileTemplate классыг ашиглана - Twig-ийн синтаксыг дуурайсан хөнгөн engine (бодитоор twig/twig library биш).
Суурь хувьсагчид
Controller дотроос template() дуудахад доорх хувьсагчид автоматаар нэмэгднэ:
| Хувьсагч | Тайлбар |
|---|---|
user | Нэвтэрсэн хэрэглэгчийн User объект (null байж болно) |
index | Script path (subdirectory дэмжлэг) |
localization | Хэл, орчуулгын мэдээлэл |
request | Одоогийн URL path |
Custom filter-ууд (Controller-ээс бүртгэгдсэн)
| Filter | Хэрэглээ | Тайлбар |
|---|---|---|
text | {{ 'key'|text }} | Орчуулгын текст авах |
link | {{ 'news'|link({'id': 5}) }} | 5-р мэдээний URL үүсгэх |
basename | {{ path|basename }} | Файлын нэр гаргах (Web templates) |
Twig-ийн дэмжигдэхгүй боломжууд
codesaur/template дотор дараах Twig pattern ажилладаггүй; жишигийн орлуулга ашиглана:
| Twig (дэмжигдэхгүй) | Орлуулга |
|---|---|
{% for i in 1..5 %} | {% for i in range(1, 5) %} |
**, // | байхгүй (*, / ашиглана) |
is divisible by, is same as | байхгүй |
loop.revindex, loop.parent | байхгүй |
{% verbatim %}, {% include %}, {% extends %} | байхгүй |
|date(format='Y-m-d') | |date('Y-m-d') (зөвхөн positional) |
codesaur/template4.1.0-аас хойшin/not in(membership),ends with,matches(regex),is even/is oddдэмжигдэнэ - жишээ:{% if type in ['image', 'video'] %}.
Жишээ
<!-- Орчуулга -->
<h1>{{ 'welcome'|text }}</h1>
<!-- Route link -->
<a href="{{ 'page'|link({'id': page.id}) }}">{{ page.title }}</a>
<!-- Хэрэглэгч шалгах (object method дуудлага дэмжигдэнэ) -->
{% if user is not null and user.can('system_content_index') %}
<p>Сайн байна уу, {{ user.profile.first_name }}!</p>
{% endif %}
<!-- Хэл солих -->
{% for code, language in localization.language %}
<a href="{{ 'language'|link({'code': code}) }}">{{ language.title }}</a>
{% endfor %}
8. Routing
Raptor нь codesaur/http-application package-ийн Router классыг ашиглана.
Route тодорхойлох
class MyRouter extends \codesaur\Router\Router
{
public function __construct()
{
// GET маршрут
$this->GET('/path', [Controller::class, 'method'])->name('route-name');
// POST маршрут
$this->POST('/path', [Controller::class, 'method'])->name('route-name');
// PUT маршрут (бүтэн ресурс шинэчлэх)
$this->PUT('/path/{uint:id}', [Controller::class, 'method'])->name('route-name');
// PATCH маршрут (хэсэгчлэн шинэчлэх - нэг талбар, статус toggle)
$this->PATCH('/path/{uint:id}/status', [Controller::class, 'method'])->name('route-name');
// DELETE маршрут
$this->DELETE('/path', [Controller::class, 'method'])->name('route-name');
// GET + POST (форм)
$this->GET_POST('/path', [Controller::class, 'method'])->name('route-name');
// GET + PUT (засах форм)
$this->GET_PUT('/path/{uint:id}', [Controller::class, 'method'])->name('route-name');
}
}
Динамик параметрууд
| Pattern | Тайлбар | Жишээ |
|---|---|---|
{name} | String параметр | /page/{slug} |
{uint:id} | Unsigned integer | /page/{uint:id} |
{code} | String (хэлний код) | /language/{code} |
Router бүртгэх
Application класс дотроос:
$this->use(new MyRouter());
Route нэрийн оновчлол
->name('route-name') зөвхөн route нэр бодитоор ашиглагдаж байгаа үед тавина:
- Template дотор
{{ 'route-name'|link }}хэлбэрээр - PHP controller дотор
$this->redirectTo('route-name')хэлбэрээр
Нэрээр дуудагддаггүй route-д ->name() шаардлагагүй бөгөөд илүүдэл ачааллыг бууруулна.
9. Controller
Суурь Controller (Dashboard\Controller)
Бүх Controller-ууд Dashboard\Controller ангиас удамшина. Доорх боломжуудыг нийтлэг авна:
| Метод | Тайлбар |
|---|---|
$this->pdo | PDO холболт |
getUser() | Нэвтэрсэн хэрэглэгч (User|null) |
getUserId() | Хэрэглэгчийн ID |
isUserAuthorized() | Нэвтэрсэн эсэх |
isUser($role) | RBAC дүр шалгах |
isUserCan($permission) | RBAC эрх шалгах |
getLanguageCode() | Идэвхтэй хэлний код |
getLanguages() | Бүх хэлний жагсаалт |
text($key) | Орчуулгын текст |
template($file, $vars) | Template объект |
respondJSON($data, $code) | JSON хариулт |
redirectTo($route, $params) | Redirect хийх |
log($table, $level, $msg) | Лог бичих |
dispatch($event) | PSR-14 event дамжуулах |
generateRouteLink($name, $params) | URL үүсгэх |
getContainer() | DI Container |
getService($id) | Service авах |
Жишээ: Шинэ Controller бичих
namespace Dashboard\Products;
class ProductsController extends \Dashboard\Controller
{
public function index()
{
// Эрх шалгах
if (!$this->isUserCan('product_read')) {
throw new \Error('Эрх хүрэлцэхгүй', 403);
}
// Model ашиглах
$model = new ProductsModel($this->pdo);
$products = $model->getRows();
// Template рендерлэх
$twig = $this->template(__DIR__ . '/index.html', [
'products' => $products
]);
$twig->render();
}
public function store()
{
$body = $this->getRequest()->getParsedBody();
$model = new ProductsModel($this->pdo);
$id = $model->insert($body);
// Лог бичих - стандарт `record_id` түлхүүр ашиглах
// (бичлэгийн харах/засах хуудсан дээрх Logger Protocol-д харагдана).
$this->log('products', \Psr\Log\LogLevel::INFO, 'Бүтээгдэхүүн нэмлээ', [
'action' => 'create',
'record_id' => $id
]);
// JSON хариулт
$this->respondJSON(['status' => 'success', 'id' => $id]);
}
}
10. Model
Raptor нь codesaur/dataobject package-ийн Model классуудыг ашиглана.
Model (нэг хэлтэй)
use codesaur\DataObject\Column;
use codesaur\DataObject\Model;
class ProductsModel extends Model
{
public function __construct(\PDO $pdo)
{
$this->setInstance($pdo);
$this->setColumns([
(new Column('id', 'bigint'))->primary(),
new Column('name', 'varchar', 255),
new Column('price', 'decimal', '10,2'),
(new Column('is_active', 'tinyint'))->default(1),
new Column('created_at', 'datetime'),
]);
$this->setTable('products');
}
}
LocalizedModel (олон хэлтэй)
use codesaur\DataObject\Column;
use codesaur\DataObject\LocalizedModel;
class CategoriesModel extends LocalizedModel
{
public function __construct(\PDO $pdo)
{
$this->setInstance($pdo);
// Үндсэн хүснэгт
$this->setColumns([
(new Column('id', 'bigint'))->primary(),
(new Column('is_active', 'tinyint'))->default(1),
]);
// Хэл тус бүрийн контент
$this->setContentColumns([
new Column('title', 'varchar', 255),
new Column('description', 'text'),
]);
$this->setTable('categories');
}
}
Гол методууд
| Метод | Тайлбар |
|---|---|
insert($record) | Бичлэг нэмэх |
updateById($id, $record) | ID-р шинэчлэх |
deleteById($id) | ID-р бүрмөсөн устгах (контент модулиудад) |
deactivateById($id, $record) | ID-р идэвхгүй болгох (Users/Organizations-ийн soft delete, мөн Forgot токеныг ашиглагдсаны дараа идэвхгүй болгоход) |
getRowWhere($with_values) | WHERE key=value хэлбэрийн нөхцөлөөр нэг мөр авах |
getRow($condition) | SELECT нөхцөлөөр нэг мөр авах |
getRows($condition) | SELECT нөхцөлөөр олон мөр авах |
getName() | Хүснэгтийн нэр авах |
LocalizedModel өгөгдлийн бүтэц
LocalizedModel::getRows() буцаах бүтэц:
[
1 => [
'id' => 1,
'is_active' => 1,
'localized' => [
'mn' => ['title' => 'Монгол гарчиг', 'description' => '...'],
'en' => ['title' => 'English title', 'description' => '...'],
]
],
// ...
]
11. Тест
Raptor нь PHPUnit 11 суурьтай unit болон integration тестүүдтэй.
Шаардлага
composer install # phpunit dev dependency суулгах
Тест ажиллуулах
# Бүх тест
composer test
# Зөвхөн unit тест
composer test:unit
# Зөвхөн integration тест
composer test:integration
Тохиргоо
.env.testing файл нь тест орчны тохиргоог агуулна. Integration тест нь тусдаа test database ашиглана (жишээ: raptor12_test).
RAPTOR_DB_NAME=raptor12_test
Тестийн бүтэц
tests/
|-- bootstrap.php # Тест орчин тохируулах
|-- Support/
| |-- RaptorTestCase.php # Unit тестийн суурь анги
| \-- IntegrationTestCase.php # Integration тестийн суурь анги
|-- Unit/
| |-- Authentication/
| | \-- UserTest.php # User::is(), User::can() тест
| |-- Controller/
| | \-- ControllerTextTest.php # Controller::text() тест
| \-- Migration/
| \-- MigrationSecurityScannerTest.php # Sensitive SQL pattern шалгалт
\-- Integration/
|-- Model/
| |-- UsersModelTest.php # Хэрэглэгчийн CRUD тест
| |-- OrganizationModelTest.php # Байгууллагын тест
| \-- SignupModelTest.php # Бүртгэлийн тест
|-- RBAC/
| \-- RolesPermissionsTest.php # RBAC seed шалгалт
|-- Authentication/
| \-- JWTAuthTest.php # JWT encode/decode тест
\-- Migration/
\-- MigrationRunnerIntegrationTest.php # File-based migration runner тест
Тестийн онцлогууд
- Transaction isolation - Integration тест бүр transaction дотор ажиллаж, дуусахад rollback хийнэ. Тест дата бодит database-д нөлөөлөхгүй
- RaptorTestCase - Mock request, mock user үүсгэх helper-ууд (
createAdmin(),createCoder(),createGuest()) - IntegrationTestCase - Static PDO холболт (тест анги дотор дахин холбогдохгүй), auto database create
Шинэ тест бичих жишээ
namespace Tests\Unit;
use Tests\Support\RaptorTestCase;
class MyTest extends RaptorTestCase
{
public function test_example(): void
{
$user = $this->createAdmin();
$this->assertTrue($user->can('system_user_index'));
}
}
12. Хэрэглээний жишээ
Шинэ Router нэмэх
- Router класс үүсгэх:
// application/dashboard/mymodule/MyModuleRouter.php
namespace Dashboard\MyModule;
class MyModuleRouter extends \codesaur\Router\Router
{
public function __construct()
{
$this->GET('/dashboard/mymodule', [MyModuleController::class, 'index'])->name('mymodule');
$this->GET_POST('/dashboard/mymodule/insert', [MyModuleController::class, 'insert'])->name('mymodule-insert');
}
}
composer.jsonдотор namespace бүртгэх:
{
"autoload": {
"psr-4": {
"Dashboard\\MyModule\\": "application/dashboard/mymodule/"
}
}
}
Дараа нь autoloader-г шинэчлэх:
composer dump-autoload
Dashboard\Application-ийн constructor дотор бусад$this->use(...)router бүртгэлүүдийн хажууд Router-аа бүртгэнэ:
// application/dashboard/Application.php (__construct дотор)
$this->use(new MyModule\MyModuleRouter()); // Шинэ router
Web хуудас нэмэх
// application/web/WebRouter.php
$this->GET('/products', [HomeController::class, 'products'])->name('products');
// application/web/HomeController.php
public function products()
{
$model = new ProductsModel($this->pdo);
$products = $model->getRows(['WHERE' => "published=1 AND code='$code'"]);
$this->webTemplate(__DIR__ . '/products.html', ['products' => $products])->render();
}
Database сонгох
Driver-г .env доторх RAPTOR_DB_DRIVER хувьсагчаар солино:
# MySQL (default)
RAPTOR_DB_DRIVER=mysql
# PostgreSQL руу шилжих
RAPTOR_DB_DRIVER=pgsql
\Dashboard\DatabaseConnection::connect() энэ утгыг уншиж тохирох PDO үүсгэнэ.
Дараагийн алхмууд
- API тайлбар - Бүх класс, методуудын дэлгэрэнгүй API reference
- Хэлэлцүүлэг - Асуулт асуух, санал хуваалцах, тусламж авах
- codesaur ecosystem - Бусад packages