Releases: gemvc/gemvc
new ORM methods whereIn() and whereNotIn()
Full Changelog: 5.7.1...5.8.0
GEMVC Framework - Release Notes
Version 5.8.0 - Table fluent API: whereIn and whereNotIn
Release Date: 04.juni.2026
Type: Minor Release (Backward Compatible)
Tag: 5.8.0
📋 Overview
This release adds whereIn() and whereNotIn() to the Table fluent query builder, matching capabilities already available on Gemvc\Database\Query\WhereTrait (Select/Update/Delete query objects).
🔧 Changes
Gemvc\Database\Table
whereIn(string $column, array $values): self— boundIN (...)clause; empty$valuesadds no condition.whereNotIn(string $column, array $values): self— boundNOT IN (...)clause; same empty-array behavior.- Parameter names use
str_replace('.', '_', $column)for qualified columns (e.g.users.role_id). - Suffix from
_arr_wherecount avoids bind collisions when chaining multiple IN/NOT IN clauses.
Documentation
- Updated
AI_API_REFERENCE.md,AI_CONTEXT.md,GEMVC_PHPDOC_REFERENCE.php, andgemvc-api-reference.jsonc.
🎯 Benefits
- ✅ Parity between
Tablefluent selects and standalone QueryBuilder - ✅ Prepared statements for all IN list values (no string concatenation of user data)
- ✅ Predictable chaining with existing
whereEqual,whereLike, joins, etc.
🔄 Migration Guide
From 5.7.1 to 5.8.0
This release is fully backward compatible.
Example:
$rows = $this->select()
->whereIn('status', ['active', 'pending'])
->whereNotIn('id', [10, 20, 30])
->run();Breaking Changes: None
Version 5.7.1 - TableGenerator type mapping accuracy improvements
Release Date: 30.mai.2026
Type: Patch Release (Backward Compatible)
Tag: 5.7.1
📋 Overview
This patch release improves SQL type generation accuracy in TableGenerator by correctly handling nullable mapped PHP types and by preventing unintended _id coercion for non-integer IDs.
🔧 Changes
TableGenerator::mapTypeToSqlType()
- Nullable mapped types now normalize before matching (e.g.,
?string->string,?int->int). _idsuffix columns are forced toINT(11)only when the PHP/base type isintorinteger.- Non-integer
_idfields (e.g., UUID/external identifiers) preserve their declared string mapping.
🎯 Benefits
- ✅ Correct schema mapping for nullable types (
?stringno longer falls back toTEXT) - ✅ Safer data integrity for non-integer IDs (no unintended cast to
INT) - ✅ Backward-compatible behavior for classic integer foreign keys
🔄 Migration Guide
From 5.7.0 to 5.7.1
This release is fully backward compatible.
What you should do:
- Run
composer updateto pullgemvc/library5.7.1. - Re-run table generation/migrations if you rely on nullable mapped types or string-based
_idcolumns.
Breaking Changes: None
Version 5.7.0 - CLI foundation extracted to gemvc/cli-base
Release Date: 18.05.2026
Type: Minor Release (Backward Compatible)
Tag: 5.7.0
📋 Overview
This release moves shared CLI infrastructure into the Composer package gemvc/cli-base (^1.0.1). The framework library keeps framework-specific commands (init, db:*, Docker wizards, templates) while terminal I/O, filesystem helpers, and codegen abstract bases live in the dedicated package.
Install / upgrade:
composer require gemvc/library:^5.7 --with-all-dependencies🔧 Changes
New dependency: gemvc/cli-base
In cli-base (Gemvc\CLI\) |
Stays in library (src/CLI/) |
|---|---|
Command, CliColor, CliLine |
AbstractInit, InitProject, InitApache, InitSwoole, … |
FileSystemManager |
DockerComposeInit, DockerContainerBuilder |
Commands\CliBoxShow |
All concrete db:*, create:*, admin commands |
Commands\AbstractBaseGenerator, AbstractBaseCrudGenerator |
InstallationTest (framework install smoke checks) |
InstallControl (package install verification) |
templates/cli/, CommandCategories |
CLI output
- Colored output uses the
CliColorenum (write($message, CliColor::Blue)), not string color names. CliBoxShow/CliLineused for boxed output (e.g.db:describe, init wizards).- Blue accents instead of cyan for reliable rendering on macOS Terminal.
PHPStan (library repo)
- Removed
phpstan-tests.neon; analysis targetssrc/only viaphpstan.neon. - Added Composer script:
composer phpstan.
Packaging (cli-base 1.0.1)
.gitattributesexport-ignore—tests/and dev files are no longer shipped in Composer installs ofgemvc/cli-base.
🎯 Benefits
- ✅ Smaller, clearer CLI layer in the main library
- ✅ Reusable CLI foundation for future GEMVC packages
- ✅ Dedicated tests and docs in
gemvc/cli-base(AI-Assistant.md, PHPUnit) - ✅ Same
gemvcbinary and commands for end users
🔄 Migration Guide
From 5.6.7 to 5.7.0
This release is backward compatible for application code (app/api, app/controller, etc.).
What changed:
- Shared CLI classes now come from
gemvc/cli-base(Composer dependency). - Duplicate copies removed from
src/CLI/in the library. - CLI colors use
CliColorenum inwrite()(not string color names).
What you should do:
- Run
composer updateto pullgemvc/library5.7.0 andgemvc/cli-base^1.0.1. - Custom CLI commands: extend
Gemvc\CLI\Command; useCliColor, not'green'/'cyan'strings. - AI assistants:
vendor/gemvc/cli-base/AI-Assistant.md+ CLI.md.
Breaking Changes: None for app/ code. Internal library CLI duplicates removed (provided by vendor).
Requires: gemvc/cli-base ^1.0.1
Minimum PHP Version: 8.2+
Version 5.6.7 - PHP 8.5 Compatibility & CLI Terminal Colors
Full Changelog (5.6.6…5.6.7): 5.6.6...5.6.7
Release Date: 2026-05-17
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release removes PHP 8.5 deprecation warnings for MySQL PDO init-command attributes and improves CLI colored output on macOS Terminal by using blue instead of cyan. No API or configuration changes are required.
🔧 Changes
PHP 8.5 – PDO MySQL init command attribute
- Deprecation fix: Driver-specific
PDO::MYSQL_ATTR_INIT_COMMANDis deprecated in PHP 8.5 in favor ofPdo\Mysql::ATTR_INIT_COMMAND. - Implementation: Use
Pdo\Mysql::ATTR_INIT_COMMANDwhen running on PHP 8.5+ and the class exists; otherwise fall back toPDO::MYSQL_ATTR_INIT_COMMAND. - Locations:
src/CLI/commands/DbConnect.php–connect(),connectAsRoot()(and duplicate undercommands/commands/)src/core/Developer/DeveloperTable.php– root connection forCREATE DATABASE
CLI – Terminal colors (macOS / cross-platform)
- Problem: macOS Terminal does not render cyan ANSI codes reliably; prompts and
db:describetable borders could appear wrong or invisible. - Solution: Use blue (
\033[34m/\033[1;34m) instead of cyan across CLI output. Command.php:write()supportsblue;cyanis an alias mapping to the same blue code for backward compatibility.- Updated commands: Init wizards, Docker setup,
db:describe,db:list, and related duplicate command files.
🎯 Benefits
- ✅ PHP 8.5 ready – No deprecation noise from CLI or Developer database setup
- ✅ Better CLI UX on Mac – Readable colors on macOS Terminal, Windows, and Linux
- ✅ Backward compatible – PHP 8.2–8.4 unchanged; no migration steps
🔄 Migration Guide
From 5.6.6 to 5.6.7
This release is fully backward compatible. No action required.
What Changed:
- PDO MySQL connection options in CLI
DbConnectandDeveloperTable - CLI ANSI accent color from cyan to blue
Breaking Changes: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+ (8.5 supported)
For detailed changes, see CHANGELOG.md.
Version 5.6.6 - Security Hardening & Path Normalization
Release Date: 2026-02-18
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release hardens the framework's security by implementing strict path normalization in SecurityManager to prevent access rule bypasses. It also improves input sanitization and request body handling in ApacheRequest (fixing empty body issues with PUT/PATCH) and sanitizes request URIs in SwooleRequest.
🔒 Security & Changes
SecurityManager – Path Normalization
- Path access rules enforcement:
- Normalizes request paths before checking blocked paths/extensions.
- Collapses multiple slashes (e.g.
//app→/app). - Decodes URL-encoded segments once (e.g.
%2fapp,%2e%2e) before comparison. - Resolves
.and..segments to prevent path traversal (e.g./api/../app→/app). - Benefit: Prevents bypassing security rules via obfuscated paths.
- Location:
src/core/SecurityManager.php
ApacheRequest – Input Hardening
- Stream Handling: Reads
php://inputonce per request and reuses it for JSON POST, PUT, and PATCH.- Fixes issues where PUT/PATCH streams could be empty if read multiple times.
- Sanitization:
sanitizeInput()returns empty string instead offalsewhen filter fails.- `sanitizeRequestURI()...
5.7.1 - TableGenerator type mapping accuracy improvements
Full Changelog: 5.7.0...5.7.1
GEMVC Framework - Release Notes
Version 5.7.1 - TableGenerator type mapping accuracy improvements
Release Date: 30.mai.2026
Type: Patch Release (Backward Compatible)
Tag: 5.7.1
📋 Overview
This patch release improves SQL type generation accuracy in TableGenerator by correctly handling nullable mapped PHP types and by preventing unintended _id coercion for non-integer IDs.
🔧 Changes
TableGenerator::mapTypeToSqlType()
- Nullable mapped types now normalize before matching (e.g.,
?string->string,?int->int). _idsuffix columns are forced toINT(11)only when the PHP/base type isintorinteger.- Non-integer
_idfields (e.g., UUID/external identifiers) preserve their declared string mapping.
🎯 Benefits
- ✅ Correct schema mapping for nullable types (
?stringno longer falls back toTEXT) - ✅ Safer data integrity for non-integer IDs (no unintended cast to
INT) - ✅ Backward-compatible behavior for classic integer foreign keys
🔄 Migration Guide
From 5.7.0 to 5.7.1
This release is fully backward compatible.
What you should do:
- Run
composer updateto pullgemvc/library5.7.1. - Re-run table generation/migrations if you rely on nullable mapped types or string-based
_idcolumns.
Breaking Changes: None
Version 5.7.0 - CLI foundation extracted
Full Changelog: 5.6.7...5.7.0
GEMVC Framework - Release Notes
Version 5.7.0 - CLI foundation extracted to gemvc/cli-base
Release Date: 18.05.2026
Type: Minor Release (Backward Compatible)
Tag: 5.7.0
📋 Overview
This release moves shared CLI infrastructure into the Composer package gemvc/cli-base (^1.0.1). The framework library keeps framework-specific commands (init, db:*, Docker wizards, templates) while terminal I/O, filesystem helpers, and codegen abstract bases live in the dedicated package.
Install / upgrade:
composer require gemvc/library:^5.7 --with-all-dependencies🔧 Changes
New dependency: gemvc/cli-base
In cli-base (Gemvc\CLI\) |
Stays in library (src/CLI/) |
|---|---|
Command, CliColor, CliLine |
AbstractInit, InitProject, InitApache, InitSwoole, … |
FileSystemManager |
DockerComposeInit, DockerContainerBuilder |
Commands\CliBoxShow |
All concrete db:*, create:*, admin commands |
Commands\AbstractBaseGenerator, AbstractBaseCrudGenerator |
InstallationTest (framework install smoke checks) |
InstallControl (package install verification) |
templates/cli/, CommandCategories |
CLI output
- Colored output uses the
CliColorenum (write($message, CliColor::Blue)), not string color names. CliBoxShow/CliLineused for boxed output (e.g.db:describe, init wizards).- Blue accents instead of cyan for reliable rendering on macOS Terminal.
PHPStan (library repo)
- Removed
phpstan-tests.neon; analysis targetssrc/only viaphpstan.neon. - Added Composer script:
composer phpstan.
Packaging (cli-base 1.0.1)
.gitattributesexport-ignore—tests/and dev files are no longer shipped in Composer installs ofgemvc/cli-base.
🎯 Benefits
- ✅ Smaller, clearer CLI layer in the main library
- ✅ Reusable CLI foundation for future GEMVC packages
- ✅ Dedicated tests and docs in
gemvc/cli-base(AI-Assistant.md, PHPUnit) - ✅ Same
gemvcbinary and commands for end users
🔄 Migration Guide
From 5.6.7 to 5.7.0
This release is backward compatible for application code (app/api, app/controller, etc.).
What changed:
- Shared CLI classes now come from
gemvc/cli-base(Composer dependency). - Duplicate copies removed from
src/CLI/in the library. - CLI colors use
CliColorenum inwrite()(not string color names).
What you should do:
- Run
composer updateto pullgemvc/library5.7.0 andgemvc/cli-base^1.0.1. - Custom CLI commands: extend
Gemvc\CLI\Command; useCliColor, not'green'/'cyan'strings. - AI assistants:
vendor/gemvc/cli-base/AI-Assistant.md+ CLI.md.
Breaking Changes: None for app/ code. Internal library CLI duplicates removed (provided by vendor).
Requires: gemvc/cli-base ^1.0.1
Minimum PHP Version: 8.2+
Version 5.6.7 - PHP 8.5 Compatibility & CLI Terminal Colors
Full Changelog (5.6.6…5.6.7): 5.6.6...5.6.7
Release Date: 2026-05-17
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release removes PHP 8.5 deprecation warnings for MySQL PDO init-command attributes and improves CLI colored output on macOS Terminal by using blue instead of cyan. No API or configuration changes are required.
🔧 Changes
PHP 8.5 – PDO MySQL init command attribute
- Deprecation fix: Driver-specific
PDO::MYSQL_ATTR_INIT_COMMANDis deprecated in PHP 8.5 in favor ofPdo\Mysql::ATTR_INIT_COMMAND. - Implementation: Use
Pdo\Mysql::ATTR_INIT_COMMANDwhen running on PHP 8.5+ and the class exists; otherwise fall back toPDO::MYSQL_ATTR_INIT_COMMAND. - Locations:
src/CLI/commands/DbConnect.php–connect(),connectAsRoot()(and duplicate undercommands/commands/)src/core/Developer/DeveloperTable.php– root connection forCREATE DATABASE
CLI – Terminal colors (macOS / cross-platform)
- Problem: macOS Terminal does not render cyan ANSI codes reliably; prompts and
db:describetable borders could appear wrong or invisible. - Solution: Use blue (
\033[34m/\033[1;34m) instead of cyan across CLI output. Command.php:write()supportsblue;cyanis an alias mapping to the same blue code for backward compatibility.- Updated commands: Init wizards, Docker setup,
db:describe,db:list, and related duplicate command files.
🎯 Benefits
- ✅ PHP 8.5 ready – No deprecation noise from CLI or Developer database setup
- ✅ Better CLI UX on Mac – Readable colors on macOS Terminal, Windows, and Linux
- ✅ Backward compatible – PHP 8.2–8.4 unchanged; no migration steps
🔄 Migration Guide
From 5.6.6 to 5.6.7
This release is fully backward compatible. No action required.
What Changed:
- PDO MySQL connection options in CLI
DbConnectandDeveloperTable - CLI ANSI accent color from cyan to blue
Breaking Changes: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+ (8.5 supported)
For detailed changes, see CHANGELOG.md.
Version 5.6.6 - Security Hardening & Path Normalization
Release Date: 2026-02-18
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release hardens the framework's security by implementing strict path normalization in SecurityManager to prevent access rule bypasses. It also improves input sanitization and request body handling in ApacheRequest (fixing empty body issues with PUT/PATCH) and sanitizes request URIs in SwooleRequest.
🔒 Security & Changes
SecurityManager – Path Normalization
- Path access rules enforcement:
- Normalizes request paths before checking blocked paths/extensions.
- Collapses multiple slashes (e.g.
//app→/app). - Decodes URL-encoded segments once (e.g.
%2fapp,%2e%2e) before comparison. - Resolves
.and..segments to prevent path traversal (e.g./api/../app→/app). - Benefit: Prevents bypassing security rules via obfuscated paths.
- Location:
src/core/SecurityManager.php
ApacheRequest – Input Hardening
- Stream Handling: Reads
php://inputonce per request and reuses it for JSON POST, PUT, and PATCH.- Fixes issues where PUT/PATCH streams could be empty if read multiple times.
- Sanitization:
sanitizeInput()returns empty string instead offalsewhen filter fails.sanitizeRequestURI()uses the filtered URL result when valid.sanitizeQueryString()uses empty string offalseon failure.- Recursive Sanitization: deeply nested array values in POST, GET, PUT, PATCH are fully sanitized.
- Location:
src/http/ApacheRequest.php
SwooleRequest – URI Sanitization
- Sanitization:
sanitizeRequestURI()returns the filtered URL when valid instead of the original URI. - Location:
src/http/SwooleRequest.php
🎯 Benefits
- ✅ Stronger Security: Path normalization prevents common bypass techniques (double slashes, encoding, traversal).
- ✅ Reliability: PUT/PATCH bodies are correctly parsed on Apache.
- ✅ Safety: Fail-safe defaults (empty strings) when sanitization filters fail.
- ✅ XSS Prevention: Deep recursive sanitization for all input arrays.
🔄 Migration Guide
From 5.6.5 to 5.6.6
This release is fully backward compatible. No action required.
What Changed:
- Security hardening in
SecurityManager,ApacheRequest, andSwooleRequest.
Breaking Changes: None
Version 5.6.5 - Hot Reload & ProjectHelper Refactor (Core DRY)
Release Date: 2026-02-09
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release centralizes paths and environment handling via ProjectHelper across the library core (DRY), improves hot reload so it watches only the app directory and runs with a 5-second interval in dev, and disables OPcache in development so file changes take effect without restart (Apache/Nginx and OpenSwoole). Documentation is updated to match.
🔄 Changes
Core – ProjectHelper (DRY)
- Paths – Bootstrap, SwooleBootstrap, DeveloperController, DeveloperModel, DeveloperTable, ApmModel now use:
ProjectHelper::appDir()for API service path, web 404 path, app/api, app/tableProjectHelper::getLibrarySystemPagesPath()for system pages (e.g. developer UI templates)
- Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
ProjectHelper::isDevEnvironment()for dev checksProjectHelper::getAppEnv()forAPP_ENV(e.g. developer info, APM)ProjectHelper::getBaseUrl()/getApiBaseUrl()for base URL and API base URL
- ApmModel – Single constant
APM_NOT_ENABLED_MESSAGEfor the “APM not enabled…” message (DRY).
HotReloadManager
- Scope – Watches app directory only via
ProjectHelper::appDir()(no longer watchesvendor/gemvc/library/src). - When – Starts only when
ProjectHelper::isDevEnvironment()is true. - Interval – Check interval reduced from 15 seconds to 5 seconds.
ProjectHelper – OPcache in dev
- New method –
ProjectHelper::disableOpcacheIfDev():- No-op when not in dev.
- In dev: calls
opcache_reset()andopcache_disable()when available (with@to avoid notices if O...
v5.6.7 - PHP 8.5 & macOS CLI fixes
Full Changelog: 5.6.6...5.6.7
GEMVC Framework - Release Notes
Version 5.6.7 - PHP 8.5 Compatibility & CLI Terminal Colors
Release Date: 2026-05-17
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release removes PHP 8.5 deprecation warnings for MySQL PDO init-command attributes and improves CLI colored output on macOS Terminal by using blue instead of cyan. No API or configuration changes are required.
🔧 Changes
PHP 8.5 – PDO MySQL init command attribute
- Deprecation fix: Driver-specific
PDO::MYSQL_ATTR_INIT_COMMANDis deprecated in PHP 8.5 in favor ofPdo\Mysql::ATTR_INIT_COMMAND. - Implementation: Use
Pdo\Mysql::ATTR_INIT_COMMANDwhen running on PHP 8.5+ and the class exists; otherwise fall back toPDO::MYSQL_ATTR_INIT_COMMAND. - Locations:
src/CLI/commands/DbConnect.php–connect(),connectAsRoot()(and duplicate undercommands/commands/)src/core/Developer/DeveloperTable.php– root connection forCREATE DATABASE
CLI – Terminal colors (macOS / cross-platform)
- Problem: macOS Terminal does not render cyan ANSI codes reliably; prompts and
db:describetable borders could appear wrong or invisible. - Solution: Use blue (
\033[34m/\033[1;34m) instead of cyan across CLI output. Command.php:write()supportsblue;cyanis an alias mapping to the same blue code for backward compatibility.- Updated commands: Init wizards, Docker setup,
db:describe,db:list, and related duplicate command files.
🎯 Benefits
- ✅ PHP 8.5 ready – No deprecation noise from CLI or Developer database setup
- ✅ Better CLI UX on Mac – Readable colors on macOS Terminal, Windows, and Linux
- ✅ Backward compatible – PHP 8.2–8.4 unchanged; no migration steps
🔄 Migration Guide
From 5.6.6 to 5.6.7
This release is fully backward compatible. No action required.
What Changed:
- PDO MySQL connection options in CLI
DbConnectandDeveloperTable - CLI ANSI accent color from cyan to blue
Breaking Changes: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+ (8.5 supported)
For detailed changes, see CHANGELOG.md.
Version 5.6.6 - Security Hardening & Path Normalization
Release Date: 2026-02-18
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release hardens the framework's security by implementing strict path normalization in SecurityManager to prevent access rule bypasses. It also improves input sanitization and request body handling in ApacheRequest (fixing empty body issues with PUT/PATCH) and sanitizes request URIs in SwooleRequest.
🔒 Security & Changes
SecurityManager – Path Normalization
- Path access rules enforcement:
- Normalizes request paths before checking blocked paths/extensions.
- Collapses multiple slashes (e.g.
//app→/app). - Decodes URL-encoded segments once (e.g.
%2fapp,%2e%2e) before comparison. - Resolves
.and..segments to prevent path traversal (e.g./api/../app→/app). - Benefit: Prevents bypassing security rules via obfuscated paths.
- Location:
src/core/SecurityManager.php
ApacheRequest – Input Hardening
- Stream Handling: Reads
php://inputonce per request and reuses it for JSON POST, PUT, and PATCH.- Fixes issues where PUT/PATCH streams could be empty if read multiple times.
- Sanitization:
sanitizeInput()returns empty string instead offalsewhen filter fails.sanitizeRequestURI()uses the filtered URL result when valid.sanitizeQueryString()uses empty string offalseon failure.- Recursive Sanitization: deeply nested array values in POST, GET, PUT, PATCH are fully sanitized.
- Location:
src/http/ApacheRequest.php
SwooleRequest – URI Sanitization
- Sanitization:
sanitizeRequestURI()returns the filtered URL when valid instead of the original URI. - Location:
src/http/SwooleRequest.php
🎯 Benefits
- ✅ Stronger Security: Path normalization prevents common bypass techniques (double slashes, encoding, traversal).
- ✅ Reliability: PUT/PATCH bodies are correctly parsed on Apache.
- ✅ Safety: Fail-safe defaults (empty strings) when sanitization filters fail.
- ✅ XSS Prevention: Deep recursive sanitization for all input arrays.
🔄 Migration Guide
From 5.6.5 to 5.6.6
This release is fully backward compatible. No action required.
What Changed:
- Security hardening in
SecurityManager,ApacheRequest, andSwooleRequest.
Breaking Changes: None
Version 5.6.5 - Hot Reload & ProjectHelper Refactor (Core DRY)
Release Date: 2026-02-09
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release centralizes paths and environment handling via ProjectHelper across the library core (DRY), improves hot reload so it watches only the app directory and runs with a 5-second interval in dev, and disables OPcache in development so file changes take effect without restart (Apache/Nginx and OpenSwoole). Documentation is updated to match.
🔄 Changes
Core – ProjectHelper (DRY)
- Paths – Bootstrap, SwooleBootstrap, DeveloperController, DeveloperModel, DeveloperTable, ApmModel now use:
ProjectHelper::appDir()for API service path, web 404 path, app/api, app/tableProjectHelper::getLibrarySystemPagesPath()for system pages (e.g. developer UI templates)
- Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
ProjectHelper::isDevEnvironment()for dev checksProjectHelper::getAppEnv()forAPP_ENV(e.g. developer info, APM)ProjectHelper::getBaseUrl()/getApiBaseUrl()for base URL and API base URL
- ApmModel – Single constant
APM_NOT_ENABLED_MESSAGEfor the “APM not enabled…” message (DRY).
HotReloadManager
- Scope – Watches app directory only via
ProjectHelper::appDir()(no longer watchesvendor/gemvc/library/src). - When – Starts only when
ProjectHelper::isDevEnvironment()is true. - Interval – Check interval reduced from 15 seconds to 5 seconds.
ProjectHelper – OPcache in dev
- New method –
ProjectHelper::disableOpcacheIfDev():- No-op when not in dev.
- In dev: calls
opcache_reset()andopcache_disable()when available (with@to avoid notices if OPcache is not loaded).
- Bootstrap –
Bootstrap::__construct()callsdisableOpcacheIfDev()early so each request in dev runs without OPcache. - OpenSwoole – In
workerStart, when in dev, each worker callsdisableOpcacheIfDev()so file changes are picked up without restart.
📚 Documentation
- CHANGELOG.md – Added [5.6.5] entry for core DRY, hot reload, and OPcache changes.
- ARCHITECTURE.md – Updated
HotReloadManagerandProjectHelperdescriptions to reflect app-only watch, 5s interval, anddisableOpcacheIfDev(). - CLI.md – In ProjectHelper section, added “Also used by Core” and listed:
isDevEnvironment(),getAppEnv(),getBaseUrl(),getApiBaseUrl(),getLibrarySystemPagesPath(),disableOpcacheIfDev().
🎯 Benefits
- ✅ Single source of truth – Paths and env in core come from
ProjectHelperonly. - ✅ Faster dev cycle – Hot reload watches app code only; 5s interval.
- ✅ No restart in dev – OPcache disabled in dev (Bootstrap + OpenSwoole workers) so edits take effect immediately.
- ✅ Backward compatible – No API or behavior change for existing apps.
🔒 Security
- No security vulnerabilities reported in this release.
- All existing security features maintained (90% automatic security).
🔄 Migration Guide
From 5.6.4 to 5.6.5
This release is fully backward compatible. No action required.
What changed:
- Core uses
ProjectHelperfor paths and env; hot reload is app-only with 5s interval; OPcache is disabled in dev. - Docs (CHANGELOG, ARCHITECTURE, CLI) updated to match.
Breaking changes: None
Version 5.6.3 - Dotenv Overload for Docker Compatibility
Release Date: 2026-01-29
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release fixes environment variable loading so that applications work correctly in Dockerized environments. We changed Dotenv::load() to Dotenv::overload() in the Apache entrypoint and in ProjectHelper::loadEnv(), so that .env values can override existing environment variables (e.g. set by the container). This ensures consistent behavior when the same code runs in Docker and on a host.
🔄 Changes
Apache Entrypoint (index.php)
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()- File copied to application root; now uses
overload()for Docker compatibility - Location:
src/startup/apache/index.php
- File copied to application root; now uses
ProjectHelper::loadEnv()
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()for both root and app.env- Root
.env:$dotenv->overload($rootEnvFile) - App
.env:$dotenv->overload($appEnvFile) - Location:
src/helper/ProjectHelper.php(lines 41–52)
- Root
🎯 Benefits
- ✅ Docker compatibility -
.envcan override container-provided environment variables when needed - ✅ Consistent behavior - Same loading semantics in Apache entrypoint and
ProjectHelper - ✅ No breaking change - Existing apps without pre-set env vars behave as before
🔒 Security
- No security vulnerabilities reported in thi...
5.6.6
Full Changelog: 5.6.5...5.6.6
GEMVC Framework - Release Notes
Version 5.6.6 - Security Hardening & Path Normalization
Release Date: 2026-02-18
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release hardens the framework's security by implementing strict path normalization in SecurityManager to prevent access rule bypasses. It also improves input sanitization and request body handling in ApacheRequest (fixing empty body issues with PUT/PATCH) and sanitizes request URIs in SwooleRequest.
🔒 Security & Changes
SecurityManager – Path Normalization
- Path access rules enforcement:
- Normalizes request paths before checking blocked paths/extensions.
- Collapses multiple slashes (e.g.
//app→/app). - Decodes URL-encoded segments once (e.g.
%2fapp,%2e%2e) before comparison. - Resolves
.and..segments to prevent path traversal (e.g./api/../app→/app). - Benefit: Prevents bypassing security rules via obfuscated paths.
- Location:
src/core/SecurityManager.php
ApacheRequest – Input Hardening
- Stream Handling: Reads
php://inputonce per request and reuses it for JSON POST, PUT, and PATCH.- Fixes issues where PUT/PATCH streams could be empty if read multiple times.
- Sanitization:
sanitizeInput()returns empty string instead offalsewhen filter fails.sanitizeRequestURI()uses the filtered URL result when valid.sanitizeQueryString()uses empty string offalseon failure.- Recursive Sanitization: deeply nested array values in POST, GET, PUT, PATCH are fully sanitized.
- Location:
src/http/ApacheRequest.php
SwooleRequest – URI Sanitization
- Sanitization:
sanitizeRequestURI()returns the filtered URL when valid instead of the original URI. - Location:
src/http/SwooleRequest.php
🎯 Benefits
- ✅ Stronger Security: Path normalization prevents common bypass techniques (double slashes, encoding, traversal).
- ✅ Reliability: PUT/PATCH bodies are correctly parsed on Apache.
- ✅ Safety: Fail-safe defaults (empty strings) when sanitization filters fail.
- ✅ XSS Prevention: Deep recursive sanitization for all input arrays.
🔄 Migration Guide
From 5.6.5 to 5.6.6
This release is fully backward compatible. No action required.
What Changed:
- Security hardening in
SecurityManager,ApacheRequest, andSwooleRequest.
Breaking Changes: None
Version 5.6.5 - Hot Reload & ProjectHelper Refactor (Core DRY)
Release Date: 2026-02-09
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release centralizes paths and environment handling via ProjectHelper across the library core (DRY), improves hot reload so it watches only the app directory and runs with a 5-second interval in dev, and disables OPcache in development so file changes take effect without restart (Apache/Nginx and OpenSwoole). Documentation is updated to match.
🔄 Changes
Core – ProjectHelper (DRY)
- Paths – Bootstrap, SwooleBootstrap, DeveloperController, DeveloperModel, DeveloperTable, ApmModel now use:
ProjectHelper::appDir()for API service path, web 404 path, app/api, app/tableProjectHelper::getLibrarySystemPagesPath()for system pages (e.g. developer UI templates)
- Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
ProjectHelper::isDevEnvironment()for dev checksProjectHelper::getAppEnv()forAPP_ENV(e.g. developer info, APM)ProjectHelper::getBaseUrl()/getApiBaseUrl()for base URL and API base URL
- ApmModel – Single constant
APM_NOT_ENABLED_MESSAGEfor the “APM not enabled…” message (DRY).
HotReloadManager
- Scope – Watches app directory only via
ProjectHelper::appDir()(no longer watchesvendor/gemvc/library/src). - When – Starts only when
ProjectHelper::isDevEnvironment()is true. - Interval – Check interval reduced from 15 seconds to 5 seconds.
ProjectHelper – OPcache in dev
- New method –
ProjectHelper::disableOpcacheIfDev():- No-op when not in dev.
- In dev: calls
opcache_reset()andopcache_disable()when available (with@to avoid notices if OPcache is not loaded).
- Bootstrap –
Bootstrap::__construct()callsdisableOpcacheIfDev()early so each request in dev runs without OPcache. - OpenSwoole – In
workerStart, when in dev, each worker callsdisableOpcacheIfDev()so file changes are picked up without restart.
📚 Documentation
- CHANGELOG.md – Added [5.6.5] entry for core DRY, hot reload, and OPcache changes.
- ARCHITECTURE.md – Updated
HotReloadManagerandProjectHelperdescriptions to reflect app-only watch, 5s interval, anddisableOpcacheIfDev(). - CLI.md – In ProjectHelper section, added “Also used by Core” and listed:
isDevEnvironment(),getAppEnv(),getBaseUrl(),getApiBaseUrl(),getLibrarySystemPagesPath(),disableOpcacheIfDev().
🎯 Benefits
- ✅ Single source of truth – Paths and env in core come from
ProjectHelperonly. - ✅ Faster dev cycle – Hot reload watches app code only; 5s interval.
- ✅ No restart in dev – OPcache disabled in dev (Bootstrap + OpenSwoole workers) so edits take effect immediately.
- ✅ Backward compatible – No API or behavior change for existing apps.
🔒 Security
- No security vulnerabilities reported in this release.
- All existing security features maintained (90% automatic security).
🔄 Migration Guide
From 5.6.4 to 5.6.5
This release is fully backward compatible. No action required.
What changed:
- Core uses
ProjectHelperfor paths and env; hot reload is app-only with 5s interval; OPcache is disabled in dev. - Docs (CHANGELOG, ARCHITECTURE, CLI) updated to match.
Breaking changes: None
Version 5.6.3 - Dotenv Overload for Docker Compatibility
Release Date: 2026-01-29
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release fixes environment variable loading so that applications work correctly in Dockerized environments. We changed Dotenv::load() to Dotenv::overload() in the Apache entrypoint and in ProjectHelper::loadEnv(), so that .env values can override existing environment variables (e.g. set by the container). This ensures consistent behavior when the same code runs in Docker and on a host.
🔄 Changes
Apache Entrypoint (index.php)
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()- File copied to application root; now uses
overload()for Docker compatibility - Location:
src/startup/apache/index.php
- File copied to application root; now uses
ProjectHelper::loadEnv()
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()for both root and app.env- Root
.env:$dotenv->overload($rootEnvFile) - App
.env:$dotenv->overload($appEnvFile) - Location:
src/helper/ProjectHelper.php(lines 41–52)
- Root
🎯 Benefits
- ✅ Docker compatibility -
.envcan override container-provided environment variables when needed - ✅ Consistent behavior - Same loading semantics in Apache entrypoint and
ProjectHelper - ✅ No breaking change - Existing apps without pre-set env vars behave as before
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
🔄 Migration Guide
From 5.6.2 to 5.6.3
This release is fully backward compatible. No action required.
What Changed:
- Apache
index.phpandProjectHelper::loadEnv()now useDotenv::overload()instead ofload() - Improves behavior in Dockerized deployments
Breaking Changes: None
Version 5.6.2 - APM Assignment API Improvement
Release Date: 2026-01-27
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release introduces a cleaner, more precise API for setting APM instances on the Request object. We've added a dedicated setApm() method to the Request class and updated both Bootstrap classes to use this new method instead of direct property assignment. This improvement provides better type safety, cleaner code, and a more maintainable codebase.
✨ Added
Request::setApm() Method
- New Helper Method -
setApm(\Gemvc\Core\Apm\ApmInterface $apm): void- Provides a type-safe, explicit way to set APM instance on Request object
- Replaces direct property assignment (
$request->apm = $apm) with method call - Centralizes APM assignment logic in one place
- Better for developers who want to set APM in other classes
- Location:
src/http/Request.php
Usage Example:
// Before (still works, but less precise)
$request->apm = $apmInstance;
// Now (recommended, cleaner and more precise)
$request->setApm($apmInstance);🔄 Changes
Bootstrap Classes Refactoring
Bootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Updated
recordExceptionInApm()- Fallback code also usessetApm()- Changed from:
$this->request->apm = $apm; - Changed to:
$this->request->setApm($apm);
- Changed from:
- Location:
src/core/Bootstrap.php
SwooleBootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to: `$this->requ...
- Changed from:
5.6.5
Full Changelog: 5.6.4...5.6.5
GEMVC Framework - Release Notes
Version 5.6.5 - Hot Reload & ProjectHelper Refactor (Core DRY)
Release Date: 2026-02-09
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release centralizes paths and environment handling via ProjectHelper across the library core (DRY), improves hot reload so it watches only the app directory and runs with a 5-second interval in dev, and disables OPcache in development so file changes take effect without restart (Apache/Nginx and OpenSwoole). Documentation is updated to match.
🔄 Changes
Core – ProjectHelper (DRY)
- Paths – Bootstrap, SwooleBootstrap, DeveloperController, DeveloperModel, DeveloperTable, ApmModel now use:
ProjectHelper::appDir()for API service path, web 404 path, app/api, app/tableProjectHelper::getLibrarySystemPagesPath()for system pages (e.g. developer UI templates)
- Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
ProjectHelper::isDevEnvironment()for dev checksProjectHelper::getAppEnv()forAPP_ENV(e.g. developer info, APM)ProjectHelper::getBaseUrl()/getApiBaseUrl()for base URL and API base URL
- ApmModel – Single constant
APM_NOT_ENABLED_MESSAGEfor the “APM not enabled…” message (DRY).
HotReloadManager
- Scope – Watches app directory only via
ProjectHelper::appDir()(no longer watchesvendor/gemvc/library/src). - When – Starts only when
ProjectHelper::isDevEnvironment()is true. - Interval – Check interval reduced from 15 seconds to 5 seconds.
ProjectHelper – OPcache in dev
- New method –
ProjectHelper::disableOpcacheIfDev():- No-op when not in dev.
- In dev: calls
opcache_reset()andopcache_disable()when available (with@to avoid notices if OPcache is not loaded).
- Bootstrap –
Bootstrap::__construct()callsdisableOpcacheIfDev()early so each request in dev runs without OPcache. - OpenSwoole – In
workerStart, when in dev, each worker callsdisableOpcacheIfDev()so file changes are picked up without restart.
📚 Documentation
- CHANGELOG.md – Added [5.6.5] entry for core DRY, hot reload, and OPcache changes.
- ARCHITECTURE.md – Updated
HotReloadManagerandProjectHelperdescriptions to reflect app-only watch, 5s interval, anddisableOpcacheIfDev(). - CLI.md – In ProjectHelper section, added “Also used by Core” and listed:
isDevEnvironment(),getAppEnv(),getBaseUrl(),getApiBaseUrl(),getLibrarySystemPagesPath(),disableOpcacheIfDev().
🎯 Benefits
- ✅ Single source of truth – Paths and env in core come from
ProjectHelperonly. - ✅ Faster dev cycle – Hot reload watches app code only; 5s interval.
- ✅ No restart in dev – OPcache disabled in dev (Bootstrap + OpenSwoole workers) so edits take effect immediately.
- ✅ Backward compatible – No API or behavior change for existing apps.
🔒 Security
- No security vulnerabilities reported in this release.
- All existing security features maintained (90% automatic security).
🔄 Migration Guide
From 5.6.4 to 5.6.5
This release is fully backward compatible. No action required.
What changed:
- Core uses
ProjectHelperfor paths and env; hot reload is app-only with 5s interval; OPcache is disabled in dev. - Docs (CHANGELOG, ARCHITECTURE, CLI) updated to match.
Breaking changes: None
Version 5.6.3 - Dotenv Overload for Docker Compatibility
Release Date: 2026-01-29
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release fixes environment variable loading so that applications work correctly in Dockerized environments. We changed Dotenv::load() to Dotenv::overload() in the Apache entrypoint and in ProjectHelper::loadEnv(), so that .env values can override existing environment variables (e.g. set by the container). This ensures consistent behavior when the same code runs in Docker and on a host.
🔄 Changes
Apache Entrypoint (index.php)
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()- File copied to application root; now uses
overload()for Docker compatibility - Location:
src/startup/apache/index.php
- File copied to application root; now uses
ProjectHelper::loadEnv()
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()for both root and app.env- Root
.env:$dotenv->overload($rootEnvFile) - App
.env:$dotenv->overload($appEnvFile) - Location:
src/helper/ProjectHelper.php(lines 41–52)
- Root
🎯 Benefits
- ✅ Docker compatibility -
.envcan override container-provided environment variables when needed - ✅ Consistent behavior - Same loading semantics in Apache entrypoint and
ProjectHelper - ✅ No breaking change - Existing apps without pre-set env vars behave as before
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
🔄 Migration Guide
From 5.6.2 to 5.6.3
This release is fully backward compatible. No action required.
What Changed:
- Apache
index.phpandProjectHelper::loadEnv()now useDotenv::overload()instead ofload() - Improves behavior in Dockerized deployments
Breaking Changes: None
Version 5.6.2 - APM Assignment API Improvement
Release Date: 2026-01-27
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release introduces a cleaner, more precise API for setting APM instances on the Request object. We've added a dedicated setApm() method to the Request class and updated both Bootstrap classes to use this new method instead of direct property assignment. This improvement provides better type safety, cleaner code, and a more maintainable codebase.
✨ Added
Request::setApm() Method
- New Helper Method -
setApm(\Gemvc\Core\Apm\ApmInterface $apm): void- Provides a type-safe, explicit way to set APM instance on Request object
- Replaces direct property assignment (
$request->apm = $apm) with method call - Centralizes APM assignment logic in one place
- Better for developers who want to set APM in other classes
- Location:
src/http/Request.php
Usage Example:
// Before (still works, but less precise)
$request->apm = $apmInstance;
// Now (recommended, cleaner and more precise)
$request->setApm($apmInstance);🔄 Changes
Bootstrap Classes Refactoring
Bootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Updated
recordExceptionInApm()- Fallback code also usessetApm()- Changed from:
$this->request->apm = $apm; - Changed to:
$this->request->setApm($apm);
- Changed from:
- Location:
src/core/Bootstrap.php
SwooleBootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Location:
src/core/SwooleBootstrap.php
🎯 Benefits
- ✅ Cleaner API - Explicit method call instead of property assignment
- ✅ Better Type Safety - Method signature enforces
ApmInterfacetype - ✅ Centralized Logic - All APM assignment goes through one method
- ✅ More Maintainable - Easier to modify APM assignment behavior in the future
- ✅ Consistent Pattern - Both Bootstrap classes use the same approach
- ✅ Developer-Friendly - More precise and better for use in other classes
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
For Developers:
- You can now use
$request->setApm($apm)instead of$request->apm = $apm - Direct property assignment (
$request->apm = $apm) still works for backward compatibility - The new method is recommended for cleaner, more type-safe code
🚀 Performance
- No performance impact from these changes
- Method call overhead is negligible
- Same functionality with cleaner code
🔄 Migration Guide
From 5.6.1 to 5.6.2
This release is fully backward compatible. No action required.
What Changed:
- Added
Request::setApm()method for cleaner APM assignment - Updated Bootstrap and SwooleBootstrap to use the new method
- Direct property assignment still works (backward compatible)
Benefits:
- Cleaner API for APM assignment
- Better type safety
- More maintainable codebase
- Consistent pattern across framework
Action Required:
- None - automatic upgrade recommended
- Optional: Update custom code to use
$request->setApm($apm)instead of direct assignment - Direct property assignment continues to work for backward compatibility
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- GitHub: https://github.com/gemvc/gemvc
- Issues: https://github.com/gemvc/gemvc/issues
Upgrade Command:
composer update gemvc/libraryBreaking Changes: N...
5.6.4
Full Changelog: 5.6.2...5.6.4
GEMVC Framework - Release Notes
Version 5.6.4 - Dotenv Overload for Docker Compatibility
Release Date: 2026-01-29
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release fixes environment variable loading so that applications work correctly in Dockerized environments. We changed Dotenv::load() to Dotenv::overload() in the Apache entrypoint and in ProjectHelper::loadEnv(), so that .env values can override existing environment variables (e.g. set by the container). This ensures consistent behavior when the same code runs in Docker and on a host.
🔄 Changes
Apache Entrypoint (index.php)
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()- File copied to application root; now uses
overload()for Docker compatibility - Location:
src/startup/apache/index.php
- File copied to application root; now uses
ProjectHelper::loadEnv()
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()for both root and app.env- Root
.env:$dotenv->overload($rootEnvFile) - App
.env:$dotenv->overload($appEnvFile) - Location:
src/helper/ProjectHelper.php(lines 41–52)
- Root
🎯 Benefits
- ✅ Docker compatibility -
.envcan override container-provided environment variables when needed - ✅ Consistent behavior - Same loading semantics in Apache entrypoint and
ProjectHelper - ✅ No breaking change - Existing apps without pre-set env vars behave as before
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
🔄 Migration Guide
From 5.6.2 to 5.6.3
This release is fully backward compatible. No action required.
What Changed:
- Apache
index.phpandProjectHelper::loadEnv()now useDotenv::overload()instead ofload() - Improves behavior in Dockerized deployments
Breaking Changes: None
Version 5.6.2 - APM Assignment API Improvement
Release Date: 2026-01-27
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release introduces a cleaner, more precise API for setting APM instances on the Request object. We've added a dedicated setApm() method to the Request class and updated both Bootstrap classes to use this new method instead of direct property assignment. This improvement provides better type safety, cleaner code, and a more maintainable codebase.
✨ Added
Request::setApm() Method
- New Helper Method -
setApm(\Gemvc\Core\Apm\ApmInterface $apm): void- Provides a type-safe, explicit way to set APM instance on Request object
- Replaces direct property assignment (
$request->apm = $apm) with method call - Centralizes APM assignment logic in one place
- Better for developers who want to set APM in other classes
- Location:
src/http/Request.php
Usage Example:
// Before (still works, but less precise)
$request->apm = $apmInstance;
// Now (recommended, cleaner and more precise)
$request->setApm($apmInstance);🔄 Changes
Bootstrap Classes Refactoring
Bootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Updated
recordExceptionInApm()- Fallback code also usessetApm()- Changed from:
$this->request->apm = $apm; - Changed to:
$this->request->setApm($apm);
- Changed from:
- Location:
src/core/Bootstrap.php
SwooleBootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Location:
src/core/SwooleBootstrap.php
🎯 Benefits
- ✅ Cleaner API - Explicit method call instead of property assignment
- ✅ Better Type Safety - Method signature enforces
ApmInterfacetype - ✅ Centralized Logic - All APM assignment goes through one method
- ✅ More Maintainable - Easier to modify APM assignment behavior in the future
- ✅ Consistent Pattern - Both Bootstrap classes use the same approach
- ✅ Developer-Friendly - More precise and better for use in other classes
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
For Developers:
- You can now use
$request->setApm($apm)instead of$request->apm = $apm - Direct property assignment (
$request->apm = $apm) still works for backward compatibility - The new method is recommended for cleaner, more type-safe code
🚀 Performance
- No performance impact from these changes
- Method call overhead is negligible
- Same functionality with cleaner code
🔄 Migration Guide
From 5.6.1 to 5.6.2
This release is fully backward compatible. No action required.
What Changed:
- Added
Request::setApm()method for cleaner APM assignment - Updated Bootstrap and SwooleBootstrap to use the new method
- Direct property assignment still works (backward compatible)
Benefits:
- Cleaner API for APM assignment
- Better type safety
- More maintainable codebase
- Consistent pattern across framework
Action Required:
- None - automatic upgrade recommended
- Optional: Update custom code to use
$request->setApm($apm)instead of direct assignment - Direct property assignment continues to work for backward compatibility
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- GitHub: https://github.com/gemvc/gemvc
- Issues: https://github.com/gemvc/gemvc/issues
Upgrade Command:
composer update gemvc/libraryBreaking Changes: None
Deprecations: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+
Full Changelog: 5.6.0...5.6.1
Version 5.6.1 - PHPStan Level 9 Compliance Fixes
Release Date: 2026-01-26
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release focuses on resolving all PHPStan Level 9 static analysis errors across the framework. We've fixed type safety issues, removed unused properties, and improved method signatures to ensure full compliance with the highest static analysis level. All changes are backward compatible and require no code modifications.
🐛 Bug Fixes
PHPStan Level 9 Compliance
AsyncApiCall.php
- Removed unused property - Deleted
$responseCallbacksproperty that was never read - Fixed return type - Updated
getInternalClient()to properly exclude null from return type - Removed unnecessary checks - Eliminated redundant
method_exists()calls for methods guaranteed to exist
ApiCall.php
- Removed unused properties - Deleted
$rawBodyand$formFieldsproperties that were never read - Fixed return type - Enhanced
getInternalClient()with proper PHPStan type assertion
Controller.php
- Fixed method signature conflict - Updated
recordApmException()to support both:- Single-parameter call:
recordApmException($exception)(backward compatible) - Two-parameter call:
recordApmException($spanData, $exception)(for trait usage)
- Single-parameter call:
- Resolves PHPStan error - "Method invoked with 2 parameters, 1 required"
ApmModel.php
- Fixed mixed type access - Added proper type checks (
is_array(),is_string()) before array offset access - Fixed strlen() with mixed - Ensured string type before calling
strlen() - Added PHPStan ignore - Valid dead catch warning (constructor can throw even after
class_exists()check)
🔄 Changes
Type Safety Improvements
- Enhanced null handling in lazy-loaded client instances
- Improved type assertions for PHPStan Level 9 compliance
- Cleaner codebase with removed unused properties
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
🚀 Performance
- No performance impact from these changes
- Code cleanup may provide minor memory savings (removed unused properties)
🔄 Migration Guide
From 5.6.0 to 5.6.1
This release is fully backward compatible. No action required.
What Changed:
- PHPStan Level 9 compliance fixes
- Removed unused properties
- Fixed method signature conflicts
- Enhanced type safety
Benefits:
- Full PHPStan Level 9 compliance
- Cleaner codebase
- Better type safety
- No breaking changes
Action Required:
- None - automatic upgrade recommended
- Run
composer update gemvc/libraryto get the new version - All existing code continues to work without modification
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards with PHPStan Level 9.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- **GitH...
5.6.3
Full Changelog: 5.6.2...5.6.3
GEMVC Framework - Release Notes
Version 5.6.3 - Dotenv Overload for Docker Compatibility
Release Date: 2026-01-29
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release fixes environment variable loading so that applications work correctly in Dockerized environments. We changed Dotenv::load() to Dotenv::overload() in the Apache entrypoint and in ProjectHelper::loadEnv(), so that .env values can override existing environment variables (e.g. set by the container). This ensures consistent behavior when the same code runs in Docker and on a host.
🔄 Changes
Apache Entrypoint (index.php)
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()- File copied to application root; now uses
overload()for Docker compatibility - Location:
src/startup/apache/index.php
- File copied to application root; now uses
ProjectHelper::loadEnv()
- Updated Dotenv usage -
$dotenv->load()→$dotenv->overload()for both root and app.env- Root
.env:$dotenv->overload($rootEnvFile) - App
.env:$dotenv->overload($appEnvFile) - Location:
src/helper/ProjectHelper.php(lines 41–52)
- Root
🎯 Benefits
- ✅ Docker compatibility -
.envcan override container-provided environment variables when needed - ✅ Consistent behavior - Same loading semantics in Apache entrypoint and
ProjectHelper - ✅ No breaking change - Existing apps without pre-set env vars behave as before
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
🔄 Migration Guide
From 5.6.2 to 5.6.3
This release is fully backward compatible. No action required.
What Changed:
- Apache
index.phpandProjectHelper::loadEnv()now useDotenv::overload()instead ofload() - Improves behavior in Dockerized deployments
Breaking Changes: None
Version 5.6.2 - APM Assignment API Improvement
Release Date: 2026-01-27
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release introduces a cleaner, more precise API for setting APM instances on the Request object. We've added a dedicated setApm() method to the Request class and updated both Bootstrap classes to use this new method instead of direct property assignment. This improvement provides better type safety, cleaner code, and a more maintainable codebase.
✨ Added
Request::setApm() Method
- New Helper Method -
setApm(\Gemvc\Core\Apm\ApmInterface $apm): void- Provides a type-safe, explicit way to set APM instance on Request object
- Replaces direct property assignment (
$request->apm = $apm) with method call - Centralizes APM assignment logic in one place
- Better for developers who want to set APM in other classes
- Location:
src/http/Request.php
Usage Example:
// Before (still works, but less precise)
$request->apm = $apmInstance;
// Now (recommended, cleaner and more precise)
$request->setApm($apmInstance);🔄 Changes
Bootstrap Classes Refactoring
Bootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Updated
recordExceptionInApm()- Fallback code also usessetApm()- Changed from:
$this->request->apm = $apm; - Changed to:
$this->request->setApm($apm);
- Changed from:
- Location:
src/core/Bootstrap.php
SwooleBootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Location:
src/core/SwooleBootstrap.php
🎯 Benefits
- ✅ Cleaner API - Explicit method call instead of property assignment
- ✅ Better Type Safety - Method signature enforces
ApmInterfacetype - ✅ Centralized Logic - All APM assignment goes through one method
- ✅ More Maintainable - Easier to modify APM assignment behavior in the future
- ✅ Consistent Pattern - Both Bootstrap classes use the same approach
- ✅ Developer-Friendly - More precise and better for use in other classes
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
For Developers:
- You can now use
$request->setApm($apm)instead of$request->apm = $apm - Direct property assignment (
$request->apm = $apm) still works for backward compatibility - The new method is recommended for cleaner, more type-safe code
🚀 Performance
- No performance impact from these changes
- Method call overhead is negligible
- Same functionality with cleaner code
🔄 Migration Guide
From 5.6.1 to 5.6.2
This release is fully backward compatible. No action required.
What Changed:
- Added
Request::setApm()method for cleaner APM assignment - Updated Bootstrap and SwooleBootstrap to use the new method
- Direct property assignment still works (backward compatible)
Benefits:
- Cleaner API for APM assignment
- Better type safety
- More maintainable codebase
- Consistent pattern across framework
Action Required:
- None - automatic upgrade recommended
- Optional: Update custom code to use
$request->setApm($apm)instead of direct assignment - Direct property assignment continues to work for backward compatibility
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- GitHub: https://github.com/gemvc/gemvc
- Issues: https://github.com/gemvc/gemvc/issues
Upgrade Command:
composer update gemvc/libraryBreaking Changes: None
Deprecations: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+
Full Changelog: 5.6.0...5.6.1
Version 5.6.1 - PHPStan Level 9 Compliance Fixes
Release Date: 2026-01-26
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release focuses on resolving all PHPStan Level 9 static analysis errors across the framework. We've fixed type safety issues, removed unused properties, and improved method signatures to ensure full compliance with the highest static analysis level. All changes are backward compatible and require no code modifications.
🐛 Bug Fixes
PHPStan Level 9 Compliance
AsyncApiCall.php
- Removed unused property - Deleted
$responseCallbacksproperty that was never read - Fixed return type - Updated
getInternalClient()to properly exclude null from return type - Removed unnecessary checks - Eliminated redundant
method_exists()calls for methods guaranteed to exist
ApiCall.php
- Removed unused properties - Deleted
$rawBodyand$formFieldsproperties that were never read - Fixed return type - Enhanced
getInternalClient()with proper PHPStan type assertion
Controller.php
- Fixed method signature conflict - Updated
recordApmException()to support both:- Single-parameter call:
recordApmException($exception)(backward compatible) - Two-parameter call:
recordApmException($spanData, $exception)(for trait usage)
- Single-parameter call:
- Resolves PHPStan error - "Method invoked with 2 parameters, 1 required"
ApmModel.php
- Fixed mixed type access - Added proper type checks (
is_array(),is_string()) before array offset access - Fixed strlen() with mixed - Ensured string type before calling
strlen() - Added PHPStan ignore - Valid dead catch warning (constructor can throw even after
class_exists()check)
🔄 Changes
Type Safety Improvements
- Enhanced null handling in lazy-loaded client instances
- Improved type assertions for PHPStan Level 9 compliance
- Cleaner codebase with removed unused properties
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
🚀 Performance
- No performance impact from these changes
- Code cleanup may provide minor memory savings (removed unused properties)
🔄 Migration Guide
From 5.6.0 to 5.6.1
This release is fully backward compatible. No action required.
What Changed:
- PHPStan Level 9 compliance fixes
- Removed unused properties
- Fixed method signature conflicts
- Enhanced type safety
Benefits:
- Full PHPStan Level 9 compliance
- Cleaner codebase
- Better type safety
- No breaking changes
Action Required:
- None - automatic upgrade recommended
- Run
composer update gemvc/libraryto get the new version - All existing code continues to work without modification
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards with PHPStan Level 9.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- **GitH...
5.6.2
Full Changelog: 5.6.1...5.6.2
GEMVC Framework - Release Notes
Version 5.6.2 - APM Assignment API Improvement
Release Date: 2026-01-27
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release introduces a cleaner, more precise API for setting APM instances on the Request object. We've added a dedicated setApm() method to the Request class and updated both Bootstrap classes to use this new method instead of direct property assignment. This improvement provides better type safety, cleaner code, and a more maintainable codebase.
✨ Added
Request::setApm() Method
- New Helper Method -
setApm(\Gemvc\Core\Apm\ApmInterface $apm): void- Provides a type-safe, explicit way to set APM instance on Request object
- Replaces direct property assignment (
$request->apm = $apm) with method call - Centralizes APM assignment logic in one place
- Better for developers who want to set APM in other classes
- Location:
src/http/Request.php
Usage Example:
// Before (still works, but less precise)
$request->apm = $apmInstance;
// Now (recommended, cleaner and more precise)
$request->setApm($apmInstance);🔄 Changes
Bootstrap Classes Refactoring
Bootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Updated
recordExceptionInApm()- Fallback code also usessetApm()- Changed from:
$this->request->apm = $apm; - Changed to:
$this->request->setApm($apm);
- Changed from:
- Location:
src/core/Bootstrap.php
SwooleBootstrap.php
- Updated
initializeApm()- Now usesRequest::setApm()method- Changed from:
$this->request->apm = $this->apm; - Changed to:
$this->request->setApm($this->apm);
- Changed from:
- Location:
src/core/SwooleBootstrap.php
🎯 Benefits
- ✅ Cleaner API - Explicit method call instead of property assignment
- ✅ Better Type Safety - Method signature enforces
ApmInterfacetype - ✅ Centralized Logic - All APM assignment goes through one method
- ✅ More Maintainable - Easier to modify APM assignment behavior in the future
- ✅ Consistent Pattern - Both Bootstrap classes use the same approach
- ✅ Developer-Friendly - More precise and better for use in other classes
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
For Developers:
- You can now use
$request->setApm($apm)instead of$request->apm = $apm - Direct property assignment (
$request->apm = $apm) still works for backward compatibility - The new method is recommended for cleaner, more type-safe code
🚀 Performance
- No performance impact from these changes
- Method call overhead is negligible
- Same functionality with cleaner code
🔄 Migration Guide
From 5.6.1 to 5.6.2
This release is fully backward compatible. No action required.
What Changed:
- Added
Request::setApm()method for cleaner APM assignment - Updated Bootstrap and SwooleBootstrap to use the new method
- Direct property assignment still works (backward compatible)
Benefits:
- Cleaner API for APM assignment
- Better type safety
- More maintainable codebase
- Consistent pattern across framework
Action Required:
- None - automatic upgrade recommended
- Optional: Update custom code to use
$request->setApm($apm)instead of direct assignment - Direct property assignment continues to work for backward compatibility
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- GitHub: https://github.com/gemvc/gemvc
- Issues: https://github.com/gemvc/gemvc/issues
Upgrade Command:
composer update gemvc/libraryBreaking Changes: None
Deprecations: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+
Full Changelog: 5.6.0...5.6.1
Version 5.6.1 - PHPStan Level 9 Compliance Fixes
Release Date: 2026-01-26
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release focuses on resolving all PHPStan Level 9 static analysis errors across the framework. We've fixed type safety issues, removed unused properties, and improved method signatures to ensure full compliance with the highest static analysis level. All changes are backward compatible and require no code modifications.
🐛 Bug Fixes
PHPStan Level 9 Compliance
AsyncApiCall.php
- Removed unused property - Deleted
$responseCallbacksproperty that was never read - Fixed return type - Updated
getInternalClient()to properly exclude null from return type - Removed unnecessary checks - Eliminated redundant
method_exists()calls for methods guaranteed to exist
ApiCall.php
- Removed unused properties - Deleted
$rawBodyand$formFieldsproperties that were never read - Fixed return type - Enhanced
getInternalClient()with proper PHPStan type assertion
Controller.php
- Fixed method signature conflict - Updated
recordApmException()to support both:- Single-parameter call:
recordApmException($exception)(backward compatible) - Two-parameter call:
recordApmException($spanData, $exception)(for trait usage)
- Single-parameter call:
- Resolves PHPStan error - "Method invoked with 2 parameters, 1 required"
ApmModel.php
- Fixed mixed type access - Added proper type checks (
is_array(),is_string()) before array offset access - Fixed strlen() with mixed - Ensured string type before calling
strlen() - Added PHPStan ignore - Valid dead catch warning (constructor can throw even after
class_exists()check)
🔄 Changes
Type Safety Improvements
- Enhanced null handling in lazy-loaded client instances
- Improved type assertions for PHPStan Level 9 compliance
- Cleaner codebase with removed unused properties
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
🚀 Performance
- No performance impact from these changes
- Code cleanup may provide minor memory savings (removed unused properties)
🔄 Migration Guide
From 5.6.0 to 5.6.1
This release is fully backward compatible. No action required.
What Changed:
- PHPStan Level 9 compliance fixes
- Removed unused properties
- Fixed method signature conflicts
- Enhanced type safety
Benefits:
- Full PHPStan Level 9 compliance
- Cleaner codebase
- Better type safety
- No breaking changes
Action Required:
- None - automatic upgrade recommended
- Run
composer update gemvc/libraryto get the new version - All existing code continues to work without modification
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards with PHPStan Level 9.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- GitHub: https://github.com/gemvc/gemvc
- Issues: https://github.com/gemvc/gemvc/issues
Upgrade Command:
composer update gemvc/libraryBreaking Changes: None
Deprecations: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+
Full Changelog: 5.5.0...5.6.0
Version 5.6.0 - Core APM Architecture Unification & DX Improvements
Release Date: 2026-01-22
Type: Minor Release (Backward Compatible)
📋 Overview
This release focuses on standardizing the Application Performance Monitoring (APM) architecture across the framework core. We have unified the tracing logic using a centralized ApmTracingTrait, reducing code duplication and ensuring consistent behavior across ApiService, Controller, and UniversalQueryExecuter.
Additionally, we introduced Magic Properties in ApiService for a significantly improved Developer Experience (DX) when calling controllers.
✨ Added
🪄 Magic Controller Access (DX Improvement)
- Fluent Controller Access - Access controllers as properties in
ApiService- Syntax:
$this->UserController->method() - Replaces verbose:
$this->callController(new UserController($this->request))->method() - Automatic Tracing: The magic wrapper automatically handles APM tracing for the controller call
- Type Safety: Includes
@propertyannotations for IDE autocompletion - Location:
src/core/ApiService.php
- Syntax:
🔧 Unified APM Architecture
- ApmTracingTrait - Centralized APM logic
- Provides unified
startApmSpan,endApmSpan,traceApm, andrecordApmExceptionmethods - Adopted by
ApiService,Controller, andUniversalQueryExecuter - Ensures consistent span attributes and error handling
- Location:
src/core/Apm/ApmTracingTrait.php
- Provides unified
🔄 Changes
...
5.6.1
Full Changelog: 5.6.0...5.6.1
GEMVC Framework - Release Notes
Version 5.6.1 - PHPStan Level 9 Compliance Fixes
Release Date: 2026-01-26
Type: Patch Release (Backward Compatible)
📋 Overview
This patch release focuses on resolving all PHPStan Level 9 static analysis errors across the framework. We've fixed type safety issues, removed unused properties, and improved method signatures to ensure full compliance with the highest static analysis level. All changes are backward compatible and require no code modifications.
🐛 Bug Fixes
PHPStan Level 9 Compliance
AsyncApiCall.php
- Removed unused property - Deleted
$responseCallbacksproperty that was never read - Fixed return type - Updated
getInternalClient()to properly exclude null from return type - Removed unnecessary checks - Eliminated redundant
method_exists()calls for methods guaranteed to exist
ApiCall.php
- Removed unused properties - Deleted
$rawBodyand$formFieldsproperties that were never read - Fixed return type - Enhanced
getInternalClient()with proper PHPStan type assertion
Controller.php
- Fixed method signature conflict - Updated
recordApmException()to support both:- Single-parameter call:
recordApmException($exception)(backward compatible) - Two-parameter call:
recordApmException($spanData, $exception)(for trait usage)
- Single-parameter call:
- Resolves PHPStan error - "Method invoked with 2 parameters, 1 required"
ApmModel.php
- Fixed mixed type access - Added proper type checks (
is_array(),is_string()) before array offset access - Fixed strlen() with mixed - Ensured string type before calling
strlen() - Added PHPStan ignore - Valid dead catch warning (constructor can throw even after
class_exists()check)
🔄 Changes
Type Safety Improvements
- Enhanced null handling in lazy-loaded client instances
- Improved type assertions for PHPStan Level 9 compliance
- Cleaner codebase with removed unused properties
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained (90% automatic security)
⚙️ Configuration
No configuration changes required. All improvements are automatic and backward compatible.
🚀 Performance
- No performance impact from these changes
- Code cleanup may provide minor memory savings (removed unused properties)
🔄 Migration Guide
From 5.6.0 to 5.6.1
This release is fully backward compatible. No action required.
What Changed:
- PHPStan Level 9 compliance fixes
- Removed unused properties
- Fixed method signature conflicts
- Enhanced type safety
Benefits:
- Full PHPStan Level 9 compliance
- Cleaner codebase
- Better type safety
- No breaking changes
Action Required:
- None - automatic upgrade recommended
- Run
composer update gemvc/libraryto get the new version - All existing code continues to work without modification
Breaking Changes:
- None - 100% backward compatible
🙏 Acknowledgments
Thank you to the community for maintaining high code quality standards with PHPStan Level 9.
📝 Full Changelog
For detailed changes, see CHANGELOG.md.
🔗 Links
- Documentation: https://gemvc.de
- GitHub: https://github.com/gemvc/gemvc
- Issues: https://github.com/gemvc/gemvc/issues
Upgrade Command:
composer update gemvc/libraryBreaking Changes: None
Deprecations: None
Minimum PHP Version: 8.2+
Recommended PHP Version: 8.4+
Full Changelog: 5.5.0...5.6.0
Version 5.6.0 - Core APM Architecture Unification & DX Improvements
Release Date: 2026-01-22
Type: Minor Release (Backward Compatible)
📋 Overview
This release focuses on standardizing the Application Performance Monitoring (APM) architecture across the framework core. We have unified the tracing logic using a centralized ApmTracingTrait, reducing code duplication and ensuring consistent behavior across ApiService, Controller, and UniversalQueryExecuter.
Additionally, we introduced Magic Properties in ApiService for a significantly improved Developer Experience (DX) when calling controllers.
✨ Added
🪄 Magic Controller Access (DX Improvement)
- Fluent Controller Access - Access controllers as properties in
ApiService- Syntax:
$this->UserController->method() - Replaces verbose:
$this->callController(new UserController($this->request))->method() - Automatic Tracing: The magic wrapper automatically handles APM tracing for the controller call
- Type Safety: Includes
@propertyannotations for IDE autocompletion - Location:
src/core/ApiService.php
- Syntax:
🔧 Unified APM Architecture
- ApmTracingTrait - Centralized APM logic
- Provides unified
startApmSpan,endApmSpan,traceApm, andrecordApmExceptionmethods - Adopted by
ApiService,Controller, andUniversalQueryExecuter - Ensures consistent span attributes and error handling
- Location:
src/core/Apm/ApmTracingTrait.php
- Provides unified
🔄 Changes
Controller Layer Refactoring
- Refactored
Controller.php- Now usesApmTracingTrait- Removed duplicate
getApm()logic - Removed dead code (
getControllerName) - Aliased legacy
startTraceSpanmethods for backward compatibility - Location:
src/core/Controller.php
- Removed duplicate
Database Layer Refactoring
- Refactored
UniversalQueryExecuter.php- Now usesApmTracingTrait- Replaced manual APM environment checks with centralized logic
- Context Propagation: Renamed internal property to
$_requestto avoid DB column conflicts while maintaining APM context - Removed redundant helper methods
- Location:
src/database/UniversalQueryExecuter.php
Type Safety & Compliance
- PHPStan Level 9 -
ApiServicechecks- Added strict
instanceof Controllerchecks in magic getter - Added proper type hinting for all dynamic properties
- Added strict
🐛 Bug Fixes
- Context Propagation Safety - Fixed potential conflict in
UniversalQueryExecuterwhere$requestproperty could clash with database columns named "request". using$_requestensures safety. - Trace Continuity - Ensured database traces are always correctly linked to the parent HTTP request trace via strict object propagation.
🔒 Security
- No security vulnerabilities reported in this release
- All existing security features maintained
⚙️ Configuration
- No configuration settings changed
- APM behavior (enabled/disabled) is still controlled via
.envvariables (APM_ENABLED, etc.)
🚀 Performance
- Reduced Overhead - Removed redundant method calls and checks in tracing logic
- Optimized Tracing - Centralized "should trace" checks are more efficient
- Zero Impact - Magic controller access uses lazy loading proxy with negligible overhead
🔄 Migration Guide
From 5.5.0 to 5.6.0
This release is fully backward compatible. No action required.
Recommendation:
- Update your
ApiServicecode to use the new fluent syntax:return $this->UserController->create();for cleaner code. - Old syntax
$this->callController(...)continues to work perfectly.
Version 5.5.0 - HTTP Client Package Integration with Environment Detection
Release Date: 2026-01-22
Type: Minor Release (Backward Compatible)
📋 Overview
This release integrates the gemvc/http-client package into the framework core, providing automatic environment detection to select the optimal HTTP client implementation. ApiCall and AsyncApiCall classes now use the new package internally while maintaining 100% backward compatibility. The integration provides better error handling, improved performance in Swoole environments, and a cleaner codebase architecture.
✨ Added
HTTP Client Package Integration
- gemvc/http-client Package - Now included as a required dependency
- Provides
HttpClientfor synchronous requests (Apache/Nginx) - Provides
AsyncHttpClientfor asynchronous requests (Apache/Nginx) - Provides
SwooleHttpClientfor native Swoole coroutines (optimized) - Automatic environment detection via
WebserverDetector - Enhanced error handling with exception classification
- Better retry mechanisms and SSL support
- Provides
Automatic Environment Detection
- AsyncApiCall Environment Detection - Automatically selects optimal client
- Uses
SwooleHttpClient(native coroutines) when running in Swoole - Uses
AsyncHttpClient(curl_multi) when running in Apache/Nginx - Zero configuration required - detection happens automatically
- Performance optimized for each environment
- Uses
🔄 Changes
ApiCall Class Refactoring
- Internal Implementation - Now uses
Gemvc\Http\Client\HttpClientinternally- All public methods delegate to internal client
- Configuration automatically synced between wrapper and internal client
- Response data automatically synced back to wrapper
- All existing public properties and methods remain unchanged
- Location:
src/http/ApiCall.php
Benefits:
- ✅ Better error handling from package
- ✅ Improved retry mechanisms
- ✅ Cleaner codebase (delegation pattern)
- ✅ Future-proof (package can be updated independently)
- ✅ 100% backward compatible
AsyncApiCall Class Refactoring
- Internal Implementation - Uses
AsyncHttpClientor `SwooleHttpClie...