Releases: koldy/framework
3.4.3
3.4.2
Automatic HEAD request handling in HttpRoute
HttpRoute now automatically responds to HEAD requests by executing the corresponding GET handler and stripping the response body, returning only the headers. This means you no longer need to define separate head() methods for every route — it works out of the box.
For performance-sensitive routes, you can still override the default behaviour by implementing a dedicated head() method on your route class, giving you full control when needed.
3.4.1
This release introduces optional cache failover and brings the codebase up to PHP 8.5 compatibility. It is fully backwards compatible — no configuration changes are required to upgrade.
Highlights
Cache failover (on_fail)
Cache adapters can now declare a fallback chain via a new on_fail config block. When the primary adapter throws a connection-level error (e.g. Memcached times out, the host is unreachable, the cache directory is unwritable), the request is transparently routed to the next adapter in the chain for the rest of the request — and for a configurable cool-down window so subsequent calls don't keep hammering the broken backend.
Example:
'memcached' => [
'enabled' => true,
'adapter_class' => \Koldy\Cache\Adapter\Memcached::class,
'options' => [/* ... */],
'on_fail' => [
'next_adapter' => 'db', // name of another cache config entry
'ttl' => 30, // seconds to skip the primary after a failure
],
],
'db' => [
'enabled' => true,
'adapter_class' => \Koldy\Cache\Adapter\Db::class,
'options' => [/* ... */],
],Key points:
- Opt-in — adapters without
on_failbehave exactly as before. - Failure state is per-request; the primary is retried automatically once the TTL elapses.
- Only infrastructure errors trigger failover. Caller-side errors (oversized values, malformed keys) still surface as exceptions instead of silently switching adapters.
- Cycles in the chain (A → B → A) are detected and the call fails fast rather than recursing.
- A new
Cache::getRawAdapter()helper returns the unwrapped underlying adapter when you need adapter-specific APIs (e.g. the native\Memcachedinstance). - This feature is not yet documented on the official docs site — it will be after extended production testing. Use it at your own discretion until then.
New exception types
Cache exceptions are now split into two more specific subclasses, both extending Koldy\Cache\Exception (so existing catch blocks continue to work):
Koldy\Cache\ConnectionException— infrastructure failure (timeout, connection refused, server marked dead, unwritable filesystem). This is what the failover proxy listens for.Koldy\Cache\DataException— caller-side misuse (key too long, value too big, malformed data). These intentionally do not trigger failover.
Adapter improvements
- Memcached adapter: result codes from native
\Memcachedare now classified as connection vs. data vs. generic errors and mapped to the appropriate exception type.has(),deleteMulti(),increment(), anddecrement()now correctly raise on real infrastructure failures instead of swallowing them as cache misses. - Files adapter: filesystem failures (read errors on existing files,
mkdirfailures,file_put_contentsfailures) now report the actual underlying OS reason in the exception message and are raised asCacheConnectionExceptionso they can be handled by failover. Missing or corrupt files still resolve as cache misses, unchanged.
Upgrade notes
Drop-in upgrade — no config changes required, no API removals, no breaking signature changes.
3.4.0
Koldy Framework 3.4.0 — Release Notes
Released: 2026-04-24 · Previous release: 3.3.1 (2026-01-27)
New: HttpRoute routing system
A new HttpRoute class provides a class-based routing approach that complements the existing DefaultRoute system. Both systems are fully supported and DefaultRoute continues to work without modification.
- Class-based route definitions via HttpRoute
- Support for abstract class hierarchies (abstract classes are skipped during route resolution)
- __call() magic method is invoked on controller classes for the last URI segment, enabling catch-all handlers
- Root route edge case handled correctly
- URI segment counting fixed (uriSegment() returned a wrong count in 3.3.1)
- Internals refactored for correctness across next-segment handlers
Security hardening
All security changes are backwards-compatible unless noted.
- CSRF — Token comparison now uses hash_equals() to eliminate timing-based oracle attacks.
- Cookie defaults — secure and httpOnly now default to true; SameSite defaults to Lax. Pass explicit false to opt out.
▎ Note for local development over plain HTTP: you must now pass secure: false explicitly. - HTTP response splitting — setHeader() strips CR/LF characters from header names and values.
- Util::a() link helper — Now requires an explicit https?:// scheme; bare hostnames and javascript: URIs are rejected. The $target parameter is escaped with htmlspecialchars().
- Application key — Minimum key length raised to 16 characters (maximum remains 32). Keys shorter than 16 characters are rejected at boot time.
- Trusted proxy IP resolution — Forwarded headers (X-Forwarded-For, Client-IP, etc.) are now only trusted when REMOTE_ADDR matches a configured allowlist.
Configure via trusted_proxies in configs/application.php. IPv4 CIDR notation is supported (e.g. 10.0.0.0/8).
Response classes
- Json, Plain, and View now implement Stringable — responses can be cast to string without flushing, which is useful in tests and middleware.
- Json::fromString() and setContent() accept a pre-encoded JSON string directly, bypassing the internal array. This avoids the encode-decode-encode cycle that silently coerced empty objects to arrays.
- Json::flush() now respects the isAssociative flag when internal data is empty, so {} vs [] output is consistent.
PHP compatibility
- Minimum supported PHP version is 8.3.
- Cross-version compatibility fixes applied throughout.
Documentation
- llms/ directory added with documentation formatted for LLM consumption.
- New view.md templating guide with template fixture examples.
- request-response.md updated to reflect the fluent Data trait API for View.
- PHPUnit @runInSeparateProcess docblock annotations migrated to the modern #[RunInSeparateProcess] attribute.
3.3.0
- added isNotSuccess(), isRedirect(), isNotRedirect() in HTTP Response class to improve code readability
- other maintenance stuff
Full Changelog: 3.2.0...3.3.0
3.2.0
Overview
This release focuses on PHP 8.4 compatibility, enhanced testing capabilities, improved session handling, and better response management. The framework now includes PHPStan for static analysis and provides new utilities for developers.
🚀 New Features
Session Transport via HTTP Headers
- Session Header Transport: Sessions can now be transported via HTTP headers instead of cookies
- Configure with:
'transport' => ['type' => 'header', 'header_name' => 'X-SESSION']in session config - Provides more flexibility for API-based applications and mobile clients
New Utility Methods
- Util::pick() Method: New utility method that picks a value from input, validates it, and returns default or null
- Supports filtering with allowed values for enhanced input validation
Enhanced Testing Support
- HTTP Request Mocking: Added ability to easily mock incoming HTTP requests for unit testing
- Mock functionality works only in test mode for security
- Enables comprehensive testing of request handling logic
Response Output Management
- Response Output Capture: All HTTP responses now go through output buffering functions
- getOutput() Method: All response objects now implement
getOutput()method to read what was sent to client - Application::afterAnyResponse(): New callback system to perform operations after response output
- Automatic Output Registration: Every response flush is automatically registered as application output
🔧 Improvements
PHP 8.4 Compatibility
- PHPStan Integration: Added PHPStan for static analysis and code quality improvements
- E_STRICT Constant: Removed deprecated E_STRICT constant usage
- Session Configuration: Conditional setting of
sid_lengthandsid_bits_per_characterbased on PHP version
Logging Enhancements
- Improved Log Filtering: Log class now properly respects message type disablement even for "dump" requests
- Better control over what gets logged based on configuration
Documentation & Code Quality
- PHPDoc Improvements: Enhanced documentation throughout the codebase
- Updated README: Refreshed documentation and setup instructions
🐛 Bug Fixes
- Fixed session handling for different PHP versions
- Improved response handling consistency
- Better exception handling with proper after-response callbacks
📋 Technical Details
Breaking Changes
- None - this release maintains backward compatibility
Migration Notes
- No migration steps required for existing applications
- New session transport feature is opt-in via configuration
- PHPStan integration may reveal previously hidden code issues (recommended to address)
This release represents a significant step forward in modernizing the Koldy Framework while maintaining its ease of use and reliability. The PHP 8.4 compatibility ensures the framework stays current with the latest PHP developments, while the new testing and response management features provide developers with better tools for building robust applications.
3.1.1
- Added uuid validator
- Request::getAllParameters() now detects JSON request in HTTP body and returns parsed JSON as array as the parameters
- Ability to pass instance of Select to from() method so you can create a query on subselect
- Ability to parse multipart content and automatic params parsing on put, patch and delete when taking params with Request::getAllParameters()
- Added Util::randomUUIDv4() method for generating random UUID v4 strings
- Added UploadedFile::createFromFilesArray() static method, as a shorthand for creating new instances
- Replaced Memcached constants with integers so we don't rely on PHP version and the existance of predefined constants
- JSON response now prints {} in response body instead of [] when the data is empty
- Cache mechanisms will no longer throw CacheException on user callable functions. If there's an exception in user callable function, it will be thrown directly - not through CacheException any more
- Ability to define all configs in application config - there's no need to have separate config files any more, so all the config can be in one file only - the index.php
- Removed "final" definitions in db model so db models can be more customizable. It now provides ability to disallow magic __get and __set, while still being backcompatible
- Ability to use fetchAllGenerator() method on "raw" queries
- other fixes
3.1.0
This release is mostly about adding strict types everywhere. It should not affect your project, unless you have extended framework classes and override methods that now got the strict types. Main changes are:
- updated return types in all Db classes so they don't return themself, but return "static" instead which more accurate
- added ability to remove selected field from Select class after it was added (Select->removeField())
- added Util::now() that returns the current time in Y-m-d H:i:s.u format (includes milliseconds which aren't supported by default when using PHP's date() or gmdate() functions)
- few other small fixes
3.0.0
This is first version of the framework where new PHP 8.1 features are implemented. If you have used Koldy Framework before, then
read the change log so you can get familiar with the changes. All changes can be applied in your project with simple search&replace
rules and everything else is back compatible.
- Koldy\Version class is removed
- Route::getVar() is not using default value through an (2nd) argument any more
- Request class: get(), post(), put() and delete() methods are not accepting default (2nd) parameter any more
- Request class: get(), post(), put() and delete() methods are not accepting allowed values through an argument any more
- method \Koldy\Config->get() doesn't accept default value through an argument any more
- \Koldy\Config->getArrayItem() doesn't accept default value through an argument any more
- \Koldy\Db\Model::save() now returns null instead of -1 if DB was not queried
- CreatedAt trait - method setCreatedAtDateTime() method doesn't exist any more; setCreatedAt() now accepts string|DateTime instead and it doesn't return static/$this
- DeletedAt trait - methodsetDeletedAtDateTime() method doesn't exist any more; setDeletedAt() now accepts string|DateTime instead and it doesn't return static/$this
- UpdatedAt trait - methodsetUpdatedAtDateTime() method doesn't exist any more; setUpdatedAt() now accepts string|DateTime instead and it doesn't return static/$this
- \Koldy\Http\Request now accepts instances of CURLFile in params
- removed deprecated method \Koldy\Db\Insert::table()
- Pagination class is removed
- PHPMailer class is removed from the framework - instead, use koldy/phpmailer package
Check koldy.net docs for details about your project migration to this version.