# ICOM Framework 0.10 — ຄູ່ມືນັກພັດທະນາ Generated from docs/modular-pages.php , docs/operations-pages.php , docs/feature-pages.php and docs/production-pages.php. Run php bin/docs.php after editing chapters. ## ສ້າງ module ທຳອິດ. ຈາກ source code ໄປຫາ API ທີ່ໃຊ້ງານໄດ້ — ພ້ອມຄຳສັ່ງ ແລະຜົນທີ່ຄວນໄດ້. ### 1. ກຽມ project ດາວໂຫຼດ source ຈາກ Installation ແລະແຕກ ZIP. ໃຊ້ PHP 8.4.1+ ໃນສາຍ stable 8.4/8.5 ທີ່ຍັງມີການບຳລຸງຮັກສາ. ຄຳສັ່ງຂ້າງລຸ່ມແມ່ນສຳລັບ project ໃໝ່ໃນເຄື່ອງພັດທະນາ; project ເກົ່າຕ້ອງຮັກສາ APP_KEY ເດີມ. ```text cd icom-framework php bin/compatibility.php --production composer install cp .env.example .env php bin/icom key:generate php bin/icom migrate ``` ### 2. ສ້າງ Catalog ຄຳສັ່ງນີ້ສ້າງ 5 ໄຟລ໌: provider, contract, application service, HTTP controller ແລະ README. ມັນປະຕິເສດຊື່ຫຼືປາຍທາງທີ່ບໍ່ຖືກຕ້ອງ ແລະບໍ່ຂຽນທັບ module ທີ່ມີແລ້ວ. ```text php bin/icom make:module Catalog ``` ### 3. ລົງທະບຽນໃຫ້ຊັດເຈນ ແກ້ config/modules.php ໃຫ້ return ລາຍການດັ່ງຕົວຢ່າງ. ຖ້າມີ module ອື່ນແລ້ວ ໃຫ້ເພີ່ມ Definition ໃສ່ລາຍການເດີມ. ການສ້າງໄຟລ໌ບໍ່ໄດ້ເປີດ route ອັດຕະໂນມັດ. ```text group('/api/v1', static function ($app): void { $app->get('/reports', ReportsController::class)->name('index'); }, [\Icom\Middleware\Authenticate::class], 'reports.'); // Path: /api/v1/reports Name: reports.index ``` ### ກວດຂອບເຂດກ່ອນ merge architecture:check ໃຊ້ PHP-Parser ອ່ານ AST ຂອງ app/Modules; ບໍ່ execute ໄຟລ໌ທີ່ກວດ. ການອ້າງອີງຂ້າມ module ຕ້ອງມີ direct dependency ແລະເປັນ class/interface ໃນ Contracts. ຮອງຮັບ aliases, group imports ແລະ class-name strings ທີ່ເຫັນໄດ້ໂດຍກົງ. ໄຟລ໌ namespace ຜິດ, module ທີ່ບໍ່ລົງທະບຽນ, PHP ທີ່ parse ບໍ່ໄດ້ ຫຼື symlink ຈະຖືກລາຍງານ. ```text php bin/icom architecture:check # Expected: violations is empty and ok is true. # private-module-reference means a consumer used another module's internals. ``` ### ຂອບເຂດຂອງການກວດ ນີ້ແມ່ນ convention check ສຳລັບທີມ, ບໍ່ແມ່ນ security sandbox. Dynamic class names, reflection, eval, aliases ທີ່ສ້າງຕອນ runtime, SQL ທີ່ອ້າງຕາຕະລາງຂ້າມ module ແລະ external side effects ຕ້ອງມີ code review/tests ເພີ່ມ. config/modules.php ແມ່ນ trusted PHP configuration. ຖ້າ group callback ໂຍນ exception, prefix/middleware context ຈະກັບຄືນ ແຕ່ routes ທີ່ເພີ່ມແລ້ວບໍ່ຖືກ rollback; ໃຫ້ແກ້ bootstrap ແລະສ້າງ Application ໃໝ່. ## ອ່ານຂໍ້ມູນໃຫຍ່ເປັນໜ້ານ້ອຍ. ໃຊ້ indexed ordering key ແລະຂອບເຂດຈຳນວນແຖວ ເພື່ອຫຼີກການອ່ານທັງຕາຕະລາງເຂົ້າ memory. ### API ພື້ນຖານ cursorPaginate ອ່ານສູງສຸດ perPage + 1 ແຖວ ເພື່ອຮູ້ວ່າມີໜ້າຕໍ່ໄປຫຼືບໍ່. perPage ຕ້ອງຢູ່ 1–500. ທຸກ where condition ຂອງ query ເດີມຍັງຄົງຢູ່; cursor input ຖືກ bind ເປັນ SQL parameter. ```text $page = $db->table('products') ->where('tenant_id', $authorizedTenant) ->cursorPaginate('id', perPage: 50, after: $after, columns: ['id', 'name']); return \Icom\Http\Response::json($page); // {data: [...], per_page: 50, has_more: true, next_cursor: "p050"} ``` ### Key ທີ່ຖືກຕ້ອງ ໃຊ້ key ທີ່ unique ໃນຂອບເຂດ query, ບໍ່ເປັນ NULL/empty ແລະບໍ່ປ່ຽນຄ່າລະຫວ່າງການແບ່ງໜ້າ. ຕົວຢ່າງ PRIMARY KEY(tenant_id,id) ເໝາະກັບ where tenant_id = ?. ຄ່າ key ຕ້ອງເປັນ integer ຫຼື string ສູງສຸດ 512 bytes. ຖ້າເລືອກ columns ເອງ ຕ້ອງມີ key ນັ້ນນຳ. ຊື່ຫຼື timestamp ທີ່ຊ້ຳກັນບໍ່ເໝາະເປັນ key ດຽວ. ### ອ່ານໜ້າຕໍ່ໄປ ```text $query = $db->table('products')->where('tenant_id', $authorizedTenant); $first = $query->cursorPaginate('id', 20); if ($first->hasMore) { $next = $query->cursorPaginate('id', 20, $first->nextCursor); } // For descending order, pass direction: 'DESC' on every request. // The last page has has_more=false and next_cursor=null. ``` ### ສິດເຂົ້າເຖິງ ແລະຂໍ້ຈຳກັດ Cursor ເປັນຄ່າລຽງລຳດັບ ບໍ່ແມ່ນໂທເຄັນອະນຸຍາດ. ກວດ user/tenant ໃໝ່ທຸກ request ແລະຮັກສາ filter ເດີມ. Pagination ນີ້ບໍ່ມີ total count, ເລກໜ້າ, composite cursor ຫຼື snapshot ຂໍ້ມູນ. ແຖວທີ່ເພີ່ມກ່ອນ cursor ຈະບໍ່ປາກົດຈົນເລີ່ມອ່ານໃໝ່. ບໍ່ໃຊ້ຮ່ວມກັບ orderBy/limit ທີ່ກຳນົດໄວ້ກ່ອນ. ກວດ query plan/index ໃນຖານຂໍ້ມູນຈິງ; ບໍ່ມີການຮັບປະກັນຄວາມໄວໂດຍອັດຕະໂນມັດ. ## ວາງພື້ນຖານສຳລັບລະບົບໃຫຍ່. ເລີ່ມດ້ວຍ application ທີ່ແບ່ງ module ຊັດເຈນ ແລ້ວຂະຫຍາຍຕາມຂໍ້ມູນການໃຊ້ງານຈິງ. ### ແບ່ງຕາມທຸລະກິດ ໃຫ້ Catalog ເປັນເຈົ້າຂອງສິນຄ້າ, Sales ຂອງຄຳສັ່ງຊື້ ແລະ Billing ຂອງໃບແຈ້ງໜີ້. ແຕ່ລະ module ມີທີມຮັບຜິດຊອບ, public Contracts, tests ແລະ README. ຮັກສາ dependencies ໃຫ້ບໍ່ເປັນວົງຈອນ; ເມື່ອ API ປ່ຽນ ໃຫ້ຮັກສາ contract ເກົ່າຊົ່ວຄາວ ຫຼືອັບເດດ consumer ໃນ release ດຽວ. ### ຕົວຢ່າງທີ່ລອງໄດ້ Source ມີ Catalog/Sales example ທີ່ໃຊ້ interface ຂ້າມ module, ກວດ tenant membership ໃນ service ແລະແບ່ງໜ້າສິນຄ້າ. CLI demo ໃຊ້ SQLite ໃນ memory; ບໍ່ສ້າງບັນຊີຈິງ. ຜົນຄວນເປັນ Catalog → Sales, ໜ້າທຳອິດ Coffee/Tea ແລະໜ້າຕໍ່ໄປ Rice. ອ່ານ README ຂອງ example ກ່ອນດັດແປງ; ມັນບໍ່ໄດ້ລົງທະບຽນໃນເວັບຈິງ. ```text php examples/modular-shop/demo.php ``` ### ການຂຽນຂໍ້ມູນ ແລະ background work ໃຊ້ transaction ດຽວສຳລັບ business data ແລະ Outbox::record ເທິງ scoped PDO connection ດຽວ. ໃຫ້ queue handler ຮອງຮັບການເຮັດຊ້ຳໄດ້; ການສົ່ງ email/payment ພາຍນອກຕ້ອງມີ idempotency ຂອງມັນເອງ. ຢ່າປະສົມ Doctrine connection ອີກຕົວແລ້ວຄິດວ່າ rollback ຮ່ວມກັນ. ໃຫ້ຜູ້ປະສານງານຄົນດຽວໃຊ້ migration; module boot ບໍ່ຄວນຂຽນ schema ຫຼືສົ່ງ network request. [Transactional outbox](https://framework.icom.la/docs/outbox) [Queues and leases](https://framework.icom.la/docs/queues) ### ຂະຫຍາຍຫຼາຍ instance ກ່ອນເພີ່ມ application replicas ໃຫ້ຍ້າຍ business/auth/queue state ໄປຫາ shared SQL ທີ່ຜ່ານການທົດສອບ; ໃຊ້ Redis ສຳລັບ cache/rate limits ແລະຕັ້ງ namespace ແຍກ application. ການເພີ່ມ Redis ຢ່າງດຽວບໍ່ໄດ້ຍ້າຍ SQLite ໄປເປັນ shared database. ແຍກ web, maintenance ແລະ queue workers ຕາມ workload; ກຳນົດ timeout, retry, connection budget ແລະ graceful shutdown. ### ໃຊ້ worker runtime ຢ່າງຮອບຄອບ PHP-FPM ແມ່ນ runtime ຂອງເວັບຈິງ. FrankenPHP/Swoole adapters ມີຜົນທົດສອບປະຫວັດໃນ source; ການປ່ຽນ application/PHP/runtime ຕ້ອງທົດສອບ scope isolation, recycling, ການຂາດ DB/Redis ແລະ memory ໃນໄລຍະຍາວອີກ. ບໍ່ເກັບ identity ໃນ static/singleton ແລະບໍ່ນຳ native extensions ຂ້າມ PHP ABI ໂດຍບໍ່ rebuild. ### ວັດກ່ອນຂະຫຍາຍ ກຳນົດ workload ຈິງ: request ຕໍ່ວິນາທີ, p95/p99 latency, error rate, SQL queries, lock wait, queue age, CPU/RSS ແລະຂະໜາດຂໍ້ມູນ. ທົດສອບ backup/restore, migration ແລະ rollback ໃນ staging. ຜົນກວດ graph 500 modules ຫຼື request scopes ຊ້ຳໆ ແມ່ນ regression evidence; ບໍ່ແມ່ນການຮັບປະກັນຈຳນວນຜູ້ໃຊ້ ຫຼື production capacity. ### ອາການ ແລະວິທີກວດ ```text Missing module dependency → Register the dependency with its exact name. Module dependency cycle → Move a shared contract or reverse the dependency. Service is already bound → Review ownership; use bind only for an intentional override. private-module-reference → Depend on a public Contracts interface. Scoped service at root → Resolve inside a request/job scope, not provider boot. 404 after generation → Register the provider; composer dump-autoload; inspect routes. 403 on tenant products → Check active account, current membership and role permission. Cursor pagination error → Use a unique non-null key; remove earlier orderBy/limit. ``` ## ປຽບທຽບດ້ວຍຫຼັກຖານ. ກວດລຸ້ນທາງການໃນວັນທີ 10 ກັນຍາ 2026: ThinkPHP 8.1.4 ແລະ Laravel 13.31.0. ### ຈຸດອ້າງອີງປັດຈຸບັນ ThinkPHP ແລະ Laravel ມີ service lifecycle ແລະ route groups ຢູ່ແລ້ວ. Laravel ຍັງມີ cursor pagination ແລະ queue ecosystem ທີ່ກວ້າງ. ການເພີ່ມຄວາມສາມາດເຫຼົ່ານີ້ໃນ ICOM ຈຶ່ງເປັນການປັບພື້ນຖານໃຫ້ໃຊ້ງານງ່າຍຂຶ້ນ; ບໍ່ແມ່ນຫຼັກຖານວ່າຄູ່ປຽບທຽບຂາດຄວາມສາມາດນັ້ນ. [ThinkPHP 8.1.4 release](https://github.com/top-think/framework/releases/tag/v8.1.4) [Laravel 13.31.0 release](https://github.com/laravel/framework/releases/tag/v13.31.0) [Laravel providers](https://laravel.com/framework/docs/providers) [Laravel cursor pagination](https://laravel.com/framework/docs/pagination) [ThinkPHP service lifecycle source](https://github.com/top-think/framework/blob/v8.1.4/src/think/Service.php) [ThinkPHP route groups source](https://github.com/top-think/framework/blob/v8.1.4/src/think/route/RuleGroup.php) ### ICOM 0.7 ເນັ້ນຫຍັງ? Explicit module dependency graph, ການກວດ public Contracts ຂ້າມ module, scoped services, ການສ້າງ module ທີ່ບໍ່ເປີດ route ອັດຕະໂນມັດ, tenant-aware example ແລະຄູ່ມືພາສາລາວ. ຈຸດປະສົງແມ່ນຊ່ວຍໃຫ້ທີມເຫັນຂອບເຂດແລະກວດຄວາມຜິດພາດໄດ້ໄວຂຶ້ນ. ### ຈະພິສູດວ່າ “ດີກວ່າ” ແນວໃດ? ສ້າງ application ທີ່ມີ business rules, SQL schema, authentication, middleware ແລະ response ເທົ່າກັນ ເທິງເຄື່ອງ/PHP/runtime ດຽວກັນ. ວັດ developer task completion, defects, p95/p99 latency, throughput, CPU/RSS ແລະ failure recovery. ຮອບນີ້ບໍ່ໄດ້ຮັນ comparative benchmark ຫຼື production soak ດັ່ງກ່າວ ຈຶ່ງຍັງບໍ່ອ້າງວ່າເໜືອກວ່າທຸກດ້ານ. ### ສິ່ງທີ່ຍັງຕ້ອງປະກອບເພີ່ມ Application-specific mail/uploads, actual OIDC provider setup, recovery delivery, external brokers, distributed tracing/metrics collector, production cluster/failover, worker soak ແລະ independent security assessment ຍັງຕ້ອງອອກແບບແລະທົດສອບຕາມລະບົບຈິງ. ICOM ຍັງເປັນ developer preview; ecosystem ແລະປະຫວັດການນຳໃຊ້ຍັງບໍ່ເທົ່າ Laravel/ThinkPHP. [Release verification](https://framework.icom.la/verification.md) ## ກວດສະຖານະ ແລະກູ້ຄືນລະບົບ. ໃຊ້ CLI ທີ່ແຍກຈາກເວັບສາທາລະນະ ເພື່ອກວດ readiness, ວຽກຄ້າງ ແລະ migration ກ່ອນເກີດບັນຫາກັບຜູ້ໃຊ້. ### 1. ກວດສະຖານະຈາກ terminal ຮັນຈາກ project root ດ້ວຍບັນຊີດູແລ application. ops:check ອ່ານທຸກ queue ເມື່ອບໍ່ລະບຸຊື່; ສາມາດລະບຸ queue ທີ່ຈະຕິດຕາມໄດ້. JSON ມີ status, readiness, queue, outbox, schedules ແລະ alerts. status ເປັນ ok ຫຼື degraded; exit code 0 ໝາຍເຖິງຜ່ານ ແລະ 1 ໝາຍເຖິງຕ້ອງກວດຕໍ່. ຜົນບໍ່ສົ່ງ job payload, ລະຫັດລັບ ຫຼືລາຍລະອຽດ exception ອອກມາ. ```text php bin/icom ops:check php bin/icom ops:check default # Healthy: status = "ok", alerts = [], exit 0 # Degraded: status = "degraded", inspect alerts, exit 1 ``` ### 2. ແຍກ health ອອກຈາກ readiness /health ຍັງເປັນການກວດວ່າ application ຕອບໄດ້ ໂດຍບໍ່ probe DB/cache. /ready ກວດ DB connection, migration status ດ້ວຍການອ່ານ, cache ແລະສິດຂຽນໃນ storage ແລະ storage/logs. ເມື່ອ CACHE_DRIVER=file ຈຶ່ງກວດ storage/cache ແລະ storage/rates ເພີ່ມ; Redis ບໍ່ຕ້ອງມີສອງ directory ນັ້ນໃນເຄື່ອງ. Public response ຂອງ /ready ມີພຽງ status ready ຫຼື unavailable; ຖ້າບໍ່ພ້ອມຈະຕອບ HTTP 503. ອ່ານລາຍລະອຽດຜ່ານ ops:check ໃນ terminal. Readiness ບໍ່ໄດ້ຢືນຢັນວ່າ worker ກຳລັງແລ່ນ ຫຼືວຽກທຸລະກິດຈະສຳເລັດ. ```text curl --fail --silent --show-error https://your-app.example/health curl --fail --silent --show-error https://your-app.example/ready # /ready: HTTP 200 {"status":"ready"} # /ready: HTTP 503 {"status":"unavailable"} ``` ### Probe ເຮັດຫຍັງກັບຂໍ້ມູນ? ການກວດ queue, outbox, schedules ແລະ migration status ໃຊ້ SQL ອ່ານຢ່າງດຽວ; ບໍ່ reserve job, ບໍ່ relay outbox ແລະບໍ່ tick schedule. Readiness ຂອງ /ready ແລະ ops ໃຊ້ cache roundtrip ຈິງ: ສ້າງ key ສຸ່ມ, set ດ້ວຍ TTL 60 ວິນາທີ, get ແລະ delete. ຈຶ່ງມີການຂຽນ cache ຊົ່ວຄາວ. ການກວດສິດຂຽນ directory ບໍ່ແມ່ນການຮັບປະກັນວ່າ disk ຈະບໍ່ເຕັມຫຼື I/O ຈະສຳເລັດຄັ້ງຕໍ່ໄປ. ### 3. ອ່ານ queue ໃຫ້ຖືກ ready, delayed, leased, exhausted ແລະ failed ແມ່ນກຸ່ມທີ່ບໍ່ນັບຊ້ຳກັນ. ready ແມ່ນວຽກທີ່ພ້ອມໃຫ້ worker ຮັບ; delayed ແມ່ນວຽກທີ່ຍັງບໍ່ຮອດເວລາ; leased ແມ່ນວຽກທີ່ຍັງມີ lease ທີ່ໃຊ້ໄດ້. exhausted ແມ່ນວຽກທີ່ໃຊ້ຈຳນວນຄັ້ງລອງໝົດແລ້ວ ແລະບໍ່ມີ lease ທີ່ໃຊ້ໄດ້; failed ແມ່ນວຽກທີ່ຖືກບັນທຶກວ່າລົ້ມເຫຼວ. expired_leases ເປັນຄ່າວິນິດໄສທີ່ອາດຊ້ຳກັບກຸ່ມອື່ນ ຈຶ່ງບໍ່ຄວນບວກເຂົ້າໃນຍອດລວມ. ```text ready + delayed + leased + exhausted + failed = classified queue jobs expired_leases = additional diagnostic; do not add it again ready_since = max(available_at, expired lease end) oldest ready age = now - earliest ready_since ``` ### ຄວາມໝາຍຂອງອາຍຸວຽກ Queue ນັບອາຍຸວຽກ ready ຈາກເວລາທີ່ມັນຮັບໄດ້ຈິງ: ຄ່າທີ່ຊ້າກວ່າລະຫວ່າງ available_at ແລະ lease ທີ່ໝົດອາຍຸ. ວຽກທີ່ກຳນົດໃຫ້ເຮັດມື້ອື່ນຈຶ່ງບໍ່ເປັນວຽກຄ້າງ ready ໃນມື້ນີ້. Outbox pending ນັບອາຍຸຈາກ created_at ເພາະ relay ສາມາດສົ່ງວຽກທີ່ກຳນົດເວລາໃນອະນາຄົດເຂົ້າ queue ໄດ້ແລ້ວ. Outbox published ໝາຍເຖິງສົ່ງຕໍ່ເຂົ້າ queue ແລ້ວ; ຕ້ອງກວດຜົນຂອງ handler ແຍກຕ່າງຫາກ. ### 4. ກວດ schedule ແລະເກນແຈ້ງເຕືອນ ສຳລັບ schedule ທີ່ເຄີຍບັນທຶກ slot, lag ນັບຈາກ slot ທຳອິດທີ່ພາດ: last_slot + interval_seconds. ຄ່າຈຶ່ງເພີ່ມຕາມຊ່ວງ outage ແລະບໍ່ກັບເປັນ 0 ພຽງເພາະຮອດ interval ຖັດໄປ. ຖ້າ schedule ໃໝ່ຮອດເວລາແລ້ວແຕ່ຍັງບໍ່ມີ last_slot, ຈະນັບ never_run ແລະແຈ້ງ schedule_never_run; ອາຍຸປະຫວັດຍັງບໍ່ຮູ້ ຈຶ່ງໃຊ້ພຽງຄວາມຊ້າຈາກ due slot ລ່າສຸດສຳລັບ lag ຂອງ schedule ນັ້ນ. ບັນທຶກ slot ໝາຍເຖິງສ້າງວຽກແລ້ວ; ບໍ່ແມ່ນ worker heartbeat ຫຼືຜົນວຽກສຳເລັດ. ຕັ້ງເກນອາຍຸໃນ config/operations.php ຕາມ workload. ຄ່າ failed jobs, failed outbox ຫຼື exhausted leases ຈະແຈ້ງເຕືອນສະເໝີ; ການເພີ່ມເກນເວລາບໍ່ປິດການແຈ້ງເຕືອນເຫຼົ່ານີ້. ```text 300, 'outbox_wait_seconds' => 120, 'schedule_lag_seconds' => 120, ]; ``` ### 5. ອ່ານ metrics ຜ່ານ CLI ops:metrics ສົ່ງ Prometheus text ໄປ stdout ຂອງ private CLI. ບໍ່ມີ public /metrics endpoint ໃໝ່. Exit code 0 ໝາຍເຖິງຜະລິດ metrics ໄດ້ ແມ່ນແຕ່ຕອນລະບົບ degraded; ໃຊ້ ops:check ຫຼືອ່ານຄ່າ metrics ເພື່ອຕັດສິນສຸຂະພາບ. ຜູ້ດູແລຕ້ອງຕິດຕັ້ງ collector ທີ່ປ້ອງກັນການເຂົ້າເຖິງ ແລະວາງໄຟລ໌ອອກນອກ document root. ຄຳສັ່ງນີ້ບໍ່ສົ່ງຂໍ້ມູນໄປຫາບໍລິການພາຍນອກເອງ. ```text php bin/icom ops:metrics php bin/icom ops:metrics default # Prometheus text: HELP / TYPE comments followed by numeric samples. # A successful export can still report an unhealthy application. # Selected metric names (examples, not shell commands): # icom_operations_ok # icom_ready # icom_component_up{component="queue"} # icom_queue_jobs{state="ready"} # icom_queue_expired_leases # icom_queue_oldest_ready_age_seconds # icom_outbox_oldest_pending_age_seconds # icom_schedule_never_run # icom_schedule_max_lag_seconds ``` ### ຄວາມຖີ່ ແລະ deadline ຂອງການກວດ ເລີ່ມກວດທຸກ 30–60 ວິນາທີ ແລ້ວປັບຕາມຂະໜາດຂໍ້ມູນ ແລະເວລາຕອບຈິງ. SQL aggregates ມີຕົ້ນທຶນການອ່ານ; ກວດ query plan, index, retention ແລະ DB load ກ່ອນເພີ່ມຄວາມຖີ່. ຕັ້ງ I/O deadlines ໃນ DB/cache driver, runtime ແລະ probe platform. ການກວດຂອງ framework ບໍ່ສາມາດບັງຄັບຍົກເລີກ blocking I/O ທຸກຊະນິດພາຍໃນເວລາຕາຍຕົວ. ຢ່າຕັ້ງ readiness failure ຄັ້ງດຽວໃຫ້ restart ທຸກ instance ພ້ອມກັນ. ### 6. ກຳນົດຂອບເຂດ worker ຕົວຢ່າງນີ້ຮັນ queue default ສູງສຸດ 100 jobs ຫຼື 300 ວິນາທີ, ໃຊ້ lease 120 ວິນາທີ ແລະເກນ memory 128 MiB. --stop-when-empty ໃຫ້ອອກເມື່ອບໍ່ພົບວຽກທີ່ຮັບໄດ້. --memory=0 ປິດເກນ memory ຂອງ worker. ເກນຈຳນວນ jobs, ເວລາ ແລະ memory ກວດລະຫວ່າງ jobs; ມັນບໍ່ຕັດ handler ທີ່ກຳລັງບລັອກ. ເມື່ອມີ PCNTL signal support, SIGTERM ໃຫ້ handler ທີ່ກຳລັງເຮັດວຽກຈົບກ່ອນຢຸດຮັບວຽກໃໝ່. ຕັ້ງ supervisor grace period ໃຫ້ພໍກັບ handler ແລະຕັ້ງ network/DB timeout ພາຍໃນວຽກ. ```text php bin/icom queue:work default 100 300 --stop-when-empty --lease=120 --memory=128 ``` ### Lease ແລະວຽກທີ່ໃຊ້ເວລາດົນ Graceful shutdown ບໍ່ໄດ້ຕໍ່ອາຍຸ lease ໃຫ້ວຽກເອງ. Handler ທີ່ອາດໃຊ້ເວລາເກີນ lease ຕ້ອງມີ heartbeat ຕາມ queue API ແລະຢຸດຂຽນເມື່ອເສຍ ownership. ຖ້າ process ຢຸດ ຫຼື lease ໝົດ, ວຽກອາດຖືກເຮັດຊ້ຳ. ອອກແບບຕາມ at-least-once delivery: ໃຊ້ idempotency key ຂອງທຸລະກິດ, unique constraint ແລະກວດຜົນພາຍນອກກ່ອນ retry. ການສົ່ງ email ຫຼື payment ຕ້ອງມີການປ້ອງກັນການເຮັດຊ້ຳຂອງບໍລິການນັ້ນນຳ. [Queue ownership and heartbeat](https://framework.icom.la/docs/queues) [Transactional outbox](https://framework.icom.la/docs/outbox) ### 7. ກວດ migration ກ່ອນ deploy migrate:status ໃຊ້ SELECT ເພື່ອອ່ານ migration history; ບໍ່ສ້າງ history table ແລະບໍ່ execute migration. ຜົນມີ initialized, applied, pending, missing ແລະ ok. pending ແມ່ນ migration ໃນ release ທີ່ຍັງບໍ່ໄດ້ໃຊ້; missing ແມ່ນ migration ທີ່ DB ບັນທຶກວ່າໃຊ້ແລ້ວ ແຕ່ບໍ່ມີໃນ source ປັດຈຸບັນ. ຖ້າມີ pending/missing ຈະອອກດ້ວຍ nonzero exit code. ກວດ release, ບັນຊີ DB ແລະ backup ກ່ອນໃຊ້ migrate; ຢ່າແກ້ migration history ດ້ວຍມືເພື່ອໃຫ້ status ຜ່ານ. ```text php bin/icom migrate:status # Healthy existing installation: # initialized = true, pending = [], missing = [], ok = true # Run only as the chosen deployment coordinator after reviewing changes: php bin/icom migrate php bin/icom migrate:status ``` ### Migration lock ແລະ rollback MySQL ໃຊ້ GET_LOCK ທີ່ຜູກກັບ database ເພື່ອປະສານການຮັນ migrate; SQLite ໃຊ້ local flock. ໃນ cluster ຍັງຕ້ອງກຳນົດ deployment coordinator ດຽວ ແລະບໍ່ໃຫ້ທຸກ replica ຮັນ migration ຕອນ startup. DDL ບາງຊະນິດໃນ MySQL ບໍ່ສາມາດ rollback ດ້ວຍ transaction ໄດ້. ອອກແບບ schema ແບບເພີ່ມກ່ອນແລ້ວຄ່ອຍຖອນ ໃຫ້ release ເກົ່າແລະໃໝ່ໃຊ້ຮ່ວມກັນໄດ້ໃນຊ່ວງ deploy. ການປ່ຽນ symlink ກັບ release ເກົ່າບໍ່ໄດ້ກູ້ຄືນ schema ຫຼື side effects ຈາກ jobs. ### 8. ວິທີກວດເມື່ອເກີດບັນຫາ ເລີ່ມຈາກ ops:check ແລະປຽບທຽບກັບຄັ້ງກ່ອນ. ຖ້າ readiness ບໍ່ຜ່ານ ໃຫ້ກວດ connection, migration, cache ແລະສິດ directory ດ້ວຍບັນຊີທີ່ຮັນ application; ຢ່າແກ້ດ້ວຍ chmod 777. ຖ້າ ready age ເພີ່ມ ໃຫ້ກວດ worker process, queue name, handler ແລະ DB latency. ຖ້າ outbox pending age ເພີ່ມ ໃຫ້ກວດ maintenance/relay. ຖ້າ schedule lag ສູງ ໃຫ້ກວດ cron ແລະເວລາ UTC ຂອງ host. failed/exhausted ຕ້ອງກວດຜົນທຸລະກິດ ແລະແກ້ສາເຫດກ່ອນ retry. ```text php bin/icom ops:check php bin/icom migrate:status php bin/icom queue:failed php bin/icom outbox:failed 50 php bin/icom schedule:list # After repairing the cause and checking whether the effect already occurred: php bin/icom queue:retry FAILED_JOB_ID php bin/icom outbox:retry MESSAGE_ID php bin/icom ops:check ``` ### 9. ຂັ້ນຕອນ deploy ທີ່ກວດຍ້ອນຫຼັງໄດ້ ສຳຮອງ DB ແບບ consistent, .env ແລະ deployment configuration ໄວ້ໃນທີ່ private; ທົດສອບ restore ໃນ staging. ຕິດຕັ້ງ release ໃໝ່ແຍກ directory, ກວດ PHP/extensions, dependencies ແລະ tests, ເຊື່ອມ shared .env/storage ແລະຮັກສາ APP_KEY ເດີມ. ກວດ migration plan ກ່ອນປ່ຽນ release. ຫຼັງປ່ຽນຕ້ອງກວດ /ready, ops:check ແລະ business smoke test; ໃຫ້ supervisor restart workers ຢ່າງ graceful ເພື່ອໂຫຼດ code ໃໝ່. ຖ້າ rollback ຕ້ອງກວດວ່າ code ເກົ່າໃຊ້ schema/job payload ປັດຈຸບັນໄດ້. ລຸ້ນ 0.8 ບໍ່ເພີ່ມ schema migration ແລະບໍ່ຕ້ອງປ່ຽນ APP_KEY, cron ຫຼື PHP handler. ### ຂອບເຂດທີ່ຕ້ອງປະກອບເພີ່ມ ຊຸດກວດນີ້ຊ່ວຍໃຫ້ອ່ານສະຖານະແລະຕັດສິນໃຈກູ້ຄືນໄດ້ຊັດເຈນຂຶ້ນ. ຍັງຕ້ອງມີ supervisor, protected metrics collector, ການແຈ້ງເຕືອນໄປຫາທີມ, log rotation, backup/restore, tracing ແລະ failover ຕາມ infrastructure ຈິງ. ບໍ່ມີ dashboard ຫຼື automatic remediation ທີ່ retry/delete ຂໍ້ມູນເອງ. ທົດສອບ outage, lease expiry, worker termination ແລະ restore ໃນ staging ກ່ອນພຶ່ງພາໃນລະບົບສຳຄັນ. [Large applications](https://framework.icom.la/docs/large-applications) [Scheduler and maintenance](https://framework.icom.la/docs/scheduler) [Release verification](https://framework.icom.la/verification.md) [Lao developer guide](https://framework.icom.la/developer-guide.md) ## ຟີເຈີສຳລັບສ້າງແອັບຈິງ. ເລືອກໃຊ້ຕາມວຽກ: ແຕ່ລະຟີເຈີມີຂອບເຂດ, ການຕັ້ງຄ່າ ແລະການທົດສອບ. ### ໃໝ່ໃນ 0.9 ເພີ່ມ private storage/upload policy, CORS, signed URLs, localization, validation ແລະ API resources/problem responses/OpenAPI. ລະບົບຍັງເປັນ developer preview; ຄຳວ່າ “ທຸກຟີເຈີ” ບໍ່ມີລາຍການຕາຍຕົວ. ໜ້ານີ້ລະບຸສິ່ງທີ່ມີຈິງ ແລະສິ່ງທີ່ຕ້ອງຕໍ່ເຕີມ. [Production use · 0.10](https://framework.icom.la/docs/production-use) [Files and uploads](https://framework.icom.la/docs/storage-uploads) [CORS and signed URLs](https://framework.icom.la/docs/http-features) [Localization and validation](https://framework.icom.la/docs/localization-validation) [API tools](https://framework.icom.la/docs/api-tools) ### Kernel ແລະຂໍ້ມູນ Router, route groups, PSR-11 container, request scopes, PSR-7/15, PDO query builder, transactions, tracked migrations, cursor pagination, explicit modules ແລະ AST boundary checker ມີແລ້ວ. Doctrine ORM ແລະ Redis ເປັນ optional integrations; ຕ້ອງເພີ່ມ package ໃຫ້ເປັນ production dependency ເມື່ອໃຊ້ຈິງ. [Modules](https://framework.icom.la/docs/modules) [Large applications](https://framework.icom.la/docs/large-applications) [Database](https://framework.icom.la/docs/database) [ORM](https://framework.icom.la/docs/orm) ### Identity ແລະສິດ Password/session authentication, TOTP MFA, recovery codes, explicit role/resource authorization, tenant memberships, audit records ແລະ optional OIDC ມີແລ້ວ. ບໍ່ສ້າງ default account; ແຕ່ລະແອັບຕ້ອງກວດ ownership/tenant ກ່ອນອ່ານຫຼືແກ້ຂໍ້ມູນ. [Authentication](https://framework.icom.la/docs/authentication) [Account screens](https://framework.icom.la/account) [Tenancy](https://framework.icom.la/docs/tenancy) ### ວຽກເບື້ອງຫຼັງ ແລະການດູແລ SQL queues, retry/failed jobs, transactional outbox, UTC scheduler, synchronous events, private operations/metrics CLI, readiness ແລະ worker bounds ມີແລ້ວ. Jobs ຍັງເປັນ at least once: handler ຕ້ອງອອກແບບ idempotency. ຟີເຈີເຫຼົ່ານີ້ບໍ່ທົດແທນ supervisor, backup ຫຼື monitoring service. [Queues](https://framework.icom.la/docs/queues) [Operations](https://framework.icom.la/docs/operations) [PHP compatibility](https://framework.icom.la/docs/php-compatibility) ### ຂອບເຂດທີ່ຕ້ອງວາງແຜນຕໍ່ Mailer/notification delivery, S3/cloud object storage, WebSocket/broadcasting, SAML, API-token lifecycle, remote brokers, distributed locks, full-text search ແລະ tracing exporter ຍັງບໍ່ຖືກຕິດຕັ້ງໃນລຸ່ນນີ້. ການນຳໃຊ້ໃນອົງກອນຕ້ອງມີ integration/load/security review ຕາມ workload ຈິງ. ບໍ່ອ້າງວ່າໄວກວ່າ Laravel/ThinkPHP/Symfony ໂດຍບໍ່ມີ comparative benchmark. [Verification](https://framework.icom.la/verification.md) ### ລອງຟີເຈີຮ່ວມກັນຈາກ CLI ຕົວຢ່າງລຸ່ມໃຊ້ຂໍ້ມູນຈຳລອງ, random key ຊົ່ວຄາວ ແລະ private temporary storage; ບໍ່ອ່ານ .env ແລະບໍ່ເປີດ endpoint. ທົດລອງ validation, localization, output projection, error response, signed URL ແລະ file roundtrip ກ່ອນລຶບໄຟລ໌ທີ່ຕົນສ້າງ. ຖ້າມີ ext-fileinfo ຈະກວດ upload MIME ຈິງ; ຖ້າບໍ່ມີ ຈະລາຍງານ skipped ສະເພາະສ່ວນນັ້ນ. ```text php examples/application-features/demo.php # Expected: ok=true, cleanup=true; see the example README for its scope. ``` [Source archive](https://framework.icom.la/downloads/icom-framework-0.10.0.zip) ## ໄຟລ໌ສ່ວນຕົວ ແລະ upload ທີ່ຈຳກັດ. ເກັບໄຟລ໌ນອກ document root, ກຳນົດຂະໜາດ/ຊະນິດ ແລະກວດສິດກ່ອນດາວໂຫຼດ. ### 1. ຕຽມ private directory LocalStorage ໃຊ້ directory ທີ່ມີຢູ່ແລ້ວ, canonical absolute path, mode 0700 ແລະບໍ່ມີ symlink ໃນ path. ຕ້ອງເປັນ local POSIX filesystem ທີ່ຮອງຮັບ hard link; operator ຕ້ອງຄວບຄຸມ directory ແລະ parents. ຢ່າວາງໄວ້ໃນ public/. ບໍ່ໃຊ້ client filename ເປັນ filesystem path. ```text install -d -m 700 /private/application-files # Use your actual private path and application OS user. ``` ### 2. ຂຽນ stream ແບບມີຂອບເຂດ put ສ້າງ immutable object ID 64 hexadecimal characters, ຂຽນໄຟລ໌ mode0600 ແລະ publish ແບບບໍ່ overwrite. ຖ້າເກີນ limit ຫຼື stream ບໍ່ສົມບູນ ຈະລົ້ມເຫຼວແລະລຶບ staging file. JSON metadata ມີ id, bytes, media_type, sha256; ບໍ່ມີ private path. ```text use Icom\Storage\LocalStorage; use Nyholm\Psr7\Stream; $files = new LocalStorage('/private/application-files', maxBytes: 2_000_000); $saved = $files->put(Stream::create('Generated report')); // Persist $saved->id with the owning account/tenant in your database. // Authorize the current account and resource before reading or deleting. $response = $files->download($saved->id, 'report.txt'); ``` ### 3. ຮັບ upload ແບບ opt-in RequestGuard ປະຕິເສດ multipart ໂດຍຄ່າເລີ່ມຕົ້ນ. ແກ້ registration ຂອງ guard ທີ່ມີຢູ່ໃນ bootstrap ໃຫ້ອະນຸຍາດ exact POST path; ການເພີ່ມ guard ອີກອັນຫຼັງ default guard ບໍ່ເປີດ upload. ຕ້ອງມີ bounded Content-Length ແລະ trusted SAPI/PSR multipart parser. ຕັ້ງ web-server/PHP post_max_size, upload_max_filesize, max_file_uploads ໃຫ້ສອດຄ່ອງ. ສົ່ງ CSRF token ຜ່ານ X-CSRF-Token; authentication/authorization ຍັງຈຳເປັນ. ```text use Icom\Middleware\RequestGuard; use Icom\Storage\{UploadPolicy, Uploads}; $guard = new RequestGuard(['your-app.example'], 3_000_000, ['/account/files']); $uploads = new Uploads($files); $policy = new UploadPolicy(2_000_000, ['image/png', 'image/jpeg']); // Inside an authenticated and authorized POST /account/files handler: // $upload = $request->getUploadedFiles()['document']; // $saved = $uploads->store($upload, $policy); ``` ### 4. MIME ແລະການດາວໂຫຼດ UploadPolicy ຕ້ອງມີ ext-fileinfo ແລະ allowlist ຊັດເຈນ; ຮອງຮັບ image/jpeg, image/png, application/pdf, text/plain. ກວດ bytes ຈິງ ແລະ PHP upload error; ບໍ່ເຊື່ອ client MIME/name. Fileinfo ບໍ່ແມ່ນ antivirus, image decoder ຫຼື polyglot detector. download ຕອບ attachment + application/octet-stream + nosniff + no-store. ບໍ່ເປີດ inline HTML/SVG; ກຳນົດ ASCII attachment name ສຳລັບສະແດງເທົ່ານັ້ນ. ### 5. ວົງຈອນໄຟລ໌ ID ທີ່ຄາດເດົາຍາກບໍ່ແມ່ນສິດເຂົ້າເຖິງ. ເກັບ mapping ກັບ owner/tenant, ກວດ policy ທຸກ read/delete/download, ກຳນົດ quota/retention/backup ແລະຈັດການ orphan ຫຼັງ DB failure. Filesystem ແລະ SQL ບໍ່ຢູ່ transaction ດຽວກັນ. ບໍ່ມີ encryption-at-rest, antivirus, cloud replication ຫຼື public upload endpoint ຖືກເປີດໃນເວັບເອກະສານ. Multipart integration ຕ້ອງທົດສອບແຍກຕາມ FPM/worker adapter. [PHP upload errors](https://www.php.net/manual/en/features.file-upload.errors.php) ## CORS ແລະລິ້ງທີ່ໝົດອາຍຸ. ອະນຸຍາດ origins ຢ່າງຊັດເຈນ ແລະຜູກລາຍເຊັນກັບ URL/method/purpose. ### 1. CORS ສຳລັບ API ທີ່ເລືອກ ຕິດຕັ້ງ Cors ກ່ອນ route dispatch ແລະກ່ອນ middleware ທີ່ອາດປະຕິເສດ preflight. ໃຊ້ exact HTTPS origins; ບໍ່ມີ wildcard. pathPrefix ກົງກັບ path ນັ້ນແລະ subtree ເທົ່ານັ້ນ. ເປີດ credentials ເມື່ອອອກແບບ session/CSRF ຮອງຮັບແລ້ວ. ຖ້າ request ສົ່ງ Origin ຂອງ same-origin ເອງ ກໍຕ້ອງຢູ່ allowlist. RequestContext/Errors/RequestGuard ຄວນກວດ host, request bounds ແລະ security headers ກ່ອນ Cors; ວາງ Cors ກ່ອນ route authentication ເພື່ອຮັບ preflight. ຕົວຢ່າງນີ້ໃຊ້ໄດ້ໃນແອັບທີ່ທ່ານກຳນົດ bootstrap ເອງ. ```text use Icom\Middleware\Cors; $app->use(new Cors( pathPrefix: '/api/v1', allowedOrigins: ['https://app.example'], allowedMethods: ['GET', 'HEAD'], allowedHeaders: [], exposedHeaders: ['X-Request-ID'], credentials: false, maxAge: 600, )); ``` ### 2. CORS ບໍ່ທົດແທນ authentication CORS ຄວບຄຸມການອ່ານຂໍ້ມູນຂອງ browser; non-browser client ຍັງສົ່ງ request ໄດ້. ການຜ່ານ preflight ຢືນຢັນ configured policy, ບໍ່ຢືນຢັນວ່າ route ມີຢູ່ຫຼື user ມີສິດ. ຮັກສາ Vary headers ເພື່ອ cache ບໍ່ເອົາຄຳຕອບປົນ origins. CSRF middleware ທີ່ມີຢູ່ຍັງປະຕິເສດ foreign-origin mutation; ການເພີ່ມ CORS ບໍ່ປິດ CSRF. ໃນ 0.10 ຄຳຕອບ error ຈາກ handler ຍັງຮັກສາ Vary ແລະສິດອ່ານຂອງ origin ທີ່ອະນຸຍາດ ຜ່ານ Errors ຊັ້ນນອກ; origin ທີ່ຖືກປະຕິເສດບໍ່ໄດ້ຮັບ grant. ### 3. ສ້າງລິ້ງມີອາຍຸ ໃຊ້ raw APP_KEY 32 bytes ຈາກ config ທີ່ decode ແລ້ວ; ຢ່າ hardcode production key. SignedUrl ແຍກ HMAC key ຕາມ purpose, ຜູກ trusted origin, method, path, canonical query ແລະ expiry. ຕົວຢ່າງນີ້ມີອາຍຸ5ນາທີ; maxTtl ຈຳກັດອາຍຸສູງສຸດ. ```text use Icom\Security\SignedUrl; use Icom\Middleware\ValidateSignature; $links = new SignedUrl($rawAppKey, 'https://your-app.example', 'reports', maxTtl: 900); // First authorize the account/tenant for report 123. $url = $links->sign('/reports/123', time() + 300); // $authenticate is your application's authentication middleware. // ReportController::download must also check the report's owner/tenant. $app->get('/reports/{id}', [ReportController::class, 'download']) ->middleware(new ValidateSignature($links)) ->middleware($authenticate); // Keep the standard outer application Errors middleware. // Never print keys or signed links to public logs. ``` ### 4. ຂອບເຂດຂອງລາຍເຊັນ Query ຮອງຮັບ flat string/int ກັບ ASCII keys; duplicate keys, reserved keys ແລະ ambiguous encoding ຖືກປະຕິເສດ. GET signature ໃຊ້ HEAD ໄດ້; HEAD-only signature ໃຊ້ GET ບໍ່ໄດ້. Method ອື່ນຕ້ອງກົງກັນ. ລາຍເຊັນບໍ່ປົກປິດ query ແລະບໍ່ຜູກ request body. ລິ້ງໃຊ້ຊ້ຳໄດ້ຈົນໝົດອາຍຸ; one-time/revocation ຕ້ອງມີ server state. ValidateSignature ໃຫ້ no-store/no-referrer. ກວດ resource policy ກ່ອນຄືນຂໍ້ມູນສ່ວນຕົວ. ການແກ້ APP_KEY ເຮັດໃຫ້ລິ້ງເກົ່າໃຊ້ບໍ່ໄດ້; ຢ່າ rotate key ໂດຍບໍ່ວາງແຜນ. expires/signature ເປັນ reserved query names. ການສະຫຼັບລຳດັບ query, ໃຊ້ + ແທນ %20 ຫຼື double encoding ເຮັດໃຫ້ verify ບໍ່ຜ່ານ; ຄ່າ query ບໍ່ຮັບ literal %. maxTtl ຄ່າເລີ່ມຕົ້ນແມ່ນ 86,400 ວິນາທີ; ຕັ້ງໄດ້ 1–2,592,000 ວິນາທີ. ### 5. ຂໍ້ມູນທີ່ລາຍເຊັນຢືນຢັນ verify($request) ກວດ raw URI ແລະ request target; ບໍ່ຮັບຮອງຄ່າ getQueryParams() ທີ່ adapter ຫຼື middleware ອື່ນປ່ຽນແຍກຈາກ URI. ຢ່າ rewrite path/query ຫຼັງກວດລາຍເຊັນ, ແລະກວດ parser/adapter ໃຫ້ໄດ້ຄ່າກົງ raw query. ຕົວຢ່າງໃຊ້ report ID ຈາກ signed path ແລະກວດ owner/tenant ທຸກຄັ້ງ. ຫ້າມໃຊ້ GET/HEAD ເພື່ອແກ້ຂໍ້ມູນ, ລຶບໄຟລ໌ ຫຼືອະນຸມັດທຸລະກຳ; method ທີ່ຂຽນຂໍ້ມູນຍັງຕ້ອງມີ authentication, CSRF/authorization ແລະ body validation ຂອງມັນ. ### 6. ຮັກສາລິ້ງເປັນຂໍ້ມູນສ່ວນຕົວ ValidateSignature ໃຫ້ private, no-store ແລະ no-referrer ທັງ response ປົກກະຕິ, HttpException ແລະ unexpected failure. ໃນ 0.10 ໃຊ້ Errors middleware ຊັ້ນນອກມາດຕະຖານໄດ້ເລີຍ; ບໍ່ຕ້ອງເພີ່ມ Errors ອີກຊັ້ນຫຼັງ ValidateSignature. ກວດ HTTP 401/403/500 ຈິງດ້ວຍ. ຕັ້ງ web-server, reverse proxy, CDN, analytics ແລະ tracing ໃຫ້ບໍ່ເກັບ raw query ຂອງ signed routes; application request logger ບໍ່ເກັບ URL ແຕ່ບໍ່ຄວບຄຸມ access logs ຊັ້ນອື່ນ. ຢ່າໃສ່ secret ຫຼືຂໍ້ມູນສ່ວນຕົວໃນ URL; ລິ້ງອາດຄ້າງໃນ browser history, bookmarks ຫຼືຂໍ້ຄວາມທີ່ຖືກສົ່ງຕໍ່. ### 7. ທົດສອບກ່ອນເປີດ ທົດສອບ origin/method/header ທີ່ອະນຸຍາດແລະປະຕິເສດ, cache Vary, CSRF, tampering, expiry, wrong origin/purpose ແລະການປົນ request ໃນ worker. HTTP loopback ຕ້ອງເປີດ allowHttpLoopback ເພື່ອ local test ເທົ່ານັ້ນ; production ໃຊ້ HTTPS. ## ຫຼາຍພາສາ ແລະກວດ input ຊັດເຈນ. ກຳນົດ locale ຕໍ່ request ແລະຮັບພຽງຂໍ້ມູນທີ່ຜ່ານ schema. ### 1. Catalogues ທີ່ບໍ່ປ່ຽນ state Translator ເກັບ catalogue ແບບ immutable ແລະຮັບ locale ໃນທຸກ trans call. ບໍ່ໃຊ້ setlocale ຫຼືປ່ຽນ global locale, ຈຶ່ງບໍ່ປົນພາສາລະຫວ່າງ request ທີ່ໃຊ້ worker ດຽວກັນ. ເລືອກ locale ຈາກ allowlist ຂອງແອັບ; unknown locale ຈະ throw. ```text use Icom\Translation\Translator; $t = new Translator([ 'en' => ['greeting' => 'Hello, {name}!'], 'lo' => ['greeting' => 'ສະບາຍດີ {name}!'], ], fallback: 'en'); $message = $t->trans('greeting', 'lo', ['name' => 'ນັກພັດທະນາ']); // In an HTML template, escape this text with $e($message). ``` ### 2. Fallback ແລະ escaping ຖ້າ key ບໍ່ມີໃນ locale ທີ່ເລືອກ ຈະອ່ານ fallback; ຖ້າຍັງບໍ່ມີ ຈະຄືນ key. {name} ຖືກແທນຄ່າຄັ້ງດຽວ ແລະຜົນເປັນ plain text. ຕ້ອງ escape ຕາມ context: $e ສຳລັບ HTML ຫຼື JSON encoder ສຳລັບ JSON. ບໍ່ມີ ICU/plural/date-number formatting ຫຼື dynamic translation-file loader. ### 3. Rules ເພີ່ມເຕີມ ເພີ່ມ array, list, uuid, date:YYYY-MM-DD, confirmed, same:field, different:field, present. min/max ນັບສະມາຊິກໃນ array; integer/boolean ບໍ່ cast ຈາກ string. UUID ແມ່ນ canonical hyphenated RFC9562 versions1–8 variant10xx; nil/max ບໍ່ຜ່ານ. Date ກວດປະຕິທິນ Gregorian ຈິງ years0001–9999. ```text use Icom\Validation\Validator; use Icom\Http\Problem; $result = (new Validator())->validate($input, [ 'id' => 'required|uuid', 'starts_on' => 'required|date:YYYY-MM-DD', 'tags' => 'required|array|list|min:1|max:10', 'password' => 'required|string|min:12|confirmed', 'previous_id' => 'present|nullable|uuid|different:id', ]); if (!$result['valid']) { return Problem::response(422, 'Please check the submitted fields.', $result['errors']); } $validated = $result['data']; // Authorize before persisting; validate each nested tag value separately. // Hash passwords through the account service; never persist them as plain text. // password_confirmation is not returned unless it has its own schema entry. ``` ### 4. Schema ແລະ nested data present ຕ້ອງມີ key; null ຕ້ອງມີ nullable. confirmed/same/different ຍັງກວດ relationship ແມ່ນແຕ່ nullable input. ຄືນພຽງ fields ທີ່ມີໃນ schema, ແຕ່ array/list ບໍ່ກວດແລະບໍ່ຕັດ nested keys ອັດຕະໂນມັດ. ກວດແຕ່ລະ nested object ດ້ວຍ schema ຂອງມັນ ແລະກຳນົດ item count ກ່ອນ loop. ບໍ່ໃຊ້ validated input ເປັນຫຼັກຖານ authorization. Malformed rule/config ຈະ throw ແມ່ນແຕ່ field ບໍ່ມີ. validate ຄືນ array {valid, data, errors}; ກວດ valid ໃຫ້ຜ່ານກ່ອນໃຊ້ data. ເມື່ອ valid=false, data ອາດມີບາງ fields ທີ່ຜ່ານ ແຕ່ຫ້າມຖືເປັນ payload ທີ່ຜ່ານທັງຊຸດ. ## API resources, errors ແລະ OpenAPI. ເລືອກ public fields ຊັດເຈນ ແລະເກັບ contract ຂອງ API ໃນ source code. ### 1. ກຳນົດ output allowlist Resource ຄືນພຽງ flat scalar/null fields ທີ່ລະບຸ. ບໍ່ serialize model/object/nested array ອັດຕະໂນມັດ. ກວດ authorization ແລະ tenant filter ກ່ອນ query; projection ບໍ່ແທນ policy. ຖ້າຕ້ອງການ nested resource ໃຫ້ສ້າງ explicit projection ແຍກ. ```text use Icom\Http\Resource; $publicUser = new Resource(['id', 'display_name']); return $publicUser->response([ 'id' => 42, 'display_name' => 'Developer', 'password_hash' => 'never exposed by this projection', ]); // {"data":{"id":42,"display_name":"Developer"}} // collection($rows, limit: 100) rejects more than the configured limit. // Use cursorPaginate to bound database reads first. ``` ### 2. ຄຳຕອບ error ທີ່ສະໝ່ຳສະເໝີ Problem::response ສ້າງ application/problem+json ຕາມ RFC9457 ກັບ type about:blank, title, status ແລະ optional detail/errors. ໃຊ້ public message ທີ່ເລືອກເອງ; ຢ່າສົ່ງ exception message, SQL, token ຫຼື raw input. ຟີເຈີນີ້ບໍ່ປ່ຽນ error response ເກົ່າທັງແອັບອັດຕະໂນມັດ. ```text use Icom\Http\Problem; return Problem::response(422, 'Please check the submitted fields.', [ 'email' => ['Enter a valid email address.'], ]); ``` [RFC9457](https://www.rfc-editor.org/rfc/rfc9457.html) ### 3. OpenAPI ຈາກ trusted metadata config/openapi.php ລະບຸພຽງ public GET /api/status ແລະ /api/hello/{name}. ເປີດ /openapi.json ເພື່ອອ່ານ OpenAPI3.1.2. ບໍ່ສະແກນ private routes, .env ຫຼື source comments ມາເຜີຍແຜ່. api:spec ສ້າງ JSON ໂດຍບໍ່ bootstrap ແອັບ; api:check bootstrap ແລ້ວກວດ method/path ທີ່ເອກະສານລະບຸ. ```text php bin/icom api:spec > openapi.json php bin/icom api:check # api:check returns nonzero when a described route is missing. # Review the JSON before publishing any additional operation. ``` [Public OpenAPI](https://framework.icom.la/openapi.json) [OpenAPI3.1.2 specification](https://spec.openapis.org/oas/v3.1.2.html) ### 4. ກຳນົດ contract ຢ່າງຊັດເຈນ OpenApi constructor ຮັບ title, version, operations, schemas ແລະ securitySchemes. Operation ຕ້ອງມີ method/path/operationId/responses/security; public ໃຊ້ security: []. ຖ້າ protected ໃຫ້ລະບຸ scheme ທີ່ປະກາດໄວ້. ລຸ່ນນີ້ຮອງຮັບ HTTP ແລະ header/cookie apiKey schemes, local schema references ເທົ່ານັ້ນ. ບໍ່ດຶງ external $ref ແລະບໍ່ປະກາດ OAuth flows ໃຫ້ອັດຕະໂນມັດ. ### 5. ສິ່ງທີ່ api:check ກວດບໍ່ໄດ້ ການມີ route ກົງເອກະສານບໍ່ພິສູດວ່າ response ທຸກອັນກົງ schema ຫຼືວ່າ authentication ຖືກຕິດຕັ້ງ. Builder ເປັນ bounded description tool, ບໍ່ແມ່ນ full JSON Schema validator/code generator. ຕ້ອງກວດ contract, auth ແລະ payload ດ້ວຍ integration tests; ໃຊ້ official schema validator ໃນ CI ຫຼັງແກ້ specification. ບໍ່ມີ Swagger UI ຫຼື remote CDN script ຖືກໂຫຼດ. ## ກຽມລະບົບເພື່ອໃຊ້ງານຈິງ. ຕິດຕັ້ງ, ກວດ configuration, ສຳຮອງ, ທົດລອງກູ້ຄືນ ແລະປ່ອຍລຸ່ນຢ່າງມີຫຼັກຖານ. ### 1. ສິ່ງທີ່ 0.10 ແກ້ໄຂ ລຸ່ນນີ້ແກ້ບັນຫາທີ່ພິສູດໄດ້: environment/boolean ພິມຜິດ, quoted config ຖືກຕັດຄ່າ, limit/order ຖືກມອງຂ້າມໃນ update/delete, logging failure ທີ່ທຳລາຍ response, CORS/signed headers ທີ່ຫາຍຕອນ error ແລະ readiness ທີ່ຮ້ອງຂໍ log directory ແມ່ນແຕ່ໃຊ້ stderr. ແກ້ Host header ໃນ SAPI/Swoole/FrankenPHP ເພື່ອໃຫ້ signed URL ເຮັດວຽກຜ່ານ HTTP ຈິງ. ເພີ່ມ config:check ແລະ SQLite backup CLI. ນີ້ເປັນ framework developer preview; ການນຳໄປໃຊ້ຕ້ອງທົດສອບ workload, business rules ແລະການດູແລຂອງແອັບທ່ານ. [Verification](https://framework.icom.la/verification.md) [Feature catalogue](https://framework.icom.la/docs/feature-catalog) ### 2. ຕິດຕັ້ງໃໝ່ ໃຊ້ PHP stable ທີ່ຮອງຮັບ ແລະ Composer lock ທີ່ກວດແລ້ວ. ຄຳສັ່ງ key:generate ໃຊ້ສຳລັບ installation ໃໝ່ທີ່ key ວ່າງເທົ່ານັ້ນ. ຖ້າ upgrade ໃຫ້ຮັກສາ key ແລະ private storage ເດີມ. ກຳນົດ document root ໃຫ້ເປັນ public/; ຢ່າເປີດໂຄງການທັງໝົດຜ່ານເວັບ. ```text composer install --no-dev --prefer-dist --no-interaction composer check-platform-reqs --no-dev cp .env.example .env php bin/icom key:generate chmod 600 .env # Edit .env privately for this installation before the production checks below. # Optional Redis/Doctrine used by your app must be production dependencies. ``` ### 3. Configuration ທີ່ຊັດເຈນ APP_ENV ຮອງຮັບ local, testing, staging, production. Staging/production ຕ້ອງ HTTPS ແລະ APP_DEBUG=false; “prod” ຈະຖືກປະຕິເສດ. APP_URL ໃຊ້ພຽງ origin ທີ່ບໍ່ມີ credentials/path/query/fragment; APP_HOSTS ຕ້ອງລວມ host ນັ້ນ ແລະບໍ່ໃຊ້ wildcard. .env ໃນ staging/production ຕ້ອງເປັນ private readable file; shared symlink ທີ່ຊີ້ໄປໄຟລ໌ 0600 ນອກ public ໃຊ້ໄດ້. Environment-only containers ບໍ່ຈຳເປັນມີ .env. ```text APP_ENV=production APP_DEBUG=false APP_URL=https://your-app.example APP_HOSTS=your-app.example # Retain APP_KEY generated for this installation. DB_DSN=sqlite:storage/app.sqlite CACHE_DRIVER=file LOG_PATH=php://stderr ``` ### 4. ຂອບເຂດການອ່ານ .env Quotes ດ້ານນອກທີ່ກົງກັນຈະຖືກຖອດພຽງໜຶ່ງຄູ່; spaces ແລະ quotes ພາຍໃນຄ່າຖືກຮັກສາ. ບໍ່ interpolate variables ຫຼື execute shell; backslash ເປັນ literal. ບໍ່ຮອງຮັບ multiline values ຫຼື inline comments. Duplicate keys ແລະ unmatched leading quotes ເປັນ error. Boolean ຮັບ true/false, yes/no, on/off, 1/0 ແບບບໍ່ແຍກຕົວນ້ອຍ/ໃຫຍ່; empty ໝາຍເຖິງ false. ຄ່າອື່ນເປັນ error. Process environment ຍັງມີລຳດັບກ່ອນ .env. ### 5. ກວດກ່ອນເປີດ traffic compatibility ກວດ PHP/extensions, config:check ກວດ application settings ໂດຍບໍ່ bootstrap ແອັບ ຫຼືເຊື່ອມ DB/cache. --production ບັງຄັບ APP_ENV=production. Exit 0 ຄືຜ່ານ, 1 ຄື config ບໍ່ຜ່ານ, 2 ຄື arguments ບໍ່ຖືກ. Output ບໍ່ມີ key, DSN, credentials ຫຼື private path. ການຜ່ານ config ບໍ່ຢືນຢັນເຊື່ອມບໍລິການໄດ້; ຈຶ່ງຕ້ອງກວດ operations ຕໍ່. ```text php bin/compatibility.php --production --pdo=sqlite php bin/icom config:check --production php bin/icom migrate:status # Fresh installations have pending migrations: review then run migrate. # Existing installations need a verified backup first. php bin/icom migrate php bin/icom maintenance:run php bin/icom ops:check php bin/icom api:check ``` ### 6. Storage/logging ຕ້ອງກົງ deployment LOG_PATH=php://stderr ໃຊ້ container/platform logging; readiness ບໍ່ຮ້ອງຂໍ storage/logs ໃນກໍລະນີນີ້. ຖ້າໃຊ້ log file ໃຫ້ກຽມ private writable parent directory ນອກ public/ ແລະຕັ້ງ rotation. Database/log path ບໍ່ຮັບ device, FIFO, stream wrappers ຫຼື public aliases. Default file cache/rate limits ຍັງຕ້ອງ persistent writable storage. Logging outage ບໍ່ປ່ຽນ response ທີ່ເຮັດສຳເລັດແລ້ວ; ມີພຽງ fixed fallback diagnostic. ຜູ້ດູແລຍັງຕ້ອງແຈ້ງເຕືອນກ່ຽວກັບ disk/log collector. ### 7. ສຳຮອງ SQLite ທີ່ກຳລັງໃຊ້ backup:create ໃຊ້ VACUUM INTO ເພື່ອໄດ້ snapshot ທີ່ລວມ committed WAL data, ກວດ integrity/foreign keys, sync ແລະ publish ແບບບໍ່ overwrite. ຕ້ອງເປັນ file-backed SQLite main database, ບໍ່ຢູ່ outer transaction ຫຼືມີ attached databases. ຕ້ອງມີ disk ແລະເວລາພຽງພໍ; backup ອາດມີ I/O ສູງ. ```text install -d -m 700 /private/icom-backups php bin/icom backup:create --output=/private/icom-backups/release-0.10.sqlite php bin/icom backup:verify /private/icom-backups/release-0.10.sqlite # Existing destinations are refused; use a new name for every snapshot. # Keep the backup outside every web document root. ``` [SQLite VACUUM INTO](https://www.sqlite.org/lang_vacuum.html) ### 8. Backup verification ບໍ່ແມ່ນ restore ຄົບລະບົບ backup:verify ບໍ່ bootstrap ແອັບ; ເປີດ snapshot ແບບ read-only ພ້ອມ SQLite locking ແລະກວດ SHA-256/schema/integrity/foreign keys. ໃຊ້ trusted standalone artifact ທີ່ມີ parent0700/file0600; WAL-format/sidecars ຖືກປະຕິເສດ. Hash ບໍ່ຢືນຢັນຜູ້ສ້າງ. ຟີເຈີນີ້ໃຊ້ local POSIX filesystem ທີ່ຮອງຮັບ hard links/fsync; ບໍ່ແມ່ນ MySQL backup ຫຼື cloud backup. ຖ້າ sync ຫຼັງ publish ລົ້ມເຫຼວ file ທີ່ກວດແລ້ວຈະຍັງຢູ່: ກວດ file ກ່ອນລອງຊື່ໃໝ່. ### 9. ທົດລອງກູ້ຄືນກ່ອນຕ້ອງໃຊ້ຈິງ ເກັບ APP_KEY/.env, uploaded files ແລະ code release ແຍກໄວ້ຢ່າງປອດໄພ; database backup ຢ່າງດຽວບໍ່ສາມາດຖອດລະຫັດ MFA ໄດ້ຖ້າຂາດ key. ຄືນ snapshot ໃສ່ private directory ໃໝ່ໃນ staging ທີ່ປິດບໍລິການສົ່ງຂໍ້ມູນພາຍນອກ. ກວດ migration status, login/MFA, resource ownership ແລະ queued jobs ກັບ key/release ທີ່ກົງກັນ. ກ່ອນ restore production ຕ້ອງຢຸດ traffic, workers ແລະ framework scheduler ທີ່ອາດຂຽນ DB, ເກັບສະພາບກ່ອນກູ້ຄືນ ແລະສະຫຼັບໄປໄຟລ໌ໃໝ່. ຢ່າ overwrite database ທີ່ຍັງມີ connection ເປີດ; ບໍ່ມີ auto-restore CLI ທີ່ຂຽນທັບ live DB. Snapshot ຈະຄືນ sessions, recovery codes ແລະ jobs ໄປສະຖານະເວລາສຳຮອງ: ຕ້ອງທົບທວນການຍົກເລີກສິດຫຼັງ backup ແລະຜົນຂອງ jobs ທີ່ສົ່ງໄປລະບົບພາຍນອກແລ້ວ. ການທົດສອບ 0.10 ຜ່ານ 73 ຈຸດກວດ ດ້ວຍຂໍ້ມູນຈຳລອງ, HTTPS, MFA ແລະ queue; ບໍ່ແມ່ນການຮັບຮອງ disaster recovery ຂອງແອັບທ່ານ. ### 10. ການປ່ຽນແປງທີ່ແອັບຕ້ອງກວດ update/delete ທີ່ມີ limit/orderBy ຈະ throw ກ່ອນຂຽນ SQL. ເລືອກ IDs ແບບມີຂອບເຂດ ແລ້ວຂຽນດ້ວຍ explicit unique ID, tenant ແລະ optimistic version/state ຕາມວຽກ; ກວດ row count ແລະ conflict. ຢ່າລຶບ limit ອອກພຽງເພື່ອໃຫ້ error ຫາຍ. Gate/Identity ສຳເນົາ role/permission values ໃນຕອນສ້າງ; ການແກ້ config array ພາຍຫຼັງບໍ່ປ່ຽນສິດໃນ object ເກົ່າ. ຖ້າປ່ຽນ authorization configuration ໃຫ້ rebuild worker/app ຢ່າງຊັດເຈນ. ### 11. Error policies ແລະການປ່ອຍລຸ່ນ ໃຊ້ RequestContext → Errors → RequestGuard → optional Cors → CSRF/auth/routes. ຕິດ Cors ກ່ອນ middleware ທີ່ຕ້ອງໃຫ້ error response ມີ CORS headers; ການປະຕິເສດກ່ອນເຂົ້າ Cors ບໍ່ມີ headers ຂອງມັນ. ValidateSignature ທີ່ route ຮັກສາ no-store/no-referrer ທັງ known errors ແລະ unexpected errors ຜ່ານ outer Errors; ບໍ່ຕ້ອງມີ inner Errors ເພີ່ມ. ກວດ clean installation, actual runtime/dependencies, business flows, HTTPS ແລະ backup ກ່ອນສະຫຼັບ release. ຮັກສາ rollback code ແລະຮູ້ວ່າ code rollback ບໍ່ undo database writes. ### 12. ການກວດທີ່ຍັງຕ້ອງມີຕາມລະບົບຈິງ ຕ້ອງກວດ capacity, long-running memory, actual DB topology/failover, trusted proxy handling, external OIDC provider, notification delivery, independent security assessment ແລະ off-site restore ຕາມ deployment ຈິງ. Docker/Kubernetes files ເປັນ references; ການທົດສອບ fresh-storage behavior ບໍ່ແມ່ນຫຼັກຖານວ່າ cluster ຂອງທ່ານຜ່ານແລ້ວ. ບໍ່ມີ default account, ບໍ່ສົ່ງ email ຫຼືເປີດບໍລິການພາຍນອກອັດຕະໂນມັດ.