citomni/infrastructure
Composer 安装命令:
composer require citomni/infrastructure
包简介
Lean, cross-mode infrastructure for CitOmni apps: DB, logging, text/i18n, mail, cURL, brute-force protection, and optional contact routes.
关键字:
README 文档
README
Lean, cross-mode infrastructure for CitOmni apps. Predictable service maps, deterministic config (last-wins), no magic. Ultra-fast PHP 8.2+, side-effect free, designed for HTTP and CLI runtimes. ♻️
Highlights
- Shared services available in both HTTP & CLI (
db,log,txt,mailer) - Deterministic boot -> vendor baseline -> providers -> app (last wins)
- No scanning ->
$this->app->{id}resolves instantly (cacheable maps) - Prod-friendly -> config/service maps can be precompiled by the App
- Infrastructure focus -> DB (LiteMySQLi), logging, mail (PHPMailer), text/i18n
Requirements
-
PHP 8.2+
-
Extensions:
ext-json(standard)ext-iconvorext-mbstring(mailer UTF-8 normalization; one of them is used)ext-gd(required for the optional/captcharoute)- Freetype (optional) enables TTF text in captcha (falls back to bitmap fonts if missing)
-
OPcache recommended in production
Install
composer require citomni/infrastructure composer dump-autoload -o
Ensure your app is PSR-4 mapped:
{
"autoload": { "psr-4": { "App\\": "src/" } }
}
Enable the provider in /config/providers.php:
<?php return [ \CitOmni\Infrastructure\Boot\Services::class, ];
Services (exported IDs)
This package contributes a baseline service map (app can override in /config/services.php):
| id | class | purpose |
|---|---|---|
db |
CitOmni\Infrastructure\Service\Db |
LiteMySQLi wrapper (lazy connect) |
log |
CitOmni\Infrastructure\Service\Log |
LiteLog (JSONL etc., with rotate) |
txt |
CitOmni\Infrastructure\Service\Txt |
Static text/i18n loader (LiteTxt) |
mailer |
CitOmni\Infrastructure\Service\Mailer |
PHPMailer wrapper (+ logging) |
Constructor contract (all services)
__construct(\CitOmni\Kernel\App $app, array $options = [])
Usage:
// DB $id = $this->app->db->insert('crm_msg', ['msg_subject' => 'Hi']); $row = $this->app->db->fetchRow('SELECT * FROM crm_msg WHERE id=?', [$id]); // Logging $this->app->log->write('orders.jsonl', 'order.create', ['id'=>$id,'total'=>$total]); // Text (i18n) $this->app->txt->get('err_invalid_email', 'contact', 'citomni/infrastructure', 'Invalid.'); // Mail $this->app->mailer ->to('user@example.com') ->subject('Welcome, {name}') ->templateVars(['name' => 'Sarah']) ->body('<p>Hello {name}</p>', true) ->send();
Configuration (last wins)
At runtime the App builds config as:
- Vendor infrastructure baseline
\CitOmni\Infrastructure\Boot\Services::CFG_HTTP(andCFG_CLI) - Provider CFGs (if any) listed in
/config/providers.php - App base cfg:
/config/citomni_http_cfg.phpor/config/citomni_cli_cfg.php - App env overlay:
/config/citomni_{http|cli}_cfg.{env}.php(optional)
Merge rules: Associative arrays are deep-merged (last wins). Numeric lists are replaced by the last source.
Important keys used by this package
'db' => [ 'host' => 'localhost', 'user' => 'root', 'pass' => '', 'name' => 'citomni', 'charset' => 'utf8mb4', ], 'log' => [ 'path' => CITOMNI_APP_PATH . '/var/logs', 'default_file' => 'citomni_app.log', 'max_bytes' => 2_000_000, 'max_files' => 10, // null = unlimited ], 'txt' => [ 'log' => [ 'file' => 'litetxt_errors.jsonl', 'path' => CITOMNI_APP_PATH . '/var/logs', ], ], 'mail' => [ 'from' => ['email' => '', 'name' => ''], 'reply_to' => ['email' => '', 'name' => ''], 'format' => 'html', // 'html' | 'text' 'transport' => 'smtp', // 'smtp' | 'mail' | 'sendmail' | 'qmail' // 'sendmail_path' => '/usr/sbin/sendmail', 'smtp' => [ 'host' => '', 'port' => 587, 'encryption' => null, // 'tls' | 'ssl' | null 'auth' => true, 'username' => '', 'password' => '', 'auto_tls' => true, 'timeout' => 15, 'keepalive' => false, ], 'logging' => [ 'log_success' => false, // dev aid 'debug_transcript' => false, 'max_lines' => 200, 'include_bodies' => false, // keep false in prod ], ], 'security' => [ 'csrf_protection' => true, 'csrf_field_name' => 'csrf_token', 'captcha_protection' => true, 'honeypot_protection' => true, 'form_action_switching'=> true, ], 'routes' => [ '/kontakt.html' => [ 'controller' => \CitOmni\Infrastructure\Controller\InfrastructureController::class, 'action' => 'contact', 'methods' => ['GET','POST'], 'template_file' => 'public/contact.html', 'template_layer' => 'citomni/infrastructure', ], '/captcha' => [ 'controller' => \CitOmni\Infrastructure\Controller\InfrastructureController::class, 'action' => 'captcha', 'methods' => ['GET'], ], ],
The HTTP router reads routes as raw arrays (
$this->app->cfg->routes[...]).
DB service (db)
Thin wrapper around LiteMySQLi with lazy connection and ergonomic __call() pass-through:
$id = $this->app->db->insert('crm_msg', ['msg_subject' => 'Hi']); $row = $this->app->db->fetchRow('SELECT * FROM crm_msg WHERE id=?', [$id]);
For models, you can extend CitOmni\Infrastructure\Model\BaseModelLiteMySQLi and access $this->db.
Logging (log)
Backed by LiteLog:
$this->app->log->write('order.jsonl', 'order.create', ['id'=>$id,'total'=>$total]);
Rotation controlled by log.max_bytes and log.max_files. Directory defaults to var/logs.
Text / i18n (txt)
Static text loader via LiteTxt, with layered paths:
$this->app->txt->get($key, $file, $layer='app', $default='', $vars=[]);
layer='app'->CITOMNI_APP_PATH/language/{lang}/{file}.phplayer='vendor/package'->CITOMNI_APP_PATH/vendor/{layer}/language/{lang}/{file}.php- Language comes from
cfg['locale']['language']('da','da_DK', etc.) - Placeholders:
%UPPER_CASE%-> replaced from$vars(e.g.%APP_NAME%)
Errors go to txt.log.file (default litetxt_errors.jsonl).
Mailer (mailer)
PHPMailer wrapper with sensible defaults:
$this->app->mailer ->from('system@example.com', 'CitOmni') ->to(['john@example.com','jane@example.com']) ->subject('Welcome, {name}') ->templateVars(['name' => 'Sarah']) ->body('<p>Hello {name}</p>', true) ->send();
-
Transport:
smtp,mail,sendmail,qmail(from cfg) -
Default From/Reply-To read from cfg
-
Templating:
{var}placeholders (mailer-only) viatemplateVars() -
Auto-generates
AltBodyfrom HTML if you don't set it -
Logging:
- Success (dev-friendly):
mail_log.jsonwhenmail.logging.log_success=true - Errors:
mailer_errors.jsonwith optional SMTP transcript (debug_transcript)
- Success (dev-friendly):
Contact form (optional)
If you keep the provided routes:
GET|POST /kontakt.html-> validates, stores in DB (crm_msg), emails app recipientGET /captcha-> returns a PNG captcha usingext-gdFonts (optional) read fromvendor/citomni/infrastructure/assets/fonts/*.ttf
Security interplay: honors security.csrf_protection, captcha_protection, and honeypot_protection.
Recipient: cfg['identity']['email'] (fallback: cfg['mail']['from']['email']).
If you plan to use the contact form routes, import the schema now (see Database schema below).
Database schema
This package ships a ready-to-apply SQL schema for the contact form model:
- File:
vendor/citomni/infrastructure/sql/crm_msg.sqlCreates tablecrm_msg(InnoDB,utf8mb4_unicode_ci, PKidauto-increment). Works on MySQL 8+ / MariaDB 10.4+.
Option A — Manual import (recommended)
Use your preferred tool:
MySQL CLI
mysql -u <user> -p <database> < vendor/citomni/infrastructure/sql/crm_msg.sql
phpMyAdmin / Adminer
- Open your database
- Import the file:
vendor/citomni/infrastructure/sql/crm_msg.sql
Option B — Code-based, one-off installer (idempotent)
If you prefer to install via code, run once during setup/deploy:
<?php declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; define('CITOMNI_ENVIRONMENT', 'cli'); define('CITOMNI_APP_PATH', __DIR__); $app = new \CitOmni\Kernel\App(__DIR__ . '/config', \CitOmni\Kernel\Mode::CLI); $sql = (string)\file_get_contents(__DIR__ . '/vendor/citomni/infrastructure/sql/crm_msg.sql'); $app->db->execute($sql); echo "crm_msg installed.\n";
Keep this script out of web-root; run it once, then delete it. The
Dbservice must haveCREATEprivileges, otherwise use Option A.
Notes
- The
CrmMessageModelexpects the table namecrm_msgand the columns defined in the SQL file. - You can add indexes later to fit your reporting needs (e.g.,
msg_added_dt,msg_from_email).
Why no auto-migrate?
CitOmni packages are side-effect free by design. Vendor code should not create or alter your database automatically. That keeps the runtime predictable, reviewable, and safe across environments.
Why this policy exists
- Determinism & reviewability – DB changes live in your app/ops repos, not hidden in vendor code.
- Least privilege – production credentials often lack
CREATE/ALTER; installs shouldn’t assume elevated rights. - Safer deploys – no surprise schema writes that can fail under load, lock tables, or break blue/green rollouts.
- Compliance & audit – schema changes pass through your change-management and CI/CD, with diffs and approvals.
- Multi-env parity – staging/prod may be managed by DBAs; the package must work without mutating state.
What to do instead
- Use the provided SQL once (see Database schema above), or
- Maintain app-owned migrations (idempotent SQL,
IF NOT EXISTS, transactional where possible), executed by your deploy pipeline or a CLI command in your app. - Track schema with a simple
schema_versiontable (or your existing migration tool).
This keeps the infrastructure package stateless, while your application controls when and how the database evolves.
Performance tips
-
Composer:
{ "config": { "optimize-autoloader": true, "classmap-authoritative": true, "apcu-autoloader": true } }Then:
composer dump-autoload -o -
OPcache (prod):
opcache.enable=1 opcache.validate_timestamps=0 opcache.revalidate_path=0 opcache.save_comments=0 realpath_cache_size=4096k realpath_cache_ttl=600
Contributing
- PHP 8.2+, PSR-4, tabs, K&R braces
- Keep vendor files side-effect free (OPcache-friendly)
- Don't swallow exceptions in core; let the global error handler log
Coding & Documentation Conventions
All CitOmni projects follow the shared conventions documented here:
CitOmni Coding & Documentation Conventions
License
CitOmni Infrastructure is open-source under the MIT License.
See: LICENSE.
Trademark notice: "CitOmni" and the CitOmni logo are trademarks of Lars Grove Mortensen.
You may not use the CitOmni name or logo to imply endorsement or affiliation without prior written permission.
Trademarks
"CitOmni" and the CitOmni logo are trademarks of Lars Grove Mortensen.
You may make factual references to "CitOmni", but do not modify the marks, create confusingly similar logos,
or imply sponsorship, endorsement, or affiliation without prior written permission.
Do not register or use "citomni" (or confusingly similar terms) in company names, domains, social handles, or top-level vendor/package names.
For details, see the project's NOTICE.
Author
Developed by Lars Grove Mortensen © 2012-present Contributions and pull requests are welcome!
Built with ❤️ on the CitOmni philosophy: low overhead, high performance, and ready for anything.
citomni/infrastructure 适用场景与选型建议
citomni/infrastructure 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 10 月 03 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「logging」 「mailer」 「framework」 「database」 「php」 「curl」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 citomni/infrastructure 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 citomni/infrastructure 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 citomni/infrastructure 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
PHP Framework HLEB2 is the foundation of the web application. Provides ease of development and application performance.
A Zend Framework module that sets up Monolog for logging in applications.
Creates new sare mail transport for laravel applications
Asynchronous Sentry for Symfony - Fire and forget
Stackdriver handler for Monolog (codeinternetapplications/monolog-stackdriver Fork).
High-performance, zero-dependency PSR-3 logger for MonkeysLegion with structured logging, handlers, processors, and PHP 8.4 features.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 31
- 依赖项目数: 2
- 推荐数: 5
其他信息
- 授权协议: MIT
- 更新时间: 2025-10-03