Skip to content

Releases: gemvc/gemvc

new ORM methods whereIn() and whereNotIn()

04 Jun 11:51

Choose a tag to compare

gemvc_let
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 — bound IN (...) clause; empty $values adds no condition.
  • whereNotIn(string $column, array $values): self — bound NOT IN (...) clause; same empty-array behavior.
  • Parameter names use str_replace('.', '_', $column) for qualified columns (e.g. users.role_id).
  • Suffix from _arr_where count avoids bind collisions when chaining multiple IN/NOT IN clauses.

Documentation

  • Updated AI_API_REFERENCE.md, AI_CONTEXT.md, GEMVC_PHPDOC_REFERENCE.php, and gemvc-api-reference.jsonc.

🎯 Benefits

  • Parity between Table fluent 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).
  • _id suffix columns are forced to INT(11) only when the PHP/base type is int or integer.
  • Non-integer _id fields (e.g., UUID/external identifiers) preserve their declared string mapping.

🎯 Benefits

  • Correct schema mapping for nullable types (?string no longer falls back to TEXT)
  • 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 update to pull gemvc/library 5.7.1.
  • Re-run table generation/migrations if you rely on nullable mapped types or string-based _id columns.

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 CliColor enum (write($message, CliColor::Blue)), not string color names.
  • CliBoxShow / CliLine used 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 targets src/ only via phpstan.neon.
  • Added Composer script: composer phpstan.

Packaging (cli-base 1.0.1)

  • .gitattributes export-ignoretests/ and dev files are no longer shipped in Composer installs of gemvc/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 gemvc binary 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 CliColor enum in write() (not string color names).

What you should do:

  • Run composer update to pull gemvc/library 5.7.0 and gemvc/cli-base ^1.0.1.
  • Custom CLI commands: extend Gemvc\CLI\Command; use CliColor, 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_COMMAND is deprecated in PHP 8.5 in favor of Pdo\Mysql::ATTR_INIT_COMMAND.
  • Implementation: Use Pdo\Mysql::ATTR_INIT_COMMAND when running on PHP 8.5+ and the class exists; otherwise fall back to PDO::MYSQL_ATTR_INIT_COMMAND.
  • Locations:
    • src/CLI/commands/DbConnect.phpconnect(), connectAsRoot() (and duplicate under commands/commands/)
    • src/core/Developer/DeveloperTable.php – root connection for CREATE DATABASE

CLI – Terminal colors (macOS / cross-platform)

  • Problem: macOS Terminal does not render cyan ANSI codes reliably; prompts and db:describe table borders could appear wrong or invisible.
  • Solution: Use blue (\033[34m / \033[1;34m) instead of cyan across CLI output.
  • Command.php: write() supports blue; cyan is 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 DbConnect and DeveloperTable
  • 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://input once 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 of false when filter fails.
    • `sanitizeRequestURI()...
Read more

5.7.1 - TableGenerator type mapping accuracy improvements

30 May 14:53

Choose a tag to compare

gemvc_let
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).
  • _id suffix columns are forced to INT(11) only when the PHP/base type is int or integer.
  • Non-integer _id fields (e.g., UUID/external identifiers) preserve their declared string mapping.

🎯 Benefits

  • Correct schema mapping for nullable types (?string no longer falls back to TEXT)
  • 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 update to pull gemvc/library 5.7.1.
  • Re-run table generation/migrations if you rely on nullable mapped types or string-based _id columns.

Breaking Changes: None

Version 5.7.0 - CLI foundation extracted

18 May 14:26

Choose a tag to compare

gemvc_let
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 CliColor enum (write($message, CliColor::Blue)), not string color names.
  • CliBoxShow / CliLine used 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 targets src/ only via phpstan.neon.
  • Added Composer script: composer phpstan.

Packaging (cli-base 1.0.1)

  • .gitattributes export-ignoretests/ and dev files are no longer shipped in Composer installs of gemvc/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 gemvc binary 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 CliColor enum in write() (not string color names).

What you should do:

  • Run composer update to pull gemvc/library 5.7.0 and gemvc/cli-base ^1.0.1.
  • Custom CLI commands: extend Gemvc\CLI\Command; use CliColor, 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_COMMAND is deprecated in PHP 8.5 in favor of Pdo\Mysql::ATTR_INIT_COMMAND.
  • Implementation: Use Pdo\Mysql::ATTR_INIT_COMMAND when running on PHP 8.5+ and the class exists; otherwise fall back to PDO::MYSQL_ATTR_INIT_COMMAND.
  • Locations:
    • src/CLI/commands/DbConnect.phpconnect(), connectAsRoot() (and duplicate under commands/commands/)
    • src/core/Developer/DeveloperTable.php – root connection for CREATE DATABASE

CLI – Terminal colors (macOS / cross-platform)

  • Problem: macOS Terminal does not render cyan ANSI codes reliably; prompts and db:describe table borders could appear wrong or invisible.
  • Solution: Use blue (\033[34m / \033[1;34m) instead of cyan across CLI output.
  • Command.php: write() supports blue; cyan is 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 DbConnect and DeveloperTable
  • 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://input once 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 of false when filter fails.
    • sanitizeRequestURI() uses the filtered URL result when valid.
    • sanitizeQueryString() uses empty string of false on 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, and SwooleRequest.

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/table
    • ProjectHelper::getLibrarySystemPagesPath() for system pages (e.g. developer UI templates)
  • Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
    • ProjectHelper::isDevEnvironment() for dev checks
    • ProjectHelper::getAppEnv() for APP_ENV (e.g. developer info, APM)
    • ProjectHelper::getBaseUrl() / getApiBaseUrl() for base URL and API base URL
  • ApmModel – Single constant APM_NOT_ENABLED_MESSAGE for the “APM not enabled…” message (DRY).

HotReloadManager

  • Scope – Watches app directory only via ProjectHelper::appDir() (no longer watches vendor/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 methodProjectHelper::disableOpcacheIfDev():
    • No-op when not in dev.
    • In dev: calls opcache_reset() and opcache_disable() when available (with @ to avoid notices if O...
Read more

v5.6.7 - PHP 8.5 & macOS CLI fixes

17 May 12:30

Choose a tag to compare

gemvc_let
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_COMMAND is deprecated in PHP 8.5 in favor of Pdo\Mysql::ATTR_INIT_COMMAND.
  • Implementation: Use Pdo\Mysql::ATTR_INIT_COMMAND when running on PHP 8.5+ and the class exists; otherwise fall back to PDO::MYSQL_ATTR_INIT_COMMAND.
  • Locations:
    • src/CLI/commands/DbConnect.phpconnect(), connectAsRoot() (and duplicate under commands/commands/)
    • src/core/Developer/DeveloperTable.php – root connection for CREATE DATABASE

CLI – Terminal colors (macOS / cross-platform)

  • Problem: macOS Terminal does not render cyan ANSI codes reliably; prompts and db:describe table borders could appear wrong or invisible.
  • Solution: Use blue (\033[34m / \033[1;34m) instead of cyan across CLI output.
  • Command.php: write() supports blue; cyan is 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 DbConnect and DeveloperTable
  • 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://input once 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 of false when filter fails.
    • sanitizeRequestURI() uses the filtered URL result when valid.
    • sanitizeQueryString() uses empty string of false on 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, and SwooleRequest.

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/table
    • ProjectHelper::getLibrarySystemPagesPath() for system pages (e.g. developer UI templates)
  • Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
    • ProjectHelper::isDevEnvironment() for dev checks
    • ProjectHelper::getAppEnv() for APP_ENV (e.g. developer info, APM)
    • ProjectHelper::getBaseUrl() / getApiBaseUrl() for base URL and API base URL
  • ApmModel – Single constant APM_NOT_ENABLED_MESSAGE for the “APM not enabled…” message (DRY).

HotReloadManager

  • Scope – Watches app directory only via ProjectHelper::appDir() (no longer watches vendor/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 methodProjectHelper::disableOpcacheIfDev():
    • No-op when not in dev.
    • In dev: calls opcache_reset() and opcache_disable() when available (with @ to avoid notices if OPcache is not loaded).
  • BootstrapBootstrap::__construct() calls disableOpcacheIfDev() early so each request in dev runs without OPcache.
  • OpenSwoole – In workerStart, when in dev, each worker calls disableOpcacheIfDev() 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 HotReloadManager and ProjectHelper descriptions to reflect app-only watch, 5s interval, and disableOpcacheIfDev().
  • 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 ProjectHelper only.
  • 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 ProjectHelper for 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

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)

🎯 Benefits

  • Docker compatibility - .env can 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...
Read more

5.6.6

18 Feb 15:11

Choose a tag to compare

gemvc_let
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://input once 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 of false when filter fails.
    • sanitizeRequestURI() uses the filtered URL result when valid.
    • sanitizeQueryString() uses empty string of false on 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, and SwooleRequest.

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/table
    • ProjectHelper::getLibrarySystemPagesPath() for system pages (e.g. developer UI templates)
  • Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
    • ProjectHelper::isDevEnvironment() for dev checks
    • ProjectHelper::getAppEnv() for APP_ENV (e.g. developer info, APM)
    • ProjectHelper::getBaseUrl() / getApiBaseUrl() for base URL and API base URL
  • ApmModel – Single constant APM_NOT_ENABLED_MESSAGE for the “APM not enabled…” message (DRY).

HotReloadManager

  • Scope – Watches app directory only via ProjectHelper::appDir() (no longer watches vendor/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 methodProjectHelper::disableOpcacheIfDev():
    • No-op when not in dev.
    • In dev: calls opcache_reset() and opcache_disable() when available (with @ to avoid notices if OPcache is not loaded).
  • BootstrapBootstrap::__construct() calls disableOpcacheIfDev() early so each request in dev runs without OPcache.
  • OpenSwoole – In workerStart, when in dev, each worker calls disableOpcacheIfDev() 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 HotReloadManager and ProjectHelper descriptions to reflect app-only watch, 5s interval, and disableOpcacheIfDev().
  • 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 ProjectHelper only.
  • 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 ProjectHelper for 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

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)

🎯 Benefits

  • Docker compatibility - .env can 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.php and ProjectHelper::loadEnv() now use Dotenv::overload() instead of load()
  • 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 uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Updated recordExceptionInApm() - Fallback code also uses setApm()
    • Changed from: $this->request->apm = $apm;
    • Changed to: $this->request->setApm($apm);
  • Location: src/core/Bootstrap.php

SwooleBootstrap.php

  • Updated initializeApm() - Now uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: `$this->requ...
Read more

5.6.5

09 Feb 12:36

Choose a tag to compare

gemvc_let
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/table
    • ProjectHelper::getLibrarySystemPagesPath() for system pages (e.g. developer UI templates)
  • Environment – SwooleServerConfig, GemvcErrorHandler, DeveloperController, DeveloperModel, GemvcAssistantModel, ApmModel now use:
    • ProjectHelper::isDevEnvironment() for dev checks
    • ProjectHelper::getAppEnv() for APP_ENV (e.g. developer info, APM)
    • ProjectHelper::getBaseUrl() / getApiBaseUrl() for base URL and API base URL
  • ApmModel – Single constant APM_NOT_ENABLED_MESSAGE for the “APM not enabled…” message (DRY).

HotReloadManager

  • Scope – Watches app directory only via ProjectHelper::appDir() (no longer watches vendor/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 methodProjectHelper::disableOpcacheIfDev():
    • No-op when not in dev.
    • In dev: calls opcache_reset() and opcache_disable() when available (with @ to avoid notices if OPcache is not loaded).
  • BootstrapBootstrap::__construct() calls disableOpcacheIfDev() early so each request in dev runs without OPcache.
  • OpenSwoole – In workerStart, when in dev, each worker calls disableOpcacheIfDev() 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 HotReloadManager and ProjectHelper descriptions to reflect app-only watch, 5s interval, and disableOpcacheIfDev().
  • 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 ProjectHelper only.
  • 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 ProjectHelper for 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

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)

🎯 Benefits

  • Docker compatibility - .env can 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.php and ProjectHelper::loadEnv() now use Dotenv::overload() instead of load()
  • 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 uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Updated recordExceptionInApm() - Fallback code also uses setApm()
    • Changed from: $this->request->apm = $apm;
    • Changed to: $this->request->setApm($apm);
  • Location: src/core/Bootstrap.php

SwooleBootstrap.php

  • Updated initializeApm() - Now uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Location: src/core/SwooleBootstrap.php

🎯 Benefits

  • Cleaner API - Explicit method call instead of property assignment
  • Better Type Safety - Method signature enforces ApmInterface type
  • 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


Upgrade Command:

composer update gemvc/library

Breaking Changes: N...

Read more

5.6.4

29 Jan 12:17

Choose a tag to compare

gemvc_let
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

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)

🎯 Benefits

  • Docker compatibility - .env can 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.php and ProjectHelper::loadEnv() now use Dotenv::overload() instead of load()
  • 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 uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Updated recordExceptionInApm() - Fallback code also uses setApm()
    • Changed from: $this->request->apm = $apm;
    • Changed to: $this->request->setApm($apm);
  • Location: src/core/Bootstrap.php

SwooleBootstrap.php

  • Updated initializeApm() - Now uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Location: src/core/SwooleBootstrap.php

🎯 Benefits

  • Cleaner API - Explicit method call instead of property assignment
  • Better Type Safety - Method signature enforces ApmInterface type
  • 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


Upgrade Command:

composer update gemvc/library

Breaking 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 $responseCallbacks property 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 $rawBody and $formFields properties 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)
  • 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/library to 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

Read more

5.6.3

29 Jan 10:24

Choose a tag to compare

gemvc_let
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

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)

🎯 Benefits

  • Docker compatibility - .env can 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.php and ProjectHelper::loadEnv() now use Dotenv::overload() instead of load()
  • 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 uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Updated recordExceptionInApm() - Fallback code also uses setApm()
    • Changed from: $this->request->apm = $apm;
    • Changed to: $this->request->setApm($apm);
  • Location: src/core/Bootstrap.php

SwooleBootstrap.php

  • Updated initializeApm() - Now uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Location: src/core/SwooleBootstrap.php

🎯 Benefits

  • Cleaner API - Explicit method call instead of property assignment
  • Better Type Safety - Method signature enforces ApmInterface type
  • 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


Upgrade Command:

composer update gemvc/library

Breaking 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 $responseCallbacks property 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 $rawBody and $formFields properties 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)
  • 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/library to 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

Read more

5.6.2

27 Jan 11:23

Choose a tag to compare

gemvc_let
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 uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Updated recordExceptionInApm() - Fallback code also uses setApm()
    • Changed from: $this->request->apm = $apm;
    • Changed to: $this->request->setApm($apm);
  • Location: src/core/Bootstrap.php

SwooleBootstrap.php

  • Updated initializeApm() - Now uses Request::setApm() method
    • Changed from: $this->request->apm = $this->apm;
    • Changed to: $this->request->setApm($this->apm);
  • Location: src/core/SwooleBootstrap.php

🎯 Benefits

  • Cleaner API - Explicit method call instead of property assignment
  • Better Type Safety - Method signature enforces ApmInterface type
  • 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


Upgrade Command:

composer update gemvc/library

Breaking 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 $responseCallbacks property 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 $rawBody and $formFields properties 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)
  • 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/library to 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


Upgrade Command:

composer update gemvc/library

Breaking 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 @property annotations for IDE autocompletion
    • Location: src/core/ApiService.php

🔧 Unified APM Architecture

  • ApmTracingTrait - Centralized APM logic
    • Provides unified startApmSpan, endApmSpan, traceApm, and recordApmException methods
    • Adopted by ApiService, Controller, and UniversalQueryExecuter
    • Ensures consistent span attributes and error handling
    • Location: src/core/Apm/ApmTracingTrait.php

🔄 Changes

...

Read more

5.6.1

26 Jan 15:02

Choose a tag to compare

gemvc_let
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 $responseCallbacks property 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 $rawBody and $formFields properties 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)
  • 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/library to 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


Upgrade Command:

composer update gemvc/library

Breaking 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 @property annotations for IDE autocompletion
    • Location: src/core/ApiService.php

🔧 Unified APM Architecture

  • ApmTracingTrait - Centralized APM logic
    • Provides unified startApmSpan, endApmSpan, traceApm, and recordApmException methods
    • Adopted by ApiService, Controller, and UniversalQueryExecuter
    • Ensures consistent span attributes and error handling
    • Location: src/core/Apm/ApmTracingTrait.php

🔄 Changes

Controller Layer Refactoring

  • Refactored Controller.php - Now uses ApmTracingTrait
    • Removed duplicate getApm() logic
    • Removed dead code (getControllerName)
    • Aliased legacy startTraceSpan methods for backward compatibility
    • Location: src/core/Controller.php

Database Layer Refactoring

  • Refactored UniversalQueryExecuter.php - Now uses ApmTracingTrait
    • Replaced manual APM environment checks with centralized logic
    • Context Propagation: Renamed internal property to $_request to avoid DB column conflicts while maintaining APM context
    • Removed redundant helper methods
    • Location: src/database/UniversalQueryExecuter.php

Type Safety & Compliance

  • PHPStan Level 9 - ApiService checks
    • Added strict instanceof Controller checks in magic getter
    • Added proper type hinting for all dynamic properties

🐛 Bug Fixes

  • Context Propagation Safety - Fixed potential conflict in UniversalQueryExecuter where $request property could clash with database columns named "request". using $_request ensures 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 .env variables (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 ApiService code 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 HttpClient for synchronous requests (Apache/Nginx)
    • Provides AsyncHttpClient for asynchronous requests (Apache/Nginx)
    • Provides SwooleHttpClient for native Swoole coroutines (optimized)
    • Automatic environment detection via WebserverDetector
    • Enhanced error handling with exception classification
    • Better retry mechanisms and SSL support

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

🔄 Changes

ApiCall Class Refactoring

  • Internal Implementation - Now uses Gemvc\Http\Client\HttpClient internally
    • 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 AsyncHttpClient or `SwooleHttpClie...
Read more